diff --git a/build.gradle b/build.gradle
index 3f12ba4..94b4bb3 100644
--- a/build.gradle
+++ b/build.gradle
@@ -8,8 +8,11 @@ plugins {
sourceSets {
main {
java {
- srcDir 'src/main/java'
- srcDir 'src/teavm/java'
+ srcDirs(
+ "src/main/java",
+ "src/lwjgl/java",
+ "sp-server/src/ipc/java"
+ )
}
}
}
@@ -24,7 +27,7 @@ tasks.withType(JavaCompile) {
}
dependencies {
- //implementation fileTree(dir: './lwjgl-rundir/', include: '*.jar')
+ implementation fileTree(dir: './lwjgl-rundir/', include: '*.jar')
teavm(teavm.libs.jso)
teavm(teavm.libs.jsoApis)
diff --git a/sp-server/.classpath b/sp-server/.classpath
new file mode 100644
index 0000000..1619373
--- /dev/null
+++ b/sp-server/.classpath
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sp-server/.project b/sp-server/.project
new file mode 100644
index 0000000..66b372c
--- /dev/null
+++ b/sp-server/.project
@@ -0,0 +1,23 @@
+
+
+ eaglercraft-sp-server-service-pack-2
+ Project sp-server created by Buildship.
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
diff --git a/sp-server/build.gradle b/sp-server/build.gradle
new file mode 100644
index 0000000..5af9856
--- /dev/null
+++ b/sp-server/build.gradle
@@ -0,0 +1,46 @@
+import org.teavm.gradle.api.OptimizationLevel
+
+plugins {
+ id "java"
+ id "eclipse"
+ id "org.teavm" version "0.10.2"
+}
+
+sourceSets {
+ main {
+ java {
+ srcDirs(
+ "src/main/java",
+ "src/ipc/java"
+ )
+ }
+ }
+}
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ teavm(teavm.libs.jso)
+ teavm(teavm.libs.jsoApis)
+ compileOnly "org.teavm:teavm-core:0.10.2" // workaround for a few hacks
+}
+
+def folder = "../javascript"
+def name = "classes_server.js"
+
+teavm.js {
+ obfuscated = true
+ sourceMap = true
+ targetFileName = "../" + name
+ optimization = OptimizationLevel.AGGRESSIVE
+ outOfProcess = false
+ fastGlobalAnalysis = false
+ processMemory = 512
+ entryPointName = "main"
+ mainClass = "net.lax1dude.eaglercraft.sp.IntegratedServer"
+ outputDir = file(folder)
+ properties = [ "java.util.TimeZone.autodetect": "true" ]
+ debugInformation = false
+}
diff --git a/sp-server/gradle.properties b/sp-server/gradle.properties
new file mode 100644
index 0000000..a36eb1c
--- /dev/null
+++ b/sp-server/gradle.properties
@@ -0,0 +1 @@
+org.gradle.jvmargs=-Xmx2G -Xms2G
\ No newline at end of file
diff --git a/sp-server/gradle/wrapper/gradle-wrapper.jar b/sp-server/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..7f93135
Binary files /dev/null and b/sp-server/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/sp-server/gradle/wrapper/gradle-wrapper.properties b/sp-server/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..e6aba25
--- /dev/null
+++ b/sp-server/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,7 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-all.zip
+networkTimeout=10000
+validateDistributionUrl=true
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/sp-server/gradlew b/sp-server/gradlew
new file mode 100644
index 0000000..744e882
--- /dev/null
+++ b/sp-server/gradlew
@@ -0,0 +1,185 @@
+#!/usr/bin/env sh
+
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MSYS* | MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=`expr $i + 1`
+ done
+ case $i in
+ 0) set -- ;;
+ 1) set -- "$args0" ;;
+ 2) set -- "$args0" "$args1" ;;
+ 3) set -- "$args0" "$args1" "$args2" ;;
+ 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=`save "$@"`
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+exec "$JAVACMD" "$@"
diff --git a/sp-server/gradlew.bat b/sp-server/gradlew.bat
new file mode 100644
index 0000000..ac1b06f
--- /dev/null
+++ b/sp-server/gradlew.bat
@@ -0,0 +1,89 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/sp-server/settings.gradle b/sp-server/settings.gradle
new file mode 100644
index 0000000..8990fe8
--- /dev/null
+++ b/sp-server/settings.gradle
@@ -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-service-pack-2'
+
+// you eagler
\ No newline at end of file
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCInputStream.java b/sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCInputStream.java
similarity index 100%
rename from src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCInputStream.java
rename to sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCInputStream.java
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCOutputStream.java b/sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCOutputStream.java
similarity index 100%
rename from src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCOutputStream.java
rename to sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCOutputStream.java
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket00StartServer.java b/sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket00StartServer.java
similarity index 100%
rename from src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket00StartServer.java
rename to sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket00StartServer.java
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket01StopServer.java b/sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket01StopServer.java
similarity index 100%
rename from src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket01StopServer.java
rename to sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket01StopServer.java
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket02InitWorld.java b/sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket02InitWorld.java
similarity index 100%
rename from src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket02InitWorld.java
rename to sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket02InitWorld.java
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket03DeleteWorld.java b/sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket03DeleteWorld.java
similarity index 100%
rename from src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket03DeleteWorld.java
rename to sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket03DeleteWorld.java
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket04RenameWorld.java b/sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket04RenameWorld.java
similarity index 100%
rename from src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket04RenameWorld.java
rename to sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket04RenameWorld.java
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket05RequestData.java b/sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket05RequestData.java
similarity index 100%
rename from src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket05RequestData.java
rename to sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket05RequestData.java
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket06RenameWorldNBT.java b/sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket06RenameWorldNBT.java
similarity index 100%
rename from src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket06RenameWorldNBT.java
rename to sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket06RenameWorldNBT.java
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket07ImportWorld.java b/sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket07ImportWorld.java
similarity index 100%
rename from src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket07ImportWorld.java
rename to sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket07ImportWorld.java
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket09RequestResponse.java b/sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket09RequestResponse.java
similarity index 100%
rename from src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket09RequestResponse.java
rename to sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket09RequestResponse.java
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket0ASetWorldDifficulty.java b/sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket0ASetWorldDifficulty.java
similarity index 100%
rename from src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket0ASetWorldDifficulty.java
rename to sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket0ASetWorldDifficulty.java
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket0BPause.java b/sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket0BPause.java
similarity index 100%
rename from src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket0BPause.java
rename to sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket0BPause.java
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket0CPlayerChannel.java b/sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket0CPlayerChannel.java
similarity index 100%
rename from src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket0CPlayerChannel.java
rename to sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket0CPlayerChannel.java
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket0DProgressUpdate.java b/sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket0DProgressUpdate.java
similarity index 100%
rename from src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket0DProgressUpdate.java
rename to sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket0DProgressUpdate.java
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket0EListWorlds.java b/sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket0EListWorlds.java
similarity index 100%
rename from src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket0EListWorlds.java
rename to sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket0EListWorlds.java
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket0FListFiles.java b/sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket0FListFiles.java
similarity index 100%
rename from src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket0FListFiles.java
rename to sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket0FListFiles.java
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket10FileRead.java b/sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket10FileRead.java
similarity index 100%
rename from src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket10FileRead.java
rename to sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket10FileRead.java
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket12FileWrite.java b/sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket12FileWrite.java
similarity index 100%
rename from src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket12FileWrite.java
rename to sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket12FileWrite.java
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket13FileCopyMove.java b/sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket13FileCopyMove.java
similarity index 100%
rename from src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket13FileCopyMove.java
rename to sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket13FileCopyMove.java
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket14StringList.java b/sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket14StringList.java
similarity index 100%
rename from src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket14StringList.java
rename to sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket14StringList.java
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket15ThrowException.java b/sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket15ThrowException.java
similarity index 100%
rename from src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket15ThrowException.java
rename to sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket15ThrowException.java
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket16NBTList.java b/sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket16NBTList.java
similarity index 100%
rename from src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket16NBTList.java
rename to sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket16NBTList.java
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket17ConfigureLAN.java b/sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket17ConfigureLAN.java
similarity index 100%
rename from src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket17ConfigureLAN.java
rename to sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket17ConfigureLAN.java
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket18ClearPlayers.java b/sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket18ClearPlayers.java
similarity index 100%
rename from src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket18ClearPlayers.java
rename to sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacket18ClearPlayers.java
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacketBase.java b/sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacketBase.java
similarity index 100%
rename from src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacketBase.java
rename to sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacketBase.java
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacketFFProcessKeepAlive.java b/sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacketFFProcessKeepAlive.java
similarity index 100%
rename from src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacketFFProcessKeepAlive.java
rename to sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacketFFProcessKeepAlive.java
diff --git a/src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacketManager.java b/sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacketManager.java
similarity index 100%
rename from src/main/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacketManager.java
rename to sp-server/src/ipc/java/net/lax1dude/eaglercraft/sp/ipc/IPCPacketManager.java
diff --git a/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/BooleanResult.java b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/BooleanResult.java
new file mode 100644
index 0000000..576a6bf
--- /dev/null
+++ b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/BooleanResult.java
@@ -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;
+ }
+
+}
\ No newline at end of file
diff --git a/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/CRC32.java b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/CRC32.java
new file mode 100644
index 0000000..5277242
--- /dev/null
+++ b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/CRC32.java
@@ -0,0 +1,39 @@
+package net.lax1dude.eaglercraft.sp;
+
+import java.util.zip.Checksum;
+
+public class CRC32 implements Checksum {
+ private com.jcraft.jzlib.CRC32 impl = new com.jcraft.jzlib.CRC32();
+ long tbytes;
+
+ @Override
+ public long getValue() {
+ return impl.getValue();
+ }
+
+ @Override
+ public void reset() {
+ impl.reset();
+ tbytes = 0;
+ }
+
+ @Override
+ public void update(int val) {
+ impl.update(new byte[] { (byte) val }, 0, 1);
+ }
+
+ public void update(byte[] buf) {
+ update(buf, 0, buf.length);
+ }
+
+ @Override
+ public void update(byte[] buf, int off, int nbytes) {
+ // avoid int overflow, check null buf
+ if (off <= buf.length && nbytes >= 0 && off >= 0 && buf.length - off >= nbytes) {
+ impl.update(buf, off, nbytes);
+ tbytes += nbytes;
+ } else {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/EAGLogAgent.java b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/EAGLogAgent.java
new file mode 100644
index 0000000..f69a075
--- /dev/null
+++ b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/EAGLogAgent.java
@@ -0,0 +1,40 @@
+package net.lax1dude.eaglercraft.sp;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import net.minecraft.src.ILogAgent;
+
+public class EAGLogAgent implements ILogAgent {
+
+ private final Logger logger = Logger.getLogger("IntegratedServer");
+
+ public Logger getServerLogger() {
+ return this.logger;
+ }
+
+ public void func_98233_a(String par1Str) {
+ this.logger.log(Level.INFO, par1Str);
+ }
+
+ public void func_98236_b(String par1Str) {
+ this.logger.log(Level.WARNING, par1Str);
+ }
+
+ public void logWarningFormatted(String par1Str, Object... par2ArrayOfObj) {
+ this.logger.log(Level.WARNING, par1Str, par2ArrayOfObj);
+ }
+
+ public void logWarningException(String par1Str, Throwable par2Throwable) {
+ this.logger.log(Level.WARNING, par1Str, par2Throwable);
+ }
+
+ public void logSevere(String par1Str) {
+ this.logger.log(Level.SEVERE, par1Str);
+ }
+
+ public void logSevereException(String par1Str, Throwable par2Throwable) {
+ this.logger.log(Level.SEVERE, par1Str, par2Throwable);
+ }
+
+}
diff --git a/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/EAGMinecraftServer.java b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/EAGMinecraftServer.java
new file mode 100644
index 0000000..224cfef
--- /dev/null
+++ b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/EAGMinecraftServer.java
@@ -0,0 +1,158 @@
+package net.lax1dude.eaglercraft.sp;
+
+import java.io.IOException;
+
+import net.lax1dude.eaglercraft.sp.ipc.IPCPacket14StringList;
+import net.minecraft.server.MinecraftServer;
+import net.minecraft.src.EnumGameType;
+import net.minecraft.src.ILogAgent;
+import net.minecraft.src.WorldSettings;
+
+public class EAGMinecraftServer extends MinecraftServer {
+
+ protected int difficulty;
+ protected EnumGameType gamemode;
+ protected long lastTick;
+ protected WorkerListenThread listenThreadImpl;
+ protected WorldSettings newWorldSettings;
+ protected boolean paused;
+ private int tpsCounter = 0;
+ private int tpsMeasure = 0;
+ private long tpsTimer = 0l;
+
+ public EAGMinecraftServer(String world, String owner, WorldSettings currentWorldSettings) {
+ super(world);
+ this.setServerOwner(owner);
+ System.out.println("server owner: " + owner);
+ this.setConfigurationManager(new EAGPlayerList(this));
+ this.listenThreadImpl = new WorkerListenThread(this);
+ this.newWorldSettings = currentWorldSettings;
+ this.paused = false;
+ }
+
+ public void setBaseServerProperties(int difficulty, EnumGameType gamemode) {
+ this.difficulty = difficulty;
+ this.gamemode = gamemode;
+ this.setCanSpawnAnimals(true);
+ this.setCanSpawnNPCs(true);
+ this.setAllowPvp(true);
+ this.setAllowFlight(true);
+ }
+
+ public void mainLoop() {
+ long ctm = SysUtil.steadyTimeMillis();
+
+ long elapsed = ctm - tpsTimer;
+ if(elapsed >= 1000l) {
+ tpsTimer = ctm;
+ tpsMeasure = tpsCounter;
+ IntegratedServer.sendIPCPacket(new IPCPacket14StringList(IPCPacket14StringList.SERVER_TPS, getTPSAndChunkBuffer(tpsMeasure)));
+ tpsCounter = 0;
+ }
+
+ if(paused && this.playersOnline.size() <= 1) {
+ lastTick = ctm;
+ return;
+ }
+
+ long delta = ctm - lastTick;
+
+ if (delta > 2000L && ctm - this.timeOfLastWarning >= 15000L) {
+ this.getLogAgent().func_98236_b("Can\'t keep up! Did the system time change, or is the server overloaded? Skipping " + ((delta - 2000l) / 50l) + " ticks");
+ delta = 2000L;
+ this.timeOfLastWarning = ctm;
+ }
+
+ if (delta < 0L) {
+ this.getLogAgent().func_98236_b("Time ran backwards! Did the fucking system time change?");
+ delta = 0L;
+ }
+
+ if (this.worldServers[0].areAllPlayersAsleep()) {
+ this.tick();
+ ++tpsCounter;
+ lastTick = SysUtil.steadyTimeMillis();
+ } else {
+ if (delta > 50l) {
+ delta -= 50L;
+ lastTick += 50l;
+ this.tick();
+ ++tpsCounter;
+ }
+ }
+
+ }
+
+ public void setPaused(boolean p) {
+ paused = p;
+ if(!p) {
+ lastTick = SysUtil.steadyTimeMillis();
+ }
+ }
+
+ public boolean getPaused() {
+ return paused;
+ }
+
+ @Override
+ protected boolean startServer() throws IOException {
+ SkinsPlugin.reset();
+ VoiceChatPlugin.reset();
+ this.loadAllWorlds(folderName, 0l, newWorldSettings);
+ this.lastTick = SysUtil.steadyTimeMillis();
+ return true;
+ }
+
+ @Override
+ public void stopServer() {
+ super.stopServer();
+ SkinsPlugin.reset();
+ VoiceChatPlugin.reset();
+ }
+
+ @Override
+ public boolean canStructuresSpawn() {
+ return false;
+ }
+
+ @Override
+ public EnumGameType getGameType() {
+ return gamemode;
+ }
+
+ @Override
+ public int getDifficulty() {
+ return difficulty;
+ }
+
+ @Override
+ public boolean isHardcore() {
+ return false;
+ }
+
+ @Override
+ public boolean isDedicatedServer() {
+ return false;
+ }
+
+ @Override
+ public boolean isCommandBlockEnabled() {
+ return true;
+ }
+
+ @Override
+ public WorkerListenThread getNetworkThread() {
+ return listenThreadImpl;
+ }
+
+ @Override
+ public String shareToLAN(EnumGameType var1, boolean var2) {
+ return null;
+ }
+
+ @Override
+ public ILogAgent getLogAgent() {
+ return IntegratedServer.logger;
+ }
+
+}
diff --git a/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/EAGPlayerList.java b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/EAGPlayerList.java
new file mode 100644
index 0000000..90ddd75
--- /dev/null
+++ b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/EAGPlayerList.java
@@ -0,0 +1,28 @@
+package net.lax1dude.eaglercraft.sp;
+
+import net.minecraft.server.MinecraftServer;
+import net.minecraft.src.EntityPlayerMP;
+import net.minecraft.src.NBTTagCompound;
+import net.minecraft.src.ServerConfigurationManager;
+
+public class EAGPlayerList extends ServerConfigurationManager {
+
+ private NBTTagCompound hostPlayerNBT = null;
+
+ public EAGPlayerList(MinecraftServer par1MinecraftServer) {
+ super(par1MinecraftServer);
+ this.viewDistance = 4;
+ }
+
+ protected void writePlayerData(EntityPlayerMP par1EntityPlayerMP) {
+ if (par1EntityPlayerMP.getCommandSenderName().equals(this.getServerInstance().getServerOwner())) {
+ this.hostPlayerNBT = new NBTTagCompound();
+ par1EntityPlayerMP.writeToNBT(hostPlayerNBT);
+ }
+ super.writePlayerData(par1EntityPlayerMP);
+ }
+
+ public NBTTagCompound getHostPlayerData() {
+ return this.hostPlayerNBT;
+ }
+}
diff --git a/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/EPK2Compiler.java b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/EPK2Compiler.java
new file mode 100644
index 0000000..623b6ce
--- /dev/null
+++ b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/EPK2Compiler.java
@@ -0,0 +1,151 @@
+package net.lax1dude.eaglercraft.sp;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import com.jcraft.jzlib.CRC32;
+
+public class EPK2Compiler {
+
+ private final ByteArrayOutputStream os;
+ private final CRC32 checkSum = new CRC32();
+ private int lengthIntegerOffset = 0;
+ private int totalFileCount = 0;
+
+ public EPK2Compiler(String name, String owner, String type) {
+ os = new ByteArrayOutputStream(0x200000);
+ try {
+
+ os.write(new byte[]{(byte)69,(byte)65,(byte)71,(byte)80,(byte)75,(byte)71,(byte)36,(byte)36}); // EAGPKG$$
+ os.write(new byte[]{(byte)6,(byte)118,(byte)101,(byte)114,(byte)50,(byte)46,(byte)48}); // 6 + ver2.0
+ Date d = new Date();
+
+ byte[] filename = (name + ".epk").getBytes(StandardCharsets.UTF_8);
+ os.write(filename.length);
+ os.write(filename);
+
+ byte[] comment = ("\n\n # Eagler EPK v2.0 (c) " + (new SimpleDateFormat("yyyy")).format(d) + " " +
+ owner + "\n # export: on " + (new SimpleDateFormat("MM/dd/yyyy")).format(d) + " at " +
+ (new SimpleDateFormat("hh:mm:ss aa")).format(d) + "\n\n # world name: " + name + "\n\n")
+ .getBytes(StandardCharsets.UTF_8);
+
+ os.write((comment.length >> 8) & 255);
+ os.write(comment.length & 255);
+ os.write(comment);
+
+ writeLong(d.getTime(), os);
+
+ lengthIntegerOffset = os.size();
+ os.write(new byte[]{(byte)255,(byte)255,(byte)255,(byte)255}); // this will be replaced with the file count
+
+ os.write('0'); // compression type: none
+
+ os.write(new byte[]{(byte)72,(byte)69,(byte)65,(byte)68}); // HEAD
+ os.write(new byte[]{(byte)9,(byte)102,(byte)105,(byte)108,(byte)101,(byte)45,(byte)116,(byte)121,
+ (byte)112,(byte)101}); // 9 + file-type
+
+ byte[] typeBytes = type.getBytes(StandardCharsets.UTF_8);
+ writeInt(typeBytes.length, os);
+ os.write(typeBytes); // write type
+ os.write('>');
+
+ ++totalFileCount;
+
+ os.write(new byte[]{(byte)72,(byte)69,(byte)65,(byte)68}); // HEAD
+ os.write(new byte[]{(byte)10,(byte)119,(byte)111,(byte)114,(byte)108,(byte)100,(byte)45,(byte)110,
+ (byte)97,(byte)109,(byte)101}); // 10 + world-name
+
+ byte[] nameBytes = name.getBytes(StandardCharsets.UTF_8);
+ writeInt(nameBytes.length, os);
+ os.write(nameBytes); // write name
+ os.write('>');
+
+ ++totalFileCount;
+
+ os.write(new byte[]{(byte)72,(byte)69,(byte)65,(byte)68}); // HEAD
+ os.write(new byte[]{(byte)11,(byte)119,(byte)111,(byte)114,(byte)108,(byte)100,(byte)45,(byte)111,
+ (byte)119,(byte)110,(byte)101,(byte)114}); // 11 + world-owner
+
+ byte[] ownerBytes = owner.getBytes(StandardCharsets.UTF_8);
+ writeInt(ownerBytes.length, os);
+ os.write(ownerBytes); // write owner
+ os.write('>');
+
+ ++totalFileCount;
+
+ }catch(IOException ex) {
+ throw new RuntimeException("This happened somehow", ex);
+ }
+ }
+
+ public void append(String name, byte[] dat) {
+ try {
+
+ checkSum.reset();
+ checkSum.update(dat, 0, dat.length);
+ long sum = checkSum.getValue();
+
+ os.write(new byte[]{(byte)70,(byte)73,(byte)76,(byte)69}); // FILE
+
+ byte[] nameBytes = name.getBytes(StandardCharsets.UTF_8);
+ os.write(nameBytes.length);
+ os.write(nameBytes);
+
+ writeInt(dat.length + 5, os);
+ writeInt((int)sum, os);
+
+ os.write(dat);
+
+ os.write(':');
+ os.write('>');
+
+ ++totalFileCount;
+
+ }catch(IOException ex) {
+ throw new RuntimeException("This happened somehow", ex);
+ }
+ }
+
+ public byte[] complete() {
+ try {
+
+ os.write(new byte[]{(byte)69,(byte)78,(byte)68,(byte)36}); // END$
+ os.write(new byte[]{(byte)58,(byte)58,(byte)58,(byte)89,(byte)69,(byte)69,(byte)58,(byte)62}); // :::YEE:>
+
+ byte[] ret = os.toByteArray();
+
+ ret[lengthIntegerOffset] = (byte)((totalFileCount >> 24) & 0xFF);
+ ret[lengthIntegerOffset + 1] = (byte)((totalFileCount >> 16) & 0xFF);
+ ret[lengthIntegerOffset + 2] = (byte)((totalFileCount >> 8) & 0xFF);
+ ret[lengthIntegerOffset + 3] = (byte)(totalFileCount & 0xFF);
+
+ return ret;
+
+ }catch(IOException ex) {
+ throw new RuntimeException("This happened somehow", ex);
+ }
+ }
+
+ public static void writeInt(int i, OutputStream os) throws IOException {
+ os.write((i >> 24) & 0xFF);
+ os.write((i >> 16) & 0xFF);
+ os.write((i >> 8) & 0xFF);
+ os.write(i & 0xFF);
+ }
+
+ public static void writeLong(long i, OutputStream os) throws IOException {
+ os.write((int)((i >> 56) & 0xFF));
+ os.write((int)((i >> 48) & 0xFF));
+ os.write((int)((i >> 40) & 0xFF));
+ os.write((int)((i >> 32) & 0xFF));
+ os.write((int)((i >> 24) & 0xFF));
+ os.write((int)((i >> 16) & 0xFF));
+ os.write((int)((i >> 8) & 0xFF));
+ os.write((int)(i & 0xFF));
+ }
+
+}
diff --git a/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/EPKDecompiler.java b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/EPKDecompiler.java
new file mode 100644
index 0000000..58986fb
--- /dev/null
+++ b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/EPKDecompiler.java
@@ -0,0 +1,217 @@
+package net.lax1dude.eaglercraft.sp;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+
+import com.jcraft.jzlib.CRC32;
+import com.jcraft.jzlib.GZIPInputStream;
+import com.jcraft.jzlib.InflaterInputStream;
+
+public class EPKDecompiler {
+
+ public static class FileEntry {
+ public final String type;
+ public final String name;
+ public final byte[] data;
+ protected FileEntry(String type, String name, byte[] data) {
+ this.type = type;
+ this.name = name;
+ this.data = data;
+ }
+ }
+
+ private ByteArrayInputStream in2;
+ private DataInputStream in;
+ private InputStream zis;
+ private SHA1Digest dg;
+ private CRC32 crc32;
+ private int numFiles;
+ private boolean isFinished = false;
+ private boolean isOldFormat = false;
+
+ public EPKDecompiler(byte[] data) throws IOException {
+ in2 = new ByteArrayInputStream(data);
+
+ byte[] header = new byte[8];
+ in2.read(header);
+
+ if(Arrays.equals(header, new byte[]{(byte)69,(byte)65,(byte)71,(byte)80,(byte)75,(byte)71,(byte)36,(byte)36})) {
+ byte[] endCode = new byte[] { (byte)':', (byte)':', (byte)':', (byte)'Y',
+ (byte)'E', (byte)'E', (byte)':', (byte)'>' };
+ for(int i = 0; i < 8; ++i) {
+ if(data[data.length - 8 + i] != endCode[i]) {
+ throw new IOException("EPK file is missing EOF code (:::YEE:>)");
+ }
+ }
+ in2 = new ByteArrayInputStream(data, 8, data.length - 16);
+ initNew();
+ }else if(Arrays.equals(header, new byte[]{(byte)69,(byte)65,(byte)71,(byte)80,(byte)75,(byte)71,(byte)33,(byte)33})) {
+ initOld();
+ }
+
+ }
+
+ public boolean isOld() {
+ return isOldFormat;
+ }
+
+ public FileEntry readFile() throws IOException {
+ if(!isOldFormat) {
+ return readFileNew();
+ }else {
+ return readFileOld();
+ }
+ }
+
+ private void initNew() throws IOException {
+ InputStream is = in2;
+
+ String vers = readASCII(is);
+ if(!vers.startsWith("ver2.")) {
+ throw new IOException("Unknown or invalid EPK version: " + vers);
+ }
+
+ is.skip(is.read()); // skip filename
+ is.skip(loadShort(is)); // skip comment
+ is.skip(8); // skip millis date
+
+ numFiles = loadInt(is);
+
+ char compressionType = (char)is.read();
+
+ switch(compressionType) {
+ case 'G':
+ zis = new GZIPInputStream(is);
+ break;
+ case 'Z':
+ zis = new InflaterInputStream(is);
+ break;
+ case '0':
+ zis = is;
+ break;
+ default:
+ throw new IOException("Invalid or unsupported EPK compression: " + compressionType);
+ }
+
+ crc32 = new CRC32();
+
+ }
+
+ private FileEntry readFileNew() throws IOException {
+ if(isFinished) {
+ return null;
+ }
+
+ byte[] typeBytes = new byte[4];
+ zis.read(typeBytes);
+ String type = readASCII(typeBytes);
+
+ if(numFiles == 0) {
+ if(!"END$".equals(type)) {
+ throw new IOException("EPK file is missing END code (END$)");
+ }
+ isFinished = true;
+ return null;
+ }else {
+ if("END$".equals(type)) {
+ throw new IOException("Unexpected END when there are still " + numFiles + " files remaining");
+ }else {
+ String name = readASCII(zis);
+ int len = loadInt(zis);
+ byte[] data;
+
+ if("FILE".equals(type)) {
+ if(len < 5) {
+ throw new IOException("File '" + name + "' is incomplete (no crc)");
+ }
+
+ int loadedCrc = loadInt(zis);
+
+ data = new byte[len - 5];
+ zis.read(data);
+
+ crc32.reset();
+ crc32.update(data, 0, data.length);
+ if((int)crc32.getValue() != loadedCrc) {
+ throw new IOException("File '" + name + "' has an invalid checksum");
+ }
+
+ if(zis.read() != ':') {
+ throw new IOException("File '" + name + "' is incomplete");
+ }
+ }else {
+ data = new byte[len];
+ zis.read(data);
+ }
+
+ if(zis.read() != '>') {
+ throw new IOException("Object '" + name + "' is incomplete");
+ }
+
+ --numFiles;
+ return new FileEntry(type, name, data);
+ }
+ }
+ }
+
+ private static final int loadShort(InputStream is) throws IOException {
+ return (is.read() << 8) | is.read();
+ }
+
+ private static final int loadInt(InputStream is) throws IOException {
+ return (is.read() << 24) | (is.read() << 16) | (is.read() << 8) | is.read();
+ }
+
+ public static final String readASCII(byte[] bytesIn) throws IOException {
+ char[] charIn = new char[bytesIn.length];
+ for(int i = 0; i < bytesIn.length; ++i) {
+ charIn[i] = (char)((int)bytesIn[i] & 0xFF);
+ }
+ return new String(charIn);
+ }
+
+ private static final String readASCII(InputStream bytesIn) throws IOException {
+ int len = bytesIn.read();
+ char[] charIn = new char[len];
+ for(int i = 0; i < len; ++i) {
+ charIn[i] = (char)(bytesIn.read() & 0xFF);
+ }
+ return new String(charIn);
+ }
+
+ private void initOld() throws IOException {
+ isOldFormat = true;
+ dg = new SHA1Digest();
+ in = new DataInputStream(in2);
+ in.readUTF();
+ in = new DataInputStream(new InflaterInputStream(in2));
+ }
+
+ private FileEntry readFileOld() throws IOException {
+ if(isFinished) {
+ return null;
+ }
+ String s = in.readUTF();
+ if(s.equals(" end")) {
+ isFinished = true;
+ return null;
+ }else if(!s.equals("")) {
+ throw new IOException("invalid epk file");
+ }
+ String path = in.readUTF();
+ byte[] digest = new byte[20];
+ byte[] digest2 = new byte[20];
+ in.read(digest);
+ int len = in.readInt();
+ byte[] file = new byte[len];
+ in.read(file);
+ dg.update(file, 0, len); dg.doFinal(digest2, 0);
+ if(!Arrays.equals(digest, digest2)) throw new IOException("invalid file hash for "+path);
+ if(!"".equals(in.readUTF())) throw new IOException("invalid epk file");
+ return new FileEntry("FILE", path, file);
+ }
+
+}
diff --git a/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/EaglerUUID.java b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/EaglerUUID.java
new file mode 100644
index 0000000..b5b1a67
--- /dev/null
+++ b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/EaglerUUID.java
@@ -0,0 +1,189 @@
+package net.lax1dude.eaglercraft.sp;
+
+public class EaglerUUID {
+
+ private final long mostSigBits;
+ private final long leastSigBits;
+
+ private EaglerUUID(byte[] data) {
+ long msb = 0;
+ long lsb = 0;
+ assert data.length == 16 : "data must be 16 bytes in length";
+ for (int i=0; i<8; i++)
+ msb = (msb << 8) | (data[i] & 0xff);
+ for (int i=8; i<16; i++)
+ lsb = (lsb << 8) | (data[i] & 0xff);
+ this.mostSigBits = msb;
+ this.leastSigBits = lsb;
+ }
+
+ public EaglerUUID(long mostSigBits, long leastSigBits) {
+ this.mostSigBits = mostSigBits;
+ this.leastSigBits = leastSigBits;
+ }
+
+ private static final EaglercraftRandom random = new EaglercraftRandom();
+
+ public static EaglerUUID randomUUID() {
+ byte[] randomBytes = new byte[16];
+ random.nextBytes(randomBytes);
+ randomBytes[6] &= 0x0f; /* clear version */
+ randomBytes[6] |= 0x40; /* set to version 4 */
+ randomBytes[8] &= 0x3f; /* clear variant */
+ randomBytes[8] |= 0x80; /* set to IETF variant */
+ return new EaglerUUID(randomBytes);
+ }
+
+ private static final MD5Digest yee = new MD5Digest();
+
+ public static EaglerUUID nameUUIDFromBytes(byte[] name) {
+ yee.update(name, 0, name.length);
+ byte[] md5Bytes = new byte[16];
+ yee.doFinal(md5Bytes, 0);
+ md5Bytes[6] &= 0x0f; /* clear version */
+ md5Bytes[6] |= 0x30; /* set to version 3 */
+ md5Bytes[8] &= 0x3f; /* clear variant */
+ md5Bytes[8] |= 0x80; /* set to IETF variant */
+ return new EaglerUUID(md5Bytes);
+ }
+
+ public static EaglerUUID fromString(String name) {
+ String[] components = name.split("-");
+ if (components.length != 5)
+ throw new IllegalArgumentException("Invalid UUID string: "+name);
+ for (int i=0; i<5; i++)
+ components[i] = "0x"+components[i];
+
+ long mostSigBits = Long.decode(components[0]).longValue();
+ mostSigBits <<= 16;
+ mostSigBits |= Long.decode(components[1]).longValue();
+ mostSigBits <<= 16;
+ mostSigBits |= Long.decode(components[2]).longValue();
+
+ long leastSigBits = Long.decode(components[3]).longValue();
+ leastSigBits <<= 48;
+ leastSigBits |= Long.decode(components[4]).longValue();
+
+ return new EaglerUUID(mostSigBits, leastSigBits);
+ }
+
+ public long getLeastSignificantBits() {
+ return leastSigBits;
+ }
+
+ public long getMostSignificantBits() {
+ return mostSigBits;
+ }
+
+ /**
+ * The version number associated with this {@code UUID}. The version
+ * number describes how this {@code UUID} was generated.
+ *
+ * The version number has the following meaning:
+ *
+ * - 1 Time-based UUID
+ *
- 2 DCE security UUID
+ *
- 3 Name-based UUID
+ *
- 4 Randomly generated UUID
+ *
+ *
+ * @return The version number of this {@code UUID}
+ */
+ public int version() {
+ // Version is bits masked by 0x000000000000F000 in MS long
+ return (int)((mostSigBits >> 12) & 0x0f);
+ }
+
+ /**
+ * The variant number associated with this {@code UUID}. The variant
+ * number describes the layout of the {@code UUID}.
+ *
+ * The variant number has the following meaning:
+ *
+ * - 0 Reserved for NCS backward compatibility
+ *
- 2 IETF RFC 4122
+ * (Leach-Salz), used by this class
+ *
- 6 Reserved, Microsoft Corporation backward compatibility
+ *
- 7 Reserved for future definition
+ *
+ *
+ * @return The variant number of this {@code UUID}
+ */
+ public int variant() {
+ // This field is composed of a varying number of bits.
+ // 0 - - Reserved for NCS backward compatibility
+ // 1 0 - The IETF aka Leach-Salz variant (used by this class)
+ // 1 1 0 Reserved, Microsoft backward compatibility
+ // 1 1 1 Reserved for future definition.
+ return (int) ((leastSigBits >>> (64 - (leastSigBits >>> 62)))
+ & (leastSigBits >> 63));
+ }
+
+ public long timestamp() {
+ if (version() != 1) {
+ throw new UnsupportedOperationException("Not a time-based UUID");
+ }
+
+ return (mostSigBits & 0x0FFFL) << 48
+ | ((mostSigBits >> 16) & 0x0FFFFL) << 32
+ | mostSigBits >>> 32;
+ }
+
+ /**
+ * The clock sequence value associated with this UUID.
+ *
+ * The 14 bit clock sequence value is constructed from the clock
+ * sequence field of this UUID. The clock sequence field is used to
+ * guarantee temporal uniqueness in a time-based UUID.
+ *
+ *
The {@code clockSequence} value is only meaningful in a time-based
+ * UUID, which has version type 1. If this UUID is not a time-based UUID
+ * then this method throws UnsupportedOperationException.
+ *
+ * @return The clock sequence of this {@code UUID}
+ *
+ * @throws UnsupportedOperationException
+ * If this UUID is not a version 1 UUID
+ */
+ public int clockSequence() {
+ if (version() != 1) {
+ throw new UnsupportedOperationException("Not a time-based UUID");
+ }
+
+ return (int)((leastSigBits & 0x3FFF000000000000L) >>> 48);
+ }
+
+ public String toString() {
+ return (digits(mostSigBits >> 32, 8) + "-" +
+ digits(mostSigBits >> 16, 4) + "-" +
+ digits(mostSigBits, 4) + "-" +
+ digits(leastSigBits >> 48, 4) + "-" +
+ digits(leastSigBits, 12));
+ }
+
+ private static String digits(long val, int digits) {
+ long hi = 1L << (digits * 4);
+ return Long.toHexString(hi | (val & (hi - 1))).substring(1);
+ }
+
+ public int hashCode() {
+ long hilo = mostSigBits ^ leastSigBits;
+ return ((int)(hilo >> 32)) ^ (int) hilo;
+ }
+
+ public boolean equals(Object obj) {
+ if ((null == obj) || !(obj instanceof EaglerUUID))
+ return false;
+ EaglerUUID id = (EaglerUUID)obj;
+ return (mostSigBits == id.mostSigBits &&
+ leastSigBits == id.leastSigBits);
+ }
+
+ public int compareTo(EaglerUUID val) {
+ return (this.mostSigBits < val.mostSigBits ? -1 :
+ (this.mostSigBits > val.mostSigBits ? 1 :
+ (this.leastSigBits < val.leastSigBits ? -1 :
+ (this.leastSigBits > val.leastSigBits ? 1 :
+ 0))));
+ }
+}
diff --git a/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/EaglercraftRandom.java b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/EaglercraftRandom.java
new file mode 100644
index 0000000..52c0ab0
--- /dev/null
+++ b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/EaglercraftRandom.java
@@ -0,0 +1,84 @@
+package net.lax1dude.eaglercraft.sp;
+
+public class EaglercraftRandom {
+
+ private static final long multiplier = 0x5DEECE66DL;
+ private static final long addend = 0xBL;
+ private static final long mask = (1L << 48) - 1;
+
+ private static final double DOUBLE_UNIT = 0x1.0p-53;
+ private long seed = 69;
+
+ public EaglercraftRandom() {
+ this(System.nanoTime());
+ }
+
+ public EaglercraftRandom(long seed) {
+ setSeed(seed);
+ }
+
+ public void setSeed(long yeed) {
+ seed = yeed;
+ }
+
+ protected int next(int bits) {
+ seed = (seed * multiplier + addend) & mask;
+ return (int)(seed >>> (48 - bits));
+ }
+
+ public void nextBytes(byte[] bytes) {
+ for (int i = 0, len = bytes.length; i < len; )
+ for (int rnd = nextInt(),
+ n = Math.min(len - i, Integer.SIZE/Byte.SIZE);
+ n-- > 0; rnd >>= Byte.SIZE)
+ bytes[i++] = (byte)rnd;
+ }
+ public int nextInt() {
+ return next(32);
+ }
+ public int nextInt(int bound) {
+ int r = next(31);
+ int m = bound - 1;
+ if ((bound & m) == 0) // i.e., bound is a power of 2
+ r = (int)((bound * (long)r) >> 31);
+ else {
+ for (int u = r;
+ u - (r = u % bound) + m < 0;
+ u = next(31))
+ ;
+ }
+ return r;
+ }
+ public long nextLong() {
+ return ((long)(next(32)) << 32) + next(32);
+ }
+ public boolean nextBoolean() {
+ return next(1) != 0;
+ }
+ public float nextFloat() {
+ return next(24) / ((float)(1 << 24));
+ }
+ public double nextDouble() {
+ return (((long)(next(26)) << 27) + next(27)) * DOUBLE_UNIT;
+ }
+ private double nextNextGaussian;
+ private boolean haveNextNextGaussian = false;
+ public double nextGaussian() {
+ // See Knuth, ACP, Section 3.4.1 Algorithm C.
+ if (haveNextNextGaussian) {
+ haveNextNextGaussian = false;
+ return nextNextGaussian;
+ } else {
+ double v1, v2, s;
+ do {
+ v1 = 2 * nextDouble() - 1; // between -1 and 1
+ v2 = 2 * nextDouble() - 1; // between -1 and 1
+ s = v1 * v1 + v2 * v2;
+ } while (s >= 1 || s == 0);
+ double multiplier = StrictMath.sqrt(-2 * StrictMath.log(s)/s);
+ nextNextGaussian = v2 * multiplier;
+ haveNextNextGaussian = true;
+ return v1 * multiplier;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/ExpiringSet.java b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/ExpiringSet.java
new file mode 100644
index 0000000..64ed0cf
--- /dev/null
+++ b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/ExpiringSet.java
@@ -0,0 +1,74 @@
+package net.lax1dude.eaglercraft.sp;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+
+// note that there's a few things not implemented, but I don't care.
+
+public class ExpiringSet extends HashSet {
+ private final long expiration;
+ private final ExpiringEvent event;
+
+ private final Map timestamps = new HashMap<>();
+
+ public ExpiringSet(long expiration) {
+ this.expiration = expiration;
+ this.event = null;
+ }
+
+ public ExpiringSet(long expiration, ExpiringEvent event) {
+ this.expiration = expiration;
+ this.event = event;
+ }
+
+ public interface ExpiringEvent {
+ void onExpiration(T item);
+ }
+
+ public void checkForExpirations() {
+ Iterator iterator = this.timestamps.keySet().iterator();
+ long now = SysUtil.steadyTimeMillis();
+ while (iterator.hasNext()) {
+ T element = iterator.next();
+ if (super.contains(element)) {
+ if (this.timestamps.get(element) + this.expiration < now) {
+ if (this.event != null)
+ this.event.onExpiration(element);
+ iterator.remove();
+ super.remove(element);
+ }
+ } else {
+ iterator.remove();
+ super.remove(element);
+ }
+ }
+ }
+
+ public boolean add(T o) {
+ checkForExpirations();
+ boolean success = super.add(o);
+ if (success)
+ timestamps.put(o, SysUtil.steadyTimeMillis());
+ return success;
+ }
+
+ public boolean remove(Object o) {
+ checkForExpirations();
+ boolean success = super.remove(o);
+ if (success)
+ timestamps.remove(o);
+ return success;
+ }
+
+ public void clear() {
+ this.timestamps.clear();
+ super.clear();
+ }
+
+ public boolean contains(Object o) {
+ checkForExpirations();
+ return super.contains(o);
+ }
+}
\ No newline at end of file
diff --git a/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/GeneralDigest.java b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/GeneralDigest.java
new file mode 100644
index 0000000..7229c20
--- /dev/null
+++ b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/GeneralDigest.java
@@ -0,0 +1,124 @@
+package net.lax1dude.eaglercraft.sp;
+
+/**
+ * base implementation of MD4 family style digest as outlined in
+ * "Handbook of Applied Cryptography", pages 344 - 347.
+ */
+public abstract class GeneralDigest {
+ private byte[] xBuf;
+ private int xBufOff;
+
+ private long byteCount;
+
+ /**
+ * Standard constructor
+ */
+ protected GeneralDigest()
+ {
+ xBuf = new byte[4];
+ xBufOff = 0;
+ }
+
+ /**
+ * Copy constructor. We are using copy constructors in place
+ * of the Object.clone() interface as this interface is not
+ * supported by J2ME.
+ */
+ protected GeneralDigest(GeneralDigest t)
+ {
+ xBuf = new byte[t.xBuf.length];
+ System.arraycopy(t.xBuf, 0, xBuf, 0, t.xBuf.length);
+
+ xBufOff = t.xBufOff;
+ byteCount = t.byteCount;
+ }
+
+ public void update(
+ byte in)
+ {
+ xBuf[xBufOff++] = in;
+
+ if (xBufOff == xBuf.length)
+ {
+ processWord(xBuf, 0);
+ xBufOff = 0;
+ }
+
+ byteCount++;
+ }
+
+ public void update(
+ byte[] in,
+ int inOff,
+ int len)
+ {
+ //
+ // fill the current word
+ //
+ while ((xBufOff != 0) && (len > 0))
+ {
+ update(in[inOff]);
+
+ inOff++;
+ len--;
+ }
+
+ //
+ // process whole words.
+ //
+ while (len > xBuf.length)
+ {
+ processWord(in, inOff);
+
+ inOff += xBuf.length;
+ len -= xBuf.length;
+ byteCount += xBuf.length;
+ }
+
+ //
+ // load in the remainder.
+ //
+ while (len > 0)
+ {
+ update(in[inOff]);
+
+ inOff++;
+ len--;
+ }
+ }
+
+ public void finish()
+ {
+ long bitLength = (byteCount << 3);
+
+ //
+ // add the pad bytes.
+ //
+ update((byte)128);
+
+ while (xBufOff != 0)
+ {
+ update((byte)0);
+ }
+
+ processLength(bitLength);
+
+ processBlock();
+ }
+
+ public void reset()
+ {
+ byteCount = 0;
+
+ xBufOff = 0;
+ for ( int i = 0; i < xBuf.length; i++ ) {
+ xBuf[i] = 0;
+ }
+ }
+
+ protected abstract void processWord(byte[] in, int inOff);
+
+ protected abstract void processLength(long bitLength);
+
+ protected abstract void processBlock();
+}
diff --git a/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/IntegratedServer.java b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/IntegratedServer.java
new file mode 100644
index 0000000..57c2a16
--- /dev/null
+++ b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/IntegratedServer.java
@@ -0,0 +1,555 @@
+package net.lax1dude.eaglercraft.sp;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.teavm.jso.JSBody;
+import org.teavm.jso.JSFunctor;
+import org.teavm.jso.JSObject;
+import org.teavm.jso.typedarrays.ArrayBuffer;
+
+import net.lax1dude.eaglercraft.sp.ipc.*;
+import net.minecraft.src.AchievementList;
+import net.minecraft.src.AchievementMap;
+import net.minecraft.src.CompressedStreamTools;
+import net.minecraft.src.EnumGameType;
+import net.minecraft.src.ILogAgent;
+import net.minecraft.src.NBTTagCompound;
+import net.minecraft.src.StringTranslate;
+import net.minecraft.src.WorldSettings;
+import net.minecraft.src.WorldType;
+
+public class IntegratedServer {
+
+ private static final LinkedList 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;
+ }
+ }
+
+ private static EAGMinecraftServer currentProcess = null;
+ private static WorldSettings newWorldSettings = null;
+
+ public static EAGMinecraftServer getServer() {
+ return currentProcess;
+ }
+
+ public static final ILogAgent logger = new EAGLogAgent();
+
+ @JSFunctor
+ private static interface WorkerBinaryPacketHandler extends JSObject {
+ public void onMessage(String channel, ArrayBuffer buf);
+ }
+
+ private static class WorkerBinaryPacketHandlerImpl implements WorkerBinaryPacketHandler {
+
+ public 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;
+ }
+
+ synchronized(messageQueue) {
+ messageQueue.add(new PKT(channel, TeaVMUtils.wrapByteArrayBuffer(buf)));
+ }
+ }
+
+ }
+
+ private static void tryStopServer() {
+ if(currentProcess != null) {
+ try {
+ currentProcess.stopServer();
+ }catch(Throwable t) {
+ System.err.println("Failed to stop server!");
+ throwExceptionToClient("Failed to stop server!", t);
+ }
+ currentProcess = null;
+ }
+ }
+
+ public static void updateStatusString(String stat, float prog) {
+ sendIPCPacket(new IPCPacket0DProgressUpdate(stat, prog));
+ }
+
+ private static boolean isServerStopped() {
+ return currentProcess == null || !currentProcess.isServerRunning();
+ }
+
+ public static void throwExceptionToClient(String msg, Throwable t) {
+ String str = t.toString();
+ System.err.println("Exception was raised to client: " + str);
+ t.printStackTrace();
+ List arr = new LinkedList<>();
+ for(StackTraceElement e : t.getStackTrace()) {
+ String st = e.toString();
+ arr.add(st);
+ }
+ sendIPCPacket(new IPCPacket15ThrowException(str, arr));
+ }
+
+ public static void sendTaskFailed() {
+ sendIPCPacket(new IPCPacketFFProcessKeepAlive(IPCPacketFFProcessKeepAlive.FAILURE));
+ }
+
+ private static void processAsyncMessageQueue() {
+ ArrayList cur;
+ synchronized(messageQueue) {
+ if(messageQueue.size() <= 0) {
+ return;
+ }
+ cur = new ArrayList(messageQueue);
+ messageQueue.clear();
+ }
+ Iterator itr = cur.iterator();
+ while(itr.hasNext()) {
+ PKT msg = itr.next();
+ 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();
+ continue;
+ }
+
+ int id = packet.id();
+
+ try {
+ switch(id) {
+ case IPCPacket00StartServer.ID: {
+ IPCPacket00StartServer pkt = (IPCPacket00StartServer)packet;
+
+ if(!isServerStopped()) {
+ currentProcess.stopServer();
+ }
+
+ currentProcess = new EAGMinecraftServer(pkt.worldName, pkt.ownerName, newWorldSettings);
+ currentProcess.setBaseServerProperties(pkt.initialDifficulty, newWorldSettings == null ? EnumGameType.SURVIVAL : newWorldSettings.getGameType());
+ currentProcess.startServer();
+
+ String[] worlds = SYS.VFS.getFile("worlds.txt").getAllLines();
+ if(worlds == null || (worlds.length == 1 && worlds[0].trim().length() <= 0)) {
+ worlds = null;
+ }
+ if(worlds == null) {
+ SYS.VFS.getFile("worlds.txt").setAllChars(pkt.worldName);
+ }else {
+ boolean found = false;
+ for(String s : worlds) {
+ if(s.equals(pkt.worldName)) {
+ found = true;
+ break;
+ }
+ }
+ if(!found) {
+ String[] s = new String[worlds.length + 1];
+ s[0] = pkt.worldName;
+ System.arraycopy(worlds, 0, s, 1, worlds.length);
+ SYS.VFS.getFile("worlds.txt").setAllChars(String.join("\n", s));
+ }
+ }
+
+ sendIPCPacket(new IPCPacketFFProcessKeepAlive(IPCPacket00StartServer.ID));
+ }
+ break;
+ case IPCPacket01StopServer.ID: {
+ if(!isServerStopped()) {
+ try {
+ currentProcess.stopServer();
+ currentProcess = null;
+ }catch(Throwable t) {
+ throwExceptionToClient("Failed to stop server!", t);
+ }
+ }else {
+ System.err.println("Client tried to stop server while it wasn't running for some reason");
+ }
+ sendIPCPacket(new IPCPacketFFProcessKeepAlive(IPCPacket01StopServer.ID));
+ }
+ break;
+ case IPCPacket02InitWorld.ID: {
+ tryStopServer();
+ IPCPacket02InitWorld pkt = (IPCPacket02InitWorld)packet;
+ newWorldSettings = new WorldSettings(pkt.seed, pkt.gamemode == 1 ? EnumGameType.CREATIVE : EnumGameType.SURVIVAL, pkt.structures,
+ pkt.gamemode == 2, pkt.worldType == 1 ? WorldType.FLAT : (pkt.worldType == 2 ? WorldType.LARGE_BIOMES : WorldType.DEFAULT_1_1));
+ newWorldSettings.func_82750_a(pkt.worldArgs);
+ if(pkt.bonusChest) {
+ newWorldSettings.enableBonusChest();
+ }
+ if(pkt.cheats) {
+ newWorldSettings.enableCheats();
+ }
+ }
+ break;
+ case IPCPacket03DeleteWorld.ID: {
+ tryStopServer();
+ IPCPacket03DeleteWorld pkt = (IPCPacket03DeleteWorld)packet;
+ if(SYS.VFS.deleteFiles("worlds/" + pkt.worldName + "/") <= 0) {
+ throwExceptionToClient("Failed to delete world!", new RuntimeException("VFS did not delete directory 'worlds/" + pkt.worldName + "' correctly"));
+ sendTaskFailed();
+ break;
+ }
+ String[] worldsTxt = SYS.VFS.getFile("worlds.txt").getAllLines();
+ if(worldsTxt != null) {
+ LinkedList newWorlds = new LinkedList<>();
+ for(String str : worldsTxt) {
+ if(!str.equalsIgnoreCase(pkt.worldName)) {
+ newWorlds.add(str);
+ }
+ }
+ SYS.VFS.getFile("worlds.txt").setAllChars(String.join("\n", newWorlds));
+ }
+ sendIPCPacket(new IPCPacketFFProcessKeepAlive(IPCPacket03DeleteWorld.ID));
+ }
+ break;
+ case IPCPacket04RenameWorld.ID: {
+ tryStopServer();
+ IPCPacket04RenameWorld pkt = (IPCPacket04RenameWorld)packet;
+ if(SYS.VFS.renameFiles("worlds/" + pkt.worldOldName + "/", "worlds/" + pkt.worldNewName + "/", pkt.copy) <= 0) {
+ throwExceptionToClient("Failed to copy/rename server!", new RuntimeException("VFS did not copy/rename directory 'worlds/" + pkt.worldOldName + "' correctly"));
+ sendTaskFailed();
+ break;
+ }else {
+ String[] worldsTxt = SYS.VFS.getFile("worlds.txt").getAllLines();
+ LinkedList newWorlds = new LinkedList<>();
+ if(worldsTxt != null) {
+ for(String str : worldsTxt) {
+ if(pkt.copy || !str.equalsIgnoreCase(pkt.worldOldName)) {
+ newWorlds.add(str);
+ }
+ }
+ }
+ newWorlds.add(pkt.worldNewName);
+ SYS.VFS.getFile("worlds.txt").setAllChars(String.join("\n", newWorlds));
+ VFile worldDat = new VFile("worlds", pkt.worldNewName, "level.dat");
+ if(worldDat.canRead()) {
+ NBTTagCompound worldDatNBT = CompressedStreamTools.decompress(worldDat.getAllBytes());
+ worldDatNBT.getCompoundTag("Data").setString("LevelName", pkt.displayName);
+ worldDat.setAllBytes(CompressedStreamTools.compress(worldDatNBT));
+ }else {
+ throwExceptionToClient("Failed to copy/rename world!", new RuntimeException("Failed to change level.dat world '" + pkt.worldNewName + "' display name to '" + pkt.displayName + "' because level.dat was missing"));
+ sendTaskFailed();
+ break;
+ }
+ }
+ sendIPCPacket(new IPCPacketFFProcessKeepAlive(IPCPacket04RenameWorld.ID));
+ }
+ break;
+ case IPCPacket05RequestData.ID: {
+ IPCPacket05RequestData pkt = (IPCPacket05RequestData)packet;
+ if(pkt.request == IPCPacket05RequestData.REQUEST_LEVEL_EAG) {
+ try {
+ sendIPCPacket(new IPCPacket09RequestResponse(WorldConverterEPK.exportWorld(pkt.worldName)));
+ } catch (Throwable t) {
+ String realWorldName = pkt.worldName;
+ int i = realWorldName.lastIndexOf(new String(new char[] { (char)253, (char)233, (char)233 }));
+ if(i != -1) {
+ realWorldName = realWorldName.substring(0, i);
+ }
+ throwExceptionToClient("Failed to export world '" + realWorldName+ "' as EPK", t);
+ sendTaskFailed();
+ }
+ }else if(pkt.request == IPCPacket05RequestData.REQUEST_LEVEL_MCA) {
+ try {
+ sendIPCPacket(new IPCPacket09RequestResponse(WorldConverterMCA.exportWorld(pkt.worldName)));
+ } catch (Throwable t) {
+ throwExceptionToClient("Failed to export world '" + pkt.worldName+ "' as MCA", t);
+ sendTaskFailed();
+ }
+ }
+ }
+ break;
+ case IPCPacket06RenameWorldNBT.ID: {
+ IPCPacket06RenameWorldNBT pkt = (IPCPacket06RenameWorldNBT)packet;
+ if(isServerStopped()) {
+ VFile worldDat = new VFile("worlds", pkt.worldName, "level.dat");
+ if(worldDat.canRead()) {
+ NBTTagCompound worldDatNBT = CompressedStreamTools.decompress(worldDat.getAllBytes());
+ worldDatNBT.getCompoundTag("Data").setString("LevelName", pkt.displayName);
+ worldDat.setAllBytes(CompressedStreamTools.compress(worldDatNBT));
+ }else {
+ throwExceptionToClient("Failed to rename world!", new RuntimeException("Failed to change level.dat world '" + pkt.worldName + "' display name to '" + pkt.displayName + "' because level.dat was missing"));
+ }
+ }else {
+ System.err.println("Client tried to rename a world '" + pkt.worldName + "' to have name '" + pkt.displayName + "' while the server is running");
+ sendTaskFailed();
+ }
+ }
+ break;
+ case IPCPacket07ImportWorld.ID: {
+ IPCPacket07ImportWorld pkt = (IPCPacket07ImportWorld)packet;
+ if(isServerStopped()) {
+ if(pkt.worldFormat == IPCPacket07ImportWorld.WORLD_FORMAT_EAG) {
+ try {
+ WorldConverterEPK.importWorld(pkt.worldData, pkt.worldName);
+ sendIPCPacket(new IPCPacketFFProcessKeepAlive(IPCPacket07ImportWorld.ID));
+ }catch(Throwable t) {
+ SYS.VFS.deleteFiles("worlds/" + VFSSaveHandler.worldNameToFolderName(pkt.worldName) + "/");
+ throwExceptionToClient("Failed to import world '" + pkt.worldName + "' as EPK", t);
+ sendTaskFailed();
+ }
+ }else if(pkt.worldFormat == IPCPacket07ImportWorld.WORLD_FORMAT_MCA) {
+ try {
+ WorldConverterMCA.importWorld(pkt.worldData, pkt.worldName);
+ sendIPCPacket(new IPCPacketFFProcessKeepAlive(IPCPacket07ImportWorld.ID));
+ }catch(Throwable t) {
+ SYS.VFS.deleteFiles("worlds/" + VFSSaveHandler.worldNameToFolderName(pkt.worldName) + "/");
+ throwExceptionToClient("Failed to import world '" + pkt.worldName + "' as MCA", t);
+ sendTaskFailed();
+ }
+ }else {
+ System.err.println("Client tried to import a world in an unknown format: 0x" + Integer.toHexString(pkt.worldFormat));
+ sendTaskFailed();
+ }
+ }else {
+ System.err.println("Client tried to import a world '" + pkt.worldName + "' while the server is running");
+ sendTaskFailed();
+ }
+ }
+ break;
+ case IPCPacket09RequestResponse.ID:
+
+ break;
+ case IPCPacket0ASetWorldDifficulty.ID: {
+ IPCPacket0ASetWorldDifficulty pkt = (IPCPacket0ASetWorldDifficulty)packet;
+ if(!isServerStopped()) {
+ currentProcess.setDifficultyForAllWorlds(pkt.difficulty);
+ }else {
+ System.err.println("Client tried to set difficulty '" + pkt.difficulty + "' while server was stopped");
+ sendTaskFailed();
+ }
+ }
+ break;
+ case IPCPacket0BPause.ID: {
+ IPCPacket0BPause pkt = (IPCPacket0BPause)packet;
+ if(!isServerStopped()) {
+ if(!pkt.pause && !currentProcess.getPaused()) {
+ currentProcess.saveAllWorlds(true);
+ }else {
+ currentProcess.setPaused(pkt.pause);
+ if(pkt.pause) {
+ currentProcess.saveAllWorlds(true);
+ }
+ }
+ sendIPCPacket(new IPCPacketFFProcessKeepAlive(IPCPacket0BPause.ID));
+ }else {
+ System.err.println("Client tried to " + (pkt.pause ? "pause" : "unpause") + " while server was stopped");
+ }
+ }
+ break;
+ case IPCPacket0CPlayerChannel.ID: {
+ IPCPacket0CPlayerChannel pkt = (IPCPacket0CPlayerChannel)packet;
+ if(!isServerStopped()) {
+ if(pkt.open) {
+ if(!currentProcess.getNetworkThread().openChannel(pkt.channel)) {
+ System.err.println("Client tried to open a duplicate channel '" + pkt.channel + "'");
+ }
+ }else {
+ if(!currentProcess.getNetworkThread().closeChannel(pkt.channel)) {
+ System.err.println("Client tried to close a null channel '" + pkt.channel + "'");
+ }
+ }
+ }else {
+ System.err.println("Client tried to " + (pkt.open ? "open" : "close") + " channel '" + pkt.channel + "' while server was stopped");
+ }
+ }
+ break;
+ case IPCPacket0EListWorlds.ID: {
+ if(isServerStopped()) {
+ String[] worlds = SYS.VFS.getFile("worlds.txt").getAllLines();
+ if(worlds == null || (worlds.length == 1 && worlds[0].trim().length() <= 0)) {
+ worlds = null;
+ }
+ if(worlds == null) {
+ sendIPCPacket(new IPCPacket16NBTList(IPCPacket16NBTList.WORLD_LIST, new LinkedList()));
+ break;
+ }
+ LinkedList updatedList = new LinkedList<>();
+ LinkedList sendListNBT = new LinkedList<>();
+ boolean rewrite = false;
+ for(String w : worlds) {
+ byte[] dat = (new VFile("worlds", w, "level.dat")).getAllBytes();
+ if(dat != null) {
+ NBTTagCompound worldDatNBT;
+ try {
+ worldDatNBT = CompressedStreamTools.decompress(dat);
+ worldDatNBT.setString("folderName", w);
+ sendListNBT.add(worldDatNBT);
+ updatedList.add(w);
+ continue;
+ }catch(IOException e) {
+ // shit fuck
+ }
+
+ }
+ rewrite = true;
+ System.err.println("World level.dat for '" + w + "' was not found, attempting to delete 'worlds/" + w + "/*'");
+ if(SYS.VFS.deleteFiles("worlds/" + w) <= 0) {
+ System.err.println("No files were deleted in 'worlds/" + w + "/*', this may be corruption but '" + w + "' will still be removed from worlds.txt");
+ }
+ }
+ if(rewrite) {
+ SYS.VFS.getFile("worlds.txt").setAllChars(String.join("\n", updatedList));
+ }
+ sendIPCPacket(new IPCPacket16NBTList(IPCPacket16NBTList.WORLD_LIST, sendListNBT));
+ }else {
+ System.err.println("Client tried to list worlds while server was running");
+ sendTaskFailed();
+ }
+ }
+ break;
+ case IPCPacket0FListFiles.ID:
+
+ break;
+ case IPCPacket10FileRead.ID:
+
+ break;
+ case IPCPacket12FileWrite.ID:
+
+ break;
+ case IPCPacket13FileCopyMove.ID:
+
+ break;
+ case IPCPacket14StringList.ID: {
+ IPCPacket14StringList pkt = (IPCPacket14StringList)packet;
+ switch(pkt.opCode) {
+ case IPCPacket14StringList.LOCALE:
+ StringTranslate.init(pkt.stringList);
+ break;
+ case IPCPacket14StringList.STAT_GUID:
+ AchievementMap.init(pkt.stringList);
+ AchievementList.init();
+ break;
+ default:
+ System.err.println("Strange string list 0x" + Integer.toHexString(pkt.opCode) + " with length " + pkt.stringList.size() + " recieved");
+ break;
+ }
+ }
+ break;
+ case IPCPacket17ConfigureLAN.ID: {
+ IPCPacket17ConfigureLAN pkt = (IPCPacket17ConfigureLAN)packet;
+ currentProcess.getConfigurationManager().configureLAN(pkt.gamemode, pkt.cheats, pkt.iceServers);
+ }
+ break;
+ case IPCPacket18ClearPlayers.ID: {
+ SYS.VFS.deleteFiles("worlds/" + ((IPCPacket18ClearPlayers)packet).worldName + "/player");
+ sendIPCPacket(new IPCPacketFFProcessKeepAlive(IPCPacket18ClearPlayers.ID));
+ }
+ break;
+ default:
+ System.err.println("IPC packet type 0x" + Integer.toHexString(id) + " class '" + packet.getClass().getSimpleName() + "' was not handled");
+ sendTaskFailed();
+ break;
+ }
+ }catch(Throwable t) {
+ String str = "IPC packet 0x" + Integer.toHexString(id) + " class '" + packet.getClass().getSimpleName() + "' was not processed correctly";
+ System.err.println(str);
+ throwExceptionToClient(str, t);
+ sendTaskFailed();
+ }
+
+ continue;
+ }
+ }
+ long watchDog = SysUtil.steadyTimeMillis();
+ itr = cur.iterator();
+ int overflow = 0;
+ while(itr.hasNext()) {
+ PKT msg = itr.next();
+ if(!msg.channel.equals("IPC")) {
+ if(SysUtil.steadyTimeMillis() - watchDog > 500l) {
+ ++overflow;
+ continue;
+ }
+ if(!msg.channel.startsWith("NET|") || currentProcess == null) {
+ //System.err.println("Unknown ICP channel: '" + msg.channel + "' passed " + msg.data.length + " bytes");
+ continue;
+ }
+ String u = msg.channel.substring(4);
+ currentProcess.getNetworkThread().recievePacket(u, msg.data);
+ }
+ }
+ if(overflow > 0) {
+ System.err.println("Async ICP queue is overloaded, server dropped " + overflow + " player packets");
+ }
+ }
+
+ @JSBody(params = { "ch", "dat" }, script = "postMessage({ ch: ch, dat : dat });")
+ private static native void sendWorkerPacket(String channel, ArrayBuffer arr);
+
+ public static void sendIPCPacket(IPCPacketBase pkt) {
+ byte[] serialized;
+
+ try {
+ serialized = IPCPacketManager.IPCSerialize(pkt);
+ } catch (IOException e) {
+ System.err.println("Could not serialize IPC packet 0x" + Integer.toHexString(pkt.id()) + " class '" + pkt.getClass().getSimpleName() + "'");
+ e.printStackTrace();
+ return;
+ }
+
+ sendWorkerPacket("IPC", TeaVMUtils.unwrapArrayBuffer(serialized));
+ }
+
+ public static void sendPlayerPacket(String channel, byte[] buf) {
+ //System.out.println("[Server][SEND][" + channel + "]: " + buf.length);
+ sendWorkerPacket("NET|" + channel, TeaVMUtils.unwrapArrayBuffer(buf));
+ }
+
+ private static boolean isRunning = false;
+
+ public static void halt() {
+ isRunning = false;
+ }
+
+ private static void mainLoop() {
+ processAsyncMessageQueue();
+
+ if(currentProcess != null) {
+ currentProcess.mainLoop();
+ if(currentProcess.isServerStopped()) {
+ sendIPCPacket(new IPCPacketFFProcessKeepAlive(IPCPacket01StopServer.ID));
+ currentProcess = null;
+ }
+ }else {
+ SysUtil.sleep(50);
+ }
+ }
+
+ @JSBody(params = { "wb" }, script = "onmessage = function(o) { wb(o.data.ch, o.data.dat); };")
+ private static native void registerPacketHandler(WorkerBinaryPacketHandler wb);
+
+ public static void main(String[] args) {
+
+ registerPacketHandler(new WorkerBinaryPacketHandlerImpl());
+
+ isRunning = true;
+
+ sendIPCPacket(new IPCPacketFFProcessKeepAlive(0xFF));
+
+ while(isRunning) {
+
+ mainLoop();
+
+ SysUtil.immediateContinue();
+ }
+
+ // yee
+ }
+
+}
diff --git a/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/MD5Digest.java b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/MD5Digest.java
new file mode 100644
index 0000000..8f007c3
--- /dev/null
+++ b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/MD5Digest.java
@@ -0,0 +1,244 @@
+package net.lax1dude.eaglercraft.sp;
+
+/**
+ * implementation of MD5 as outlined in "Handbook of Applied Cryptography",
+ * pages 346 - 347.
+ */
+public class MD5Digest extends GeneralDigest {
+ private static final int DIGEST_LENGTH = 16;
+
+ private int H1, H2, H3, H4; // IV's
+
+ private int[] X = new int[16];
+ private int xOff;
+
+ public String getAlgorithmName() {
+ return "MD5";
+ }
+
+ public int getDigestSize() {
+ return DIGEST_LENGTH;
+ }
+
+ protected void processWord(byte[] in, int inOff) {
+ X[xOff++] = littleEndianToInt(in, inOff);
+
+ if (xOff == 16) {
+ processBlock();
+ }
+ }
+
+ private int littleEndianToInt(byte[] bs, int off) {
+ int n = bs[off] & 0xff;
+ n |= (bs[++off] & 0xff) << 8;
+ n |= (bs[++off] & 0xff) << 16;
+ n |= bs[++off] << 24;
+ return n;
+ }
+
+ protected void processLength(long bitLength) {
+ if (xOff > 14) {
+ processBlock();
+ }
+
+ X[14] = (int) (bitLength & 0xffffffff);
+ X[15] = (int) (bitLength >>> 32);
+ }
+
+ public int doFinal(byte[] out, int outOff) {
+ finish();
+
+ intToLittleEndian(H1, out, outOff);
+ intToLittleEndian(H2, out, outOff + 4);
+ intToLittleEndian(H3, out, outOff + 8);
+ intToLittleEndian(H4, out, outOff + 12);
+
+ reset();
+
+ return DIGEST_LENGTH;
+ }
+
+ private void intToLittleEndian(int n, byte[] bs, int off) {
+ bs[off] = (byte) (n);
+ bs[++off] = (byte) (n >>> 8);
+ bs[++off] = (byte) (n >>> 16);
+ bs[++off] = (byte) (n >>> 24);
+ }
+
+ /**
+ * reset the chaining variables to the IV values.
+ */
+ public void reset() {
+ super.reset();
+
+ H1 = 0x67452301;
+ H2 = 0xefcdab89;
+ H3 = 0x98badcfe;
+ H4 = 0x10325476;
+
+ xOff = 0;
+
+ for (int i = 0; i != X.length; i++) {
+ X[i] = 0;
+ }
+ }
+
+ //
+ // round 1 left rotates
+ //
+ private static final int S11 = 7;
+ private static final int S12 = 12;
+ private static final int S13 = 17;
+ private static final int S14 = 22;
+
+ //
+ // round 2 left rotates
+ //
+ private static final int S21 = 5;
+ private static final int S22 = 9;
+ private static final int S23 = 14;
+ private static final int S24 = 20;
+
+ //
+ // round 3 left rotates
+ //
+ private static final int S31 = 4;
+ private static final int S32 = 11;
+ private static final int S33 = 16;
+ private static final int S34 = 23;
+
+ //
+ // round 4 left rotates
+ //
+ private static final int S41 = 6;
+ private static final int S42 = 10;
+ private static final int S43 = 15;
+ private static final int S44 = 21;
+
+ /*
+ * rotate int x left n bits.
+ */
+ private int rotateLeft(int x, int n) {
+ return (x << n) | (x >>> (32 - n));
+ }
+
+ /*
+ * F, G, H and I are the basic MD5 functions.
+ */
+ private int F(int u, int v, int w) {
+ return (u & v) | (~u & w);
+ }
+
+ private int G(int u, int v, int w) {
+ return (u & w) | (v & ~w);
+ }
+
+ private int H(int u, int v, int w) {
+ return u ^ v ^ w;
+ }
+
+ private int K(int u, int v, int w) {
+ return v ^ (u | ~w);
+ }
+
+ protected void processBlock() {
+ int a = H1;
+ int b = H2;
+ int c = H3;
+ int d = H4;
+
+ //
+ // Round 1 - F cycle, 16 times.
+ //
+ a = rotateLeft(a + F(b, c, d) + X[0] + 0xd76aa478, S11) + b;
+ d = rotateLeft(d + F(a, b, c) + X[1] + 0xe8c7b756, S12) + a;
+ c = rotateLeft(c + F(d, a, b) + X[2] + 0x242070db, S13) + d;
+ b = rotateLeft(b + F(c, d, a) + X[3] + 0xc1bdceee, S14) + c;
+ a = rotateLeft(a + F(b, c, d) + X[4] + 0xf57c0faf, S11) + b;
+ d = rotateLeft(d + F(a, b, c) + X[5] + 0x4787c62a, S12) + a;
+ c = rotateLeft(c + F(d, a, b) + X[6] + 0xa8304613, S13) + d;
+ b = rotateLeft(b + F(c, d, a) + X[7] + 0xfd469501, S14) + c;
+ a = rotateLeft(a + F(b, c, d) + X[8] + 0x698098d8, S11) + b;
+ d = rotateLeft(d + F(a, b, c) + X[9] + 0x8b44f7af, S12) + a;
+ c = rotateLeft(c + F(d, a, b) + X[10] + 0xffff5bb1, S13) + d;
+ b = rotateLeft(b + F(c, d, a) + X[11] + 0x895cd7be, S14) + c;
+ a = rotateLeft(a + F(b, c, d) + X[12] + 0x6b901122, S11) + b;
+ d = rotateLeft(d + F(a, b, c) + X[13] + 0xfd987193, S12) + a;
+ c = rotateLeft(c + F(d, a, b) + X[14] + 0xa679438e, S13) + d;
+ b = rotateLeft(b + F(c, d, a) + X[15] + 0x49b40821, S14) + c;
+
+ //
+ // Round 2 - G cycle, 16 times.
+ //
+ a = rotateLeft(a + G(b, c, d) + X[1] + 0xf61e2562, S21) + b;
+ d = rotateLeft(d + G(a, b, c) + X[6] + 0xc040b340, S22) + a;
+ c = rotateLeft(c + G(d, a, b) + X[11] + 0x265e5a51, S23) + d;
+ b = rotateLeft(b + G(c, d, a) + X[0] + 0xe9b6c7aa, S24) + c;
+ a = rotateLeft(a + G(b, c, d) + X[5] + 0xd62f105d, S21) + b;
+ d = rotateLeft(d + G(a, b, c) + X[10] + 0x02441453, S22) + a;
+ c = rotateLeft(c + G(d, a, b) + X[15] + 0xd8a1e681, S23) + d;
+ b = rotateLeft(b + G(c, d, a) + X[4] + 0xe7d3fbc8, S24) + c;
+ a = rotateLeft(a + G(b, c, d) + X[9] + 0x21e1cde6, S21) + b;
+ d = rotateLeft(d + G(a, b, c) + X[14] + 0xc33707d6, S22) + a;
+ c = rotateLeft(c + G(d, a, b) + X[3] + 0xf4d50d87, S23) + d;
+ b = rotateLeft(b + G(c, d, a) + X[8] + 0x455a14ed, S24) + c;
+ a = rotateLeft(a + G(b, c, d) + X[13] + 0xa9e3e905, S21) + b;
+ d = rotateLeft(d + G(a, b, c) + X[2] + 0xfcefa3f8, S22) + a;
+ c = rotateLeft(c + G(d, a, b) + X[7] + 0x676f02d9, S23) + d;
+ b = rotateLeft(b + G(c, d, a) + X[12] + 0x8d2a4c8a, S24) + c;
+
+ //
+ // Round 3 - H cycle, 16 times.
+ //
+ a = rotateLeft(a + H(b, c, d) + X[5] + 0xfffa3942, S31) + b;
+ d = rotateLeft(d + H(a, b, c) + X[8] + 0x8771f681, S32) + a;
+ c = rotateLeft(c + H(d, a, b) + X[11] + 0x6d9d6122, S33) + d;
+ b = rotateLeft(b + H(c, d, a) + X[14] + 0xfde5380c, S34) + c;
+ a = rotateLeft(a + H(b, c, d) + X[1] + 0xa4beea44, S31) + b;
+ d = rotateLeft(d + H(a, b, c) + X[4] + 0x4bdecfa9, S32) + a;
+ c = rotateLeft(c + H(d, a, b) + X[7] + 0xf6bb4b60, S33) + d;
+ b = rotateLeft(b + H(c, d, a) + X[10] + 0xbebfbc70, S34) + c;
+ a = rotateLeft(a + H(b, c, d) + X[13] + 0x289b7ec6, S31) + b;
+ d = rotateLeft(d + H(a, b, c) + X[0] + 0xeaa127fa, S32) + a;
+ c = rotateLeft(c + H(d, a, b) + X[3] + 0xd4ef3085, S33) + d;
+ b = rotateLeft(b + H(c, d, a) + X[6] + 0x04881d05, S34) + c;
+ a = rotateLeft(a + H(b, c, d) + X[9] + 0xd9d4d039, S31) + b;
+ d = rotateLeft(d + H(a, b, c) + X[12] + 0xe6db99e5, S32) + a;
+ c = rotateLeft(c + H(d, a, b) + X[15] + 0x1fa27cf8, S33) + d;
+ b = rotateLeft(b + H(c, d, a) + X[2] + 0xc4ac5665, S34) + c;
+
+ //
+ // Round 4 - K cycle, 16 times.
+ //
+ a = rotateLeft(a + K(b, c, d) + X[0] + 0xf4292244, S41) + b;
+ d = rotateLeft(d + K(a, b, c) + X[7] + 0x432aff97, S42) + a;
+ c = rotateLeft(c + K(d, a, b) + X[14] + 0xab9423a7, S43) + d;
+ b = rotateLeft(b + K(c, d, a) + X[5] + 0xfc93a039, S44) + c;
+ a = rotateLeft(a + K(b, c, d) + X[12] + 0x655b59c3, S41) + b;
+ d = rotateLeft(d + K(a, b, c) + X[3] + 0x8f0ccc92, S42) + a;
+ c = rotateLeft(c + K(d, a, b) + X[10] + 0xffeff47d, S43) + d;
+ b = rotateLeft(b + K(c, d, a) + X[1] + 0x85845dd1, S44) + c;
+ a = rotateLeft(a + K(b, c, d) + X[8] + 0x6fa87e4f, S41) + b;
+ d = rotateLeft(d + K(a, b, c) + X[15] + 0xfe2ce6e0, S42) + a;
+ c = rotateLeft(c + K(d, a, b) + X[6] + 0xa3014314, S43) + d;
+ b = rotateLeft(b + K(c, d, a) + X[13] + 0x4e0811a1, S44) + c;
+ a = rotateLeft(a + K(b, c, d) + X[4] + 0xf7537e82, S41) + b;
+ d = rotateLeft(d + K(a, b, c) + X[11] + 0xbd3af235, S42) + a;
+ c = rotateLeft(c + K(d, a, b) + X[2] + 0x2ad7d2bb, S43) + d;
+ b = rotateLeft(b + K(c, d, a) + X[9] + 0xeb86d391, S44) + c;
+
+ H1 += a;
+ H2 += b;
+ H3 += c;
+ H4 += d;
+
+ //
+ // reset the offset and clean out the word buffer.
+ //
+ xOff = 0;
+ for (int i = 0; i != X.length; i++) {
+ X[i] = 0;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/MessageChannel.java b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/MessageChannel.java
new file mode 100644
index 0000000..2f024cc
--- /dev/null
+++ b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/MessageChannel.java
@@ -0,0 +1,36 @@
+package net.lax1dude.eaglercraft.sp;
+
+import org.teavm.jso.JSBody;
+import org.teavm.jso.JSClass;
+import org.teavm.jso.JSObject;
+import org.teavm.jso.JSProperty;
+import org.teavm.jso.workers.MessagePort;
+
+/**
+ * Copyright (c) 2024 lax1dude. All Rights Reserved.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+@JSClass
+public class MessageChannel implements JSObject {
+
+ @JSBody(params = { }, script = "return (typeof MessageChannel !== \"undefined\");")
+ public static native boolean supported();
+
+ @JSProperty
+ public native MessagePort getPort1();
+
+ @JSProperty
+ public native MessagePort getPort2();
+
+}
diff --git a/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/NoCatchParse.java b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/NoCatchParse.java
new file mode 100644
index 0000000..70bcdeb
--- /dev/null
+++ b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/NoCatchParse.java
@@ -0,0 +1,412 @@
+package net.lax1dude.eaglercraft.sp;
+
+public class NoCatchParse {
+
+ public static final int INT_EXCEPTION = Integer.MIN_VALUE;
+ public static final float FLOAT_EXCEPTION = Float.NaN;
+ public static final double DOUBLE_EXCEPTION = Double.NaN;
+
+ public static int parseInt(String s) {
+ return parseInt(s, 10, false, INT_EXCEPTION);
+ }
+
+ public static int parseInt(String s, int radix) {
+ return parseInt(s, radix, false, INT_EXCEPTION);
+ }
+
+ public static int parseInt(String s, int radix, boolean log) {
+ return parseInt(s, radix, log, INT_EXCEPTION);
+ }
+
+ public static int parseInt(String s, int radix, boolean log, int exceptionResult) {
+ if (s == null) {
+ if (log) {
+ System.err.println("parseInt: string was null");
+ }
+ return exceptionResult;
+ }
+
+ if (s.isEmpty()) {
+ if (log) {
+ System.err.println("parseInt: string was empty");
+ }
+ return exceptionResult;
+ }
+
+ if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) {
+ if (log) {
+ System.err.println("parseInt: invalid radix '" + radix + "'");
+ }
+ return exceptionResult;
+ }
+
+ tryFail: {
+ int result = 0;
+ boolean negative = false;
+ int i = 0, len = s.length();
+ int limit = -Integer.MAX_VALUE;
+ int multmin;
+ int digit;
+
+ if (len > 0) {
+ char firstChar = s.charAt(0);
+ if (firstChar < '0') { // Possible leading "+" or "-"
+ if (firstChar == '-') {
+ negative = true;
+ limit = Integer.MIN_VALUE;
+ } else if (firstChar != '+')
+ break tryFail;
+
+ if (len == 1)
+ break tryFail;
+ i++;
+ }
+ multmin = limit / radix;
+ while (i < len) {
+ // Accumulating negatively avoids surprises near MAX_VALUE
+ digit = Character.digit(s.charAt(i++), radix);
+ if (digit < 0 || result < multmin) {
+
+ break tryFail;
+ }
+ result *= radix;
+ if (result < limit + digit) {
+ break tryFail;
+ }
+ result -= digit;
+ }
+ } else {
+ break tryFail;
+ }
+ int ret = negative ? result : -result;
+ if (ret == exceptionResult) {
+ System.err.println(
+ "parseInt: number '" + s + "' was parsed successfully but it is equal to exceptionResult");
+ }
+ return ret;
+ }
+ if (log) {
+ System.err.println("parseInt: cannot parse '" + s + "'");
+ }
+ return exceptionResult;
+ }
+
+ public static double parseDouble(String s) {
+ return parseDouble(s, false, DOUBLE_EXCEPTION);
+ }
+
+ public static double parseDouble(String s, boolean log) {
+ return parseDouble(s, log, DOUBLE_EXCEPTION);
+ }
+
+ public static double parseDouble(String s, boolean log, double exceptionResult) {
+ if (s == null) {
+ if (log) {
+ System.err.println("parseDouble: string was null");
+ }
+ return exceptionResult;
+ }
+
+ if (s.isEmpty()) {
+ if (log) {
+ System.err.println("parseDouble: string was empty");
+ }
+ return exceptionResult;
+ }
+
+ tryFail: {
+ int start = 0;
+ int end = s.length();
+ while (s.charAt(start) <= ' ') {
+ if (++start == end) {
+ break tryFail;
+ }
+ }
+ while (s.charAt(end - 1) <= ' ') {
+ --end;
+ }
+
+ boolean negative = false;
+ int index = start;
+ if (s.charAt(index) == '-') {
+ ++index;
+ negative = true;
+ } else if (s.charAt(index) == '+') {
+ ++index;
+ }
+ if (index == end) {
+ break tryFail;
+ }
+ char c = s.charAt(index);
+
+ long mantissa = 0;
+ int exp = 0;
+ boolean hasOneDigit = false;
+ if (c != '.') {
+ hasOneDigit = true;
+ if (c < '0' || c > '9') {
+ break tryFail;
+ }
+ while (index < end && s.charAt(index) == '0') {
+ ++index;
+ }
+ while (index < end) {
+ c = s.charAt(index);
+ if (c < '0' || c > '9') {
+ break;
+ }
+ if (mantissa < Long.MAX_VALUE / 10 - 9) {
+ mantissa = mantissa * 10 + (c - '0');
+ } else {
+ ++exp;
+ }
+ ++index;
+ }
+ }
+ if (index < end && s.charAt(index) == '.') {
+ ++index;
+ while (index < end) {
+ c = s.charAt(index);
+ if (c < '0' || c > '9') {
+ break;
+ }
+ if (mantissa < Long.MAX_VALUE / 10 - 9) {
+ mantissa = mantissa * 10 + (c - '0');
+ --exp;
+ }
+ ++index;
+ hasOneDigit = true;
+ }
+ if (!hasOneDigit) {
+ break tryFail;
+ }
+ }
+ if (index < end) {
+ c = s.charAt(index);
+ if (c != 'e' && c != 'E') {
+ break tryFail;
+ }
+ ++index;
+ boolean negativeExp = false;
+ if (index == end) {
+ break tryFail;
+ }
+ if (s.charAt(index) == '-') {
+ ++index;
+ negativeExp = true;
+ } else if (s.charAt(index) == '+') {
+ ++index;
+ }
+ int numExp = 0;
+ hasOneDigit = false;
+ while (index < end) {
+ c = s.charAt(index);
+ if (c < '0' || c > '9') {
+ break;
+ }
+ numExp = 10 * numExp + (c - '0');
+ hasOneDigit = true;
+ ++index;
+ }
+ if (!hasOneDigit) {
+ break tryFail;
+ }
+ if (negativeExp) {
+ numExp = -numExp;
+ }
+ exp += numExp;
+ }
+ if (exp > 308 || exp == 308 && mantissa > 17976931348623157L) {
+ return !negative ? Double.POSITIVE_INFINITY : Double.NEGATIVE_INFINITY;
+ }
+ if (negative) {
+ mantissa = -mantissa;
+ }
+ return mantissa * doubleDecimalExponent(exp);
+ }
+ if (log) {
+ System.err.println("parseDouble: cannot parse '" + s + "'");
+ }
+ return exceptionResult;
+ }
+
+ public static double doubleDecimalExponent(int n) {
+ double d;
+ if (n < 0) {
+ d = 0.1;
+ n = -n;
+ } else {
+ d = 10;
+ }
+ double result = 1;
+ while (n != 0) {
+ if (n % 2 != 0) {
+ result *= d;
+ }
+ d *= d;
+ n /= 2;
+ }
+ return result;
+ }
+
+ public static float parseFloat(String s) {
+ return parseFloat(s, false, FLOAT_EXCEPTION);
+ }
+
+ public static float parseFloat(String s, boolean log) {
+ return parseFloat(s, log, FLOAT_EXCEPTION);
+ }
+
+ public static float parseFloat(String s, boolean log, float exceptionResult) {
+ if (s == null) {
+ if (log) {
+ System.err.println("parseFloat: string was null");
+ }
+ return exceptionResult;
+ }
+
+ if (s.isEmpty()) {
+ if (log) {
+ System.err.println("parseFloat: string was empty");
+ }
+ return exceptionResult;
+ }
+
+ tryFail: {
+ int start = 0;
+ int end = s.length();
+ while (s.charAt(start) <= ' ') {
+ if (++start == end) {
+ break tryFail;
+ }
+ }
+ while (s.charAt(end - 1) <= ' ') {
+ --end;
+ }
+
+ boolean negative = false;
+ int index = start;
+ if (s.charAt(index) == '-') {
+ ++index;
+ negative = true;
+ } else if (s.charAt(index) == '+') {
+ ++index;
+ }
+ if (index == end) {
+ break tryFail;
+ }
+ char c = s.charAt(index);
+
+ int mantissa = 0;
+ int exp = 0;
+
+ boolean hasOneDigit = false;
+ if (c != '.') {
+ hasOneDigit = true;
+ if (c < '0' || c > '9') {
+ break tryFail;
+ }
+
+ while (index < end && s.charAt(index) == '0') {
+ ++index;
+ }
+ while (index < end) {
+ c = s.charAt(index);
+ if (c < '0' || c > '9') {
+ break;
+ }
+ if (mantissa < (Integer.MAX_VALUE / 10) - 9) {
+ mantissa = mantissa * 10 + (c - '0');
+ } else {
+ ++exp;
+ }
+ ++index;
+ }
+ }
+
+ if (index < end && s.charAt(index) == '.') {
+ ++index;
+ while (index < end) {
+ c = s.charAt(index);
+ if (c < '0' || c > '9') {
+ break;
+ }
+ if (mantissa < (Integer.MAX_VALUE / 10) - 9) {
+ mantissa = mantissa * 10 + (c - '0');
+ --exp;
+ }
+ ++index;
+ hasOneDigit = true;
+ }
+ if (!hasOneDigit) {
+ break tryFail;
+ }
+ }
+ if (index < end) {
+ c = s.charAt(index);
+ if (c != 'e' && c != 'E') {
+ break tryFail;
+ }
+ ++index;
+ boolean negativeExp = false;
+ if (index == end) {
+ break tryFail;
+ }
+ if (s.charAt(index) == '-') {
+ ++index;
+ negativeExp = true;
+ } else if (s.charAt(index) == '+') {
+ ++index;
+ }
+ int numExp = 0;
+ hasOneDigit = false;
+ while (index < end) {
+ c = s.charAt(index);
+ if (c < '0' || c > '9') {
+ break;
+ }
+ numExp = 10 * numExp + (c - '0');
+ hasOneDigit = true;
+ ++index;
+ }
+ if (!hasOneDigit) {
+ break tryFail;
+ }
+ if (negativeExp) {
+ numExp = -numExp;
+ }
+ exp += numExp;
+ }
+ if (exp > 38 || exp == 38 && mantissa > 34028234) {
+ return !negative ? Float.POSITIVE_INFINITY : Float.NEGATIVE_INFINITY;
+ }
+ if (negative) {
+ mantissa = -mantissa;
+ }
+ return mantissa * floatDecimalExponent(exp);
+ }
+ if (log) {
+ System.err.println("parseFloat: cannot parse '" + s + "'");
+ }
+ return exceptionResult;
+ }
+
+ private static float floatDecimalExponent(int n) {
+ double d;
+ if (n < 0) {
+ d = 0.1;
+ n = -n;
+ } else {
+ d = 10;
+ }
+ double result = 1;
+ while (n != 0) {
+ if (n % 2 != 0) {
+ result *= d;
+ }
+ d *= d;
+ n /= 2;
+ }
+ return (float) result;
+ }
+}
diff --git a/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/RandomAccessMemoryFile.java b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/RandomAccessMemoryFile.java
new file mode 100644
index 0000000..17f38f3
--- /dev/null
+++ b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/RandomAccessMemoryFile.java
@@ -0,0 +1,310 @@
+package net.lax1dude.eaglercraft.sp;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.EOFException;
+import java.io.IOException;
+
+/**
+ * Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+public class RandomAccessMemoryFile implements DataInput, DataOutput {
+
+ private byte[] buffer;
+ private int length;
+ private int pos;
+
+ public RandomAccessMemoryFile(byte[] initialBuffer, int initialLength) {
+ this.buffer = initialBuffer;
+ this.length = initialLength;
+ this.pos = 0;
+ }
+
+ private void grow(int newMaxSize) {
+ if (length < newMaxSize) {
+ if (buffer.length < newMaxSize) {
+ byte[] newBuffer = new byte[newMaxSize | 0x7FFFF];
+ System.arraycopy(buffer, 0, newBuffer, 0, length);
+ buffer = newBuffer;
+ }
+ length = newMaxSize;
+ }
+ }
+
+ public byte[] getByteArray() {
+ byte[] b = new byte[length];
+ System.arraycopy(buffer, 0, b, 0, length);
+ return b;
+ }
+
+ public int read() throws IOException {
+ return (pos < length) ? (buffer[pos++] & 0xff) : -1;
+ }
+
+ private int readBytes(byte b[], int off, int len) throws IOException {
+ if (pos >= length) {
+ return -1;
+ }
+
+ int avail = length - pos;
+ if (len > avail) {
+ len = avail;
+ }
+ if (len <= 0) {
+ return 0;
+ }
+ System.arraycopy(buffer, pos, b, off, len);
+ pos += len;
+ return len;
+ }
+
+ public int read(byte b[], int off, int len) throws IOException {
+ return readBytes(b, off, len);
+ }
+
+ public int read(byte b[]) throws IOException {
+ return readBytes(b, 0, b.length);
+ }
+
+ public final void readFully(byte b[]) throws IOException {
+ readFully(b, 0, b.length);
+ }
+
+ public final void readFully(byte b[], int off, int len) throws IOException {
+ int n = 0;
+ do {
+ int count = this.read(b, off + n, len - n);
+ if (count < 0)
+ throw new EOFException();
+ n += count;
+ } while (n < len);
+ }
+
+ public int skipBytes(int n) throws IOException {
+ int newpos;
+
+ if (n <= 0) {
+ return 0;
+ }
+ newpos = pos + n;
+ if (newpos > length) {
+ newpos = length;
+ }
+ seek(newpos);
+
+ return (int) (newpos - pos);
+ }
+
+ public void write(int b) throws IOException {
+ grow(pos + 1);
+ buffer[pos] = (byte) b;
+ pos += 1;
+ }
+
+ private void writeBytes(byte b[], int off, int len) throws IOException {
+ grow(pos + len);
+ System.arraycopy(b, off, buffer, pos, len);
+ pos += len;
+ }
+
+ public void write(byte b[]) throws IOException {
+ writeBytes(b, 0, b.length);
+ }
+
+ public void write(byte b[], int off, int len) throws IOException {
+ writeBytes(b, off, len);
+ }
+
+ public void seek(int pos) {
+ this.pos = pos;
+ }
+
+ public int getLength() {
+ return length;
+ }
+
+ public void setLength(int newLength) {
+ grow(newLength);
+ }
+
+ public final boolean readBoolean() throws IOException {
+ int ch = this.read();
+ if (ch < 0)
+ throw new EOFException();
+ return (ch != 0);
+ }
+
+ public final byte readByte() throws IOException {
+ int ch = this.read();
+ if (ch < 0)
+ throw new EOFException();
+ return (byte) (ch);
+ }
+
+ public final int readUnsignedByte() throws IOException {
+ int ch = this.read();
+ if (ch < 0)
+ throw new EOFException();
+ return ch;
+ }
+
+ public final short readShort() throws IOException {
+ int ch1 = this.read();
+ int ch2 = this.read();
+ if ((ch1 | ch2) < 0)
+ throw new EOFException();
+ return (short) ((ch1 << 8) + (ch2 << 0));
+ }
+
+ public final int readUnsignedShort() throws IOException {
+ int ch1 = this.read();
+ int ch2 = this.read();
+ if ((ch1 | ch2) < 0)
+ throw new EOFException();
+ return (ch1 << 8) + (ch2 << 0);
+ }
+
+ public final char readChar() throws IOException {
+ int ch1 = this.read();
+ int ch2 = this.read();
+ if ((ch1 | ch2) < 0)
+ throw new EOFException();
+ return (char) ((ch1 << 8) + (ch2 << 0));
+ }
+
+ public final int readInt() throws IOException {
+ int ch1 = this.read();
+ int ch2 = this.read();
+ int ch3 = this.read();
+ int ch4 = this.read();
+ if ((ch1 | ch2 | ch3 | ch4) < 0)
+ throw new EOFException();
+ return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
+ }
+
+ public final long readLong() throws IOException {
+ return ((long) (readInt()) << 32) + (readInt() & 0xFFFFFFFFL);
+ }
+
+ public final float readFloat() throws IOException {
+ return Float.intBitsToFloat(readInt());
+ }
+
+ public final double readDouble() throws IOException {
+ return Double.longBitsToDouble(readLong());
+ }
+
+ public final String readLine() throws IOException {
+ StringBuilder input = new StringBuilder();
+ int c = -1;
+ boolean eol = false;
+
+ while (!eol) {
+ switch (c = read()) {
+ case -1:
+ case '\n':
+ eol = true;
+ break;
+ case '\r':
+ eol = true;
+ int cur = pos;
+ if ((read()) != '\n') {
+ seek(cur);
+ }
+ break;
+ default:
+ input.append((char) c);
+ break;
+ }
+ }
+
+ if ((c == -1) && (input.length() == 0)) {
+ return null;
+ }
+ return input.toString();
+ }
+
+ public final String readUTF() throws IOException {
+ throw new IOException("TODO");
+ }
+
+ public final void writeBoolean(boolean v) throws IOException {
+ write(v ? 1 : 0);
+ }
+
+ public final void writeByte(int v) throws IOException {
+ write(v);
+ }
+
+ public final void writeShort(int v) throws IOException {
+ write((v >>> 8) & 0xFF);
+ write((v >>> 0) & 0xFF);
+ }
+
+ public final void writeChar(int v) throws IOException {
+ write((v >>> 8) & 0xFF);
+ write((v >>> 0) & 0xFF);
+ }
+
+ public final void writeInt(int v) throws IOException {
+ write((v >>> 24) & 0xFF);
+ write((v >>> 16) & 0xFF);
+ write((v >>> 8) & 0xFF);
+ write((v >>> 0) & 0xFF);
+ }
+
+ public final void writeLong(long v) throws IOException {
+ write((int) (v >>> 56) & 0xFF);
+ write((int) (v >>> 48) & 0xFF);
+ write((int) (v >>> 40) & 0xFF);
+ write((int) (v >>> 32) & 0xFF);
+ write((int) (v >>> 24) & 0xFF);
+ write((int) (v >>> 16) & 0xFF);
+ write((int) (v >>> 8) & 0xFF);
+ write((int) (v >>> 0) & 0xFF);
+ }
+
+ public final void writeFloat(float v) throws IOException {
+ writeInt(Float.floatToIntBits(v));
+ }
+
+ public final void writeDouble(double v) throws IOException {
+ writeLong(Double.doubleToLongBits(v));
+ }
+
+ public final void writeBytes(String s) throws IOException {
+ int len = s.length();
+ byte[] b = new byte[len];
+ s.getBytes(0, len, b, 0);
+ writeBytes(b, 0, len);
+ }
+
+ public final void writeChars(String s) throws IOException {
+ int clen = s.length();
+ int blen = 2 * clen;
+ byte[] b = new byte[blen];
+ char[] c = new char[clen];
+ s.getChars(0, clen, c, 0);
+ for (int i = 0, j = 0; i < clen; i++) {
+ b[j++] = (byte) (c[i] >>> 8);
+ b[j++] = (byte) (c[i] >>> 0);
+ }
+ writeBytes(b, 0, blen);
+ }
+
+ public final void writeUTF(String str) throws IOException {
+ throw new IOException("TODO");
+ }
+}
diff --git a/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/SHA1Digest.java b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/SHA1Digest.java
new file mode 100644
index 0000000..bffcbc0
--- /dev/null
+++ b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/SHA1Digest.java
@@ -0,0 +1,213 @@
+package net.lax1dude.eaglercraft.sp;
+
+/**
+ * implementation of SHA-1 as outlined in "Handbook of Applied Cryptography",
+ * pages 346 - 349.
+ *
+ * It is interesting to ponder why the, apart from the extra IV, the other
+ * difference here from MD5 is the "endienness" of the word processing!
+ */
+public class SHA1Digest extends GeneralDigest {
+ private static final int DIGEST_LENGTH = 20;
+
+ private int H1, H2, H3, H4, H5;
+
+ private int[] X = new int[80];
+ private int xOff;
+
+ /**
+ * Standard constructor
+ */
+ public SHA1Digest() {
+ reset();
+ }
+
+ /**
+ * Copy constructor. This will copy the state of the provided message digest.
+ */
+ public SHA1Digest(SHA1Digest t) {
+ super(t);
+
+ H1 = t.H1;
+ H2 = t.H2;
+ H3 = t.H3;
+ H4 = t.H4;
+ H5 = t.H5;
+
+ System.arraycopy(t.X, 0, X, 0, t.X.length);
+ xOff = t.xOff;
+ }
+
+ public String getAlgorithmName() {
+ return "SHA-1";
+ }
+
+ public int getDigestSize() {
+ return DIGEST_LENGTH;
+ }
+
+ protected void processWord(byte[] in, int inOff) {
+ X[xOff++] = ((in[inOff] & 0xff) << 24) | ((in[inOff + 1] & 0xff) << 16) | ((in[inOff + 2] & 0xff) << 8)
+ | ((in[inOff + 3] & 0xff));
+
+ if (xOff == 16) {
+ processBlock();
+ }
+ }
+
+ private void unpackWord(int word, byte[] out, int outOff) {
+ out[outOff] = (byte) (word >>> 24);
+ out[outOff + 1] = (byte) (word >>> 16);
+ out[outOff + 2] = (byte) (word >>> 8);
+ out[outOff + 3] = (byte) word;
+ }
+
+ protected void processLength(long bitLength) {
+ if (xOff > 14) {
+ processBlock();
+ }
+
+ X[14] = (int) (bitLength >>> 32);
+ X[15] = (int) (bitLength & 0xffffffff);
+ }
+
+ public int doFinal(byte[] out, int outOff) {
+ finish();
+
+ unpackWord(H1, out, outOff);
+ unpackWord(H2, out, outOff + 4);
+ unpackWord(H3, out, outOff + 8);
+ unpackWord(H4, out, outOff + 12);
+ unpackWord(H5, out, outOff + 16);
+
+ reset();
+
+ return DIGEST_LENGTH;
+ }
+
+ /**
+ * reset the chaining variables
+ */
+ public void reset() {
+ super.reset();
+
+ H1 = 0x67452301;
+ H2 = 0xefcdab89;
+ H3 = 0x98badcfe;
+ H4 = 0x10325476;
+ H5 = 0xc3d2e1f0;
+
+ xOff = 0;
+ for (int i = 0; i != X.length; i++) {
+ X[i] = 0;
+ }
+ }
+
+ //
+ // Additive constants
+ //
+ private static final int Y1 = 0x5a827999;
+ private static final int Y2 = 0x6ed9eba1;
+ private static final int Y3 = 0x8f1bbcdc;
+ private static final int Y4 = 0xca62c1d6;
+
+ private int f(int u, int v, int w) {
+ return ((u & v) | ((~u) & w));
+ }
+
+ private int h(int u, int v, int w) {
+ return (u ^ v ^ w);
+ }
+
+ private int g(int u, int v, int w) {
+ return ((u & v) | (u & w) | (v & w));
+ }
+
+ private int rotateLeft(int x, int n) {
+ return (x << n) | (x >>> (32 - n));
+ }
+
+ protected void processBlock() {
+ //
+ // expand 16 word block into 80 word block.
+ //
+ for (int i = 16; i <= 79; i++) {
+ X[i] = rotateLeft((X[i - 3] ^ X[i - 8] ^ X[i - 14] ^ X[i - 16]), 1);
+ }
+
+ //
+ // set up working variables.
+ //
+ int A = H1;
+ int B = H2;
+ int C = H3;
+ int D = H4;
+ int E = H5;
+
+ //
+ // round 1
+ //
+ for (int j = 0; j <= 19; j++) {
+ int t = rotateLeft(A, 5) + f(B, C, D) + E + X[j] + Y1;
+
+ E = D;
+ D = C;
+ C = rotateLeft(B, 30);
+ B = A;
+ A = t;
+ }
+
+ //
+ // round 2
+ //
+ for (int j = 20; j <= 39; j++) {
+ int t = rotateLeft(A, 5) + h(B, C, D) + E + X[j] + Y2;
+
+ E = D;
+ D = C;
+ C = rotateLeft(B, 30);
+ B = A;
+ A = t;
+ }
+
+ //
+ // round 3
+ //
+ for (int j = 40; j <= 59; j++) {
+ int t = rotateLeft(A, 5) + g(B, C, D) + E + X[j] + Y3;
+
+ E = D;
+ D = C;
+ C = rotateLeft(B, 30);
+ B = A;
+ A = t;
+ }
+
+ //
+ // round 4
+ //
+ for (int j = 60; j <= 79; j++) {
+ int t = rotateLeft(A, 5) + h(B, C, D) + E + X[j] + Y4;
+
+ E = D;
+ D = C;
+ C = rotateLeft(B, 30);
+ B = A;
+ A = t;
+ }
+
+ H1 += A;
+ H2 += B;
+ H3 += C;
+ H4 += D;
+ H5 += E;
+
+ //
+ // reset the offset and clean out the word buffer.
+ //
+ xOff = 0;
+ for (int i = 0; i != X.length; i++) {
+ X[i] = 0;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/SYS.java b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/SYS.java
new file mode 100644
index 0000000..5cded6b
--- /dev/null
+++ b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/SYS.java
@@ -0,0 +1,28 @@
+package net.lax1dude.eaglercraft.sp;
+
+import org.teavm.jso.JSBody;
+
+import net.lax1dude.eaglercraft.sp.VirtualFilesystem.VFSHandle;
+
+public class SYS {
+
+ public static final VirtualFilesystem VFS;
+
+ @JSBody(params = { }, script = "return eaglercraftServerOpts.worldDatabaseName;")
+ private static native String getWorldDatabaseName();
+
+ static {
+
+ VFSHandle vh = VirtualFilesystem.openVFS("_net_lax1dude_eaglercraft_sp_VirtualFilesystem_1_5_2_" + getWorldDatabaseName());
+
+ if(vh.vfs == null) {
+ System.err.println("Could not init filesystem!");
+ IntegratedServer.throwExceptionToClient("Could not init filesystem!", new RuntimeException("VFSHandle.vfs was null"));
+ }
+
+ VFS = vh.vfs;
+
+ }
+
+
+}
diff --git a/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/SkinsPlugin.java b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/SkinsPlugin.java
new file mode 100644
index 0000000..b211308
--- /dev/null
+++ b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/SkinsPlugin.java
@@ -0,0 +1,108 @@
+package net.lax1dude.eaglercraft.sp;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+
+import net.minecraft.src.EntityPlayerMP;
+import net.minecraft.src.Packet250CustomPayload;
+
+public class SkinsPlugin {
+
+ private static final HashMap skinCollection = new HashMap<>();
+ private static final HashMap capeCollection = new HashMap<>();
+ private static final HashMap lastSkinLayerUpdate = new HashMap<>();
+
+ private static final int[] SKIN_DATA_SIZE = new int[] { 64*32*4, 64*64*4, -9, -9, 1, 64*64*4, -9 }; // 128 pixel skins crash clients
+ private static final int[] CAPE_DATA_SIZE = new int[] { 32*32*4, -9, 1 };
+
+ public static boolean handleMessage(EntityPlayerMP player, Packet250CustomPayload payload) {
+ if(payload.data.length > 0) {
+ String user = player.username;
+ byte[] msg = payload.data;
+ try {
+ if("EAG|MySkin".equals(payload.channel)) {
+ if(!skinCollection.containsKey(user)) {
+ int t = (int)msg[0] & 0xFF;
+ if(t < SKIN_DATA_SIZE.length && msg.length == (SKIN_DATA_SIZE[t] + 1)) {
+ skinCollection.put(user, msg);
+ }
+ }
+ return true;
+ }
+ if("EAG|MyCape".equals(payload.channel)) {
+ if(!capeCollection.containsKey(user)) {
+ int t = (int)msg[0] & 0xFF;
+ if(t < CAPE_DATA_SIZE.length && msg.length == (CAPE_DATA_SIZE[t] + 2)) {
+ capeCollection.put(user, msg);
+ }
+ }
+ return true;
+ }
+ if("EAG|FetchSkin".equals(payload.channel)) {
+ if(msg.length > 2) {
+ String fetch = new String(msg, 2, msg.length - 2, StandardCharsets.UTF_8);
+ byte[] data;
+ if((data = skinCollection.get(fetch)) != null) {
+ byte[] conc = new byte[data.length + 2];
+ conc[0] = msg[0]; conc[1] = msg[1]; //synchronization cookie
+ System.arraycopy(data, 0, conc, 2, data.length);
+ if((data = capeCollection.get(fetch)) != null) {
+ byte[] conc2 = new byte[conc.length + data.length];
+ System.arraycopy(conc, 0, conc2, 0, conc.length);
+ System.arraycopy(data, 0, conc2, conc.length, data.length);
+ conc = conc2;
+ }
+ player.playerNetServerHandler.sendPacket(new Packet250CustomPayload("EAG|UserSkin", conc));
+ }
+ }
+ return true;
+ }
+ if("EAG|SkinLayers".equals(payload.channel)) {
+ long millis = SysUtil.steadyTimeMillis();
+ Long lsu = lastSkinLayerUpdate.get(user);
+ if(lsu != null && millis - lsu < 700L) { // DoS protection
+ return true;
+ }
+ lastSkinLayerUpdate.put(user, millis);
+ byte[] data;
+ if((data = capeCollection.get(user)) != null) {
+ data[1] = msg[0];
+ }else {
+ data = new byte[] { (byte)2, msg[0], (byte)0 };
+ capeCollection.put(user, data);
+ }
+ ByteArrayOutputStream bao = new ByteArrayOutputStream();
+ DataOutputStream dd = new DataOutputStream(bao);
+ dd.write(msg[0]);
+ dd.writeUTF(user);
+ byte[] bpacket = bao.toByteArray();
+ for(Object o : player.mcServer.getConfigurationManager().playerEntityList) {
+ EntityPlayerMP pl = (EntityPlayerMP) o;
+ if(!pl.username.equals(user)) {
+ pl.playerNetServerHandler.sendPacket(new Packet250CustomPayload("EAG|SkinLayers", bpacket));
+ }
+ }
+ return true;
+ }
+ }catch(Throwable t) {
+ // hacker
+ }
+ }
+ return false;
+ }
+
+ public static void handleDisconnect(EntityPlayerMP player) {
+ skinCollection.remove(player.username);
+ capeCollection.remove(player.username);
+ lastSkinLayerUpdate.remove(player.username);
+ }
+
+ public static void reset() {
+ skinCollection.clear();
+ capeCollection.clear();
+ lastSkinLayerUpdate.clear();
+ }
+
+}
diff --git a/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/SysUtil.java b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/SysUtil.java
new file mode 100644
index 0000000..09c55bb
--- /dev/null
+++ b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/SysUtil.java
@@ -0,0 +1,152 @@
+package net.lax1dude.eaglercraft.sp;
+
+import org.teavm.interop.Async;
+import org.teavm.interop.AsyncCallback;
+import org.teavm.jso.JSBody;
+import org.teavm.jso.JSObject;
+import org.teavm.jso.browser.Window;
+import org.teavm.jso.core.JSString;
+import org.teavm.jso.dom.events.EventListener;
+import org.teavm.jso.dom.events.MessageEvent;
+import org.teavm.platform.Platform;
+import org.teavm.platform.PlatformRunnable;
+
+public class SysUtil {
+
+ private static final JSObject steadyTimeFunc = getSteadyTimeFunc();
+
+ @JSBody(params = { }, script = "return ((typeof performance !== \"undefined\") && (typeof performance.now === \"function\"))"
+ + "? performance.now.bind(performance)"
+ + ": (function(epochStart){ return function() { return Date.now() - epochStart; }; })(Date.now());")
+ private static native JSObject getSteadyTimeFunc();
+
+ @JSBody(params = { "steadyTimeFunc" }, script = "return steadyTimeFunc();")
+ private static native double steadyTimeMillis0(JSObject steadyTimeFunc);
+
+ public static long steadyTimeMillis() {
+ return (long)steadyTimeMillis0(steadyTimeFunc);
+ }
+
+ public static long nanoTime() {
+ return (long)(steadyTimeMillis0(steadyTimeFunc) * 1000000.0);
+ }
+
+ @Async
+ public static native void sleep(int millis);
+
+ private static void sleep(int millis, final AsyncCallback callback) {
+ Platform.schedule(new DumbSleepHandler(callback), millis);
+ }
+
+ private static class DumbSleepHandler implements PlatformRunnable {
+ private final AsyncCallback callback;
+ private DumbSleepHandler(AsyncCallback callback) {
+ this.callback = callback;
+ }
+ @Override
+ public void run() {
+ callback.complete(null);
+ }
+ }
+
+ private static boolean hasCheckedImmediateContinue = false;
+ private static MessageChannel immediateContinueChannel = null;
+ private static Runnable currentContinueHack = null;
+ private static final JSString emptyJSString = JSString.valueOf("");
+
+ public static void immediateContinue() {
+ if(!hasCheckedImmediateContinue) {
+ hasCheckedImmediateContinue = true;
+ checkImmediateContinueSupport();
+ }
+ if(immediateContinueChannel != null) {
+ immediateContinueTeaVM();
+ }else {
+ sleep(0);
+ }
+ }
+
+ @Async
+ private static native void immediateContinueTeaVM();
+
+ private static void immediateContinueTeaVM(final AsyncCallback cb) {
+ if(currentContinueHack != null) {
+ cb.error(new IllegalStateException("Worker thread is already waiting for an immediate continue callback!"));
+ return;
+ }
+ currentContinueHack = () -> {
+ cb.complete(null);
+ };
+ try {
+ immediateContinueChannel.getPort2().postMessage(emptyJSString);
+ }catch(Throwable t) {
+ System.err.println("Caught error posting immediate continue, using setTimeout instead");
+ Window.setTimeout(() -> cb.complete(null), 0);
+ }
+ }
+
+ private static void checkImmediateContinueSupport() {
+ try {
+ immediateContinueChannel = null;
+ if(!MessageChannel.supported()) {
+ System.err.println("Fast immediate continue will be disabled for server context due to MessageChannel being unsupported");
+ return;
+ }
+ immediateContinueChannel = new MessageChannel();
+ immediateContinueChannel.getPort1().addEventListener("message", new EventListener() {
+ @Override
+ public void handleEvent(MessageEvent evt) {
+ Runnable toRun = currentContinueHack;
+ currentContinueHack = null;
+ if(toRun != null) {
+ toRun.run();
+ }
+ }
+ });
+ immediateContinueChannel.getPort1().start();
+ immediateContinueChannel.getPort2().start();
+ final boolean[] checkMe = new boolean[1];
+ checkMe[0] = false;
+ currentContinueHack = () -> {
+ checkMe[0] = true;
+ };
+ immediateContinueChannel.getPort2().postMessage(emptyJSString);
+ if(checkMe[0]) {
+ currentContinueHack = null;
+ if(immediateContinueChannel != null) {
+ safeShutdownChannel(immediateContinueChannel);
+ }
+ immediateContinueChannel = null;
+ System.err.println("Fast immediate continue will be disabled for server context due to actually continuing immediately");
+ return;
+ }
+ sleep(10);
+ currentContinueHack = null;
+ if(!checkMe[0]) {
+ if(immediateContinueChannel != null) {
+ safeShutdownChannel(immediateContinueChannel);
+ }
+ immediateContinueChannel = null;
+ System.err.println("Fast immediate continue will be disabled for server context due to startup check failing");
+ }
+ }catch(Throwable t) {
+ System.err.println("Fast immediate continue will be disabled for server context due to exceptions");
+ if(immediateContinueChannel != null) {
+ safeShutdownChannel(immediateContinueChannel);
+ }
+ immediateContinueChannel = null;
+ }
+ }
+
+ private static void safeShutdownChannel(MessageChannel chan) {
+ try {
+ chan.getPort1().close();
+ }catch(Throwable tt) {
+ }
+ try {
+ chan.getPort2().close();
+ }catch(Throwable tt) {
+ }
+ }
+
+}
diff --git a/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/TeaVMUtils.java b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/TeaVMUtils.java
new file mode 100644
index 0000000..9f1a3d1
--- /dev/null
+++ b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/TeaVMUtils.java
@@ -0,0 +1,93 @@
+package net.lax1dude.eaglercraft.sp;
+
+import org.teavm.backend.javascript.spi.GeneratedBy;
+import org.teavm.backend.javascript.spi.InjectedBy;
+import org.teavm.jso.typedarrays.ArrayBuffer;
+import org.teavm.jso.typedarrays.ArrayBufferView;
+import org.teavm.jso.typedarrays.Float32Array;
+import org.teavm.jso.typedarrays.Int16Array;
+import org.teavm.jso.typedarrays.Int32Array;
+import org.teavm.jso.typedarrays.Int8Array;
+import org.teavm.jso.typedarrays.Uint8Array;
+
+public class TeaVMUtils {
+
+ @InjectedBy(TeaVMUtilsUnwrapGenerator.UnwrapTypedArray.class)
+ public static native Int8Array unwrapByteArray(byte[] buf);
+
+ @InjectedBy(TeaVMUtilsUnwrapGenerator.UnwrapArrayBuffer.class)
+ public static native ArrayBuffer unwrapArrayBuffer(byte[] buf);
+
+ @InjectedBy(TeaVMUtilsUnwrapGenerator.UnwrapTypedArray.class)
+ public static native ArrayBufferView unwrapArrayBufferView(byte[] buf);
+
+ @GeneratedBy(TeaVMUtilsUnwrapGenerator.WrapTypedArray.class)
+ public static native byte[] wrapByteArray(Int8Array buf);
+
+ @GeneratedBy(TeaVMUtilsUnwrapGenerator.WrapArrayBuffer.class)
+ public static native byte[] wrapByteArrayBuffer(ArrayBuffer buf);
+
+ @GeneratedBy(TeaVMUtilsUnwrapGenerator.WrapArrayBufferView.class)
+ public static native byte[] wrapByteArrayBufferView(ArrayBufferView buf);
+
+ @InjectedBy(TeaVMUtilsUnwrapGenerator.UnwrapUnsignedTypedArray.class)
+ public static native Uint8Array unwrapUnsignedByteArray(byte[] buf);
+
+ @GeneratedBy(TeaVMUtilsUnwrapGenerator.WrapArrayBufferView.class)
+ public static native byte[] wrapUnsignedByteArray(Uint8Array buf);
+
+ @InjectedBy(TeaVMUtilsUnwrapGenerator.UnwrapTypedArray.class)
+ public static native Int32Array unwrapIntArray(int[] buf);
+
+ @InjectedBy(TeaVMUtilsUnwrapGenerator.UnwrapArrayBuffer.class)
+ public static native ArrayBuffer unwrapArrayBuffer(int[] buf);
+
+ @InjectedBy(TeaVMUtilsUnwrapGenerator.UnwrapTypedArray.class)
+ public static native ArrayBufferView unwrapArrayBufferView(int[] buf);
+
+ @GeneratedBy(TeaVMUtilsUnwrapGenerator.WrapTypedArray.class)
+ public static native int[] wrapIntArray(Int32Array buf);
+
+ @GeneratedBy(TeaVMUtilsUnwrapGenerator.WrapArrayBuffer.class)
+ public static native int[] wrapIntArrayBuffer(ArrayBuffer buf);
+
+ @GeneratedBy(TeaVMUtilsUnwrapGenerator.WrapArrayBufferView.class)
+ public static native int[] wrapIntArrayBufferView(ArrayBufferView buf);
+
+ @InjectedBy(TeaVMUtilsUnwrapGenerator.UnwrapTypedArray.class)
+ public static native Float32Array unwrapFloatArray(float[] buf);
+
+ @InjectedBy(TeaVMUtilsUnwrapGenerator.UnwrapArrayBuffer.class)
+ public static native ArrayBuffer unwrapArrayBuffer(float[] buf);
+
+ @InjectedBy(TeaVMUtilsUnwrapGenerator.UnwrapTypedArray.class)
+ public static native ArrayBufferView unwrapArrayBufferView(float[] buf);
+
+ @GeneratedBy(TeaVMUtilsUnwrapGenerator.WrapTypedArray.class)
+ public static native float[] wrapFloatArray(Float32Array buf);
+
+ @GeneratedBy(TeaVMUtilsUnwrapGenerator.WrapArrayBuffer.class)
+ public static native float[] wrapFloatArrayBuffer(ArrayBuffer buf);
+
+ @GeneratedBy(TeaVMUtilsUnwrapGenerator.WrapArrayBufferView.class)
+ public static native float[] wrapFloatArrayBufferView(ArrayBufferView buf);
+
+ @InjectedBy(TeaVMUtilsUnwrapGenerator.UnwrapTypedArray.class)
+ public static native Int16Array unwrapShortArray(short[] buf);
+
+ @InjectedBy(TeaVMUtilsUnwrapGenerator.UnwrapArrayBuffer.class)
+ public static native ArrayBuffer unwrapArrayBuffer(short[] buf);
+
+ @InjectedBy(TeaVMUtilsUnwrapGenerator.UnwrapTypedArray.class)
+ public static native ArrayBufferView unwrapArrayBufferView(short[] buf);
+
+ @GeneratedBy(TeaVMUtilsUnwrapGenerator.WrapTypedArray.class)
+ public static native short[] wrapShortArray(Int16Array buf);
+
+ @GeneratedBy(TeaVMUtilsUnwrapGenerator.WrapArrayBuffer.class)
+ public static native short[] wrapShortArrayBuffer(ArrayBuffer buf);
+
+ @GeneratedBy(TeaVMUtilsUnwrapGenerator.WrapArrayBufferView.class)
+ public static native short[] wrapShortArrayBuffer(ArrayBufferView buf);
+
+}
diff --git a/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/TeaVMUtilsUnwrapGenerator.java b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/TeaVMUtilsUnwrapGenerator.java
new file mode 100644
index 0000000..6358d93
--- /dev/null
+++ b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/TeaVMUtilsUnwrapGenerator.java
@@ -0,0 +1,158 @@
+package net.lax1dude.eaglercraft.sp;
+
+import org.teavm.backend.javascript.codegen.SourceWriter;
+import org.teavm.backend.javascript.spi.Generator;
+import org.teavm.backend.javascript.spi.GeneratorContext;
+import org.teavm.backend.javascript.spi.Injector;
+import org.teavm.backend.javascript.spi.InjectorContext;
+import org.teavm.model.MethodReference;
+
+public class TeaVMUtilsUnwrapGenerator {
+
+ // WARNING: This code uses internal TeaVM APIs that may not have
+ // been intended for end users of the compiler to program with
+
+ public static class UnwrapArrayBuffer implements Injector {
+
+ @Override
+ public void generate(InjectorContext context, MethodReference methodRef) {
+ context.writeExpr(context.getArgument(0));
+ context.getWriter().append(".data.buffer");
+ }
+
+ }
+
+ public static class UnwrapTypedArray implements Injector {
+
+ @Override
+ public void generate(InjectorContext context, MethodReference methodRef) {
+ context.writeExpr(context.getArgument(0));
+ context.getWriter().append(".data");
+ }
+
+ }
+
+ public static class WrapArrayBuffer implements Generator {
+
+ @Override
+ public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) {
+ String parName = context.getParameterName(1);
+ switch (methodRef.getName()) {
+ case "wrapByteArrayBuffer":
+ writer.append("return ").append(parName).ws().append('?').ws();
+ writer.appendFunction("$rt_wrapArray").append('(').appendFunction("$rt_bytecls").append(',').ws();
+ writer.append("new Int8Array(").append(parName).append("))").ws();
+ writer.append(':').ws().append("null;").softNewLine();
+ break;
+ case "wrapIntArrayBuffer":
+ writer.append("return ").append(parName).ws().append('?').ws();
+ writer.appendFunction("$rt_wrapArray").append('(').appendFunction("$rt_intcls").append(',').ws();
+ writer.append("new Int32Array(").append(parName).append("))").ws();
+ writer.append(':').ws().append("null;").softNewLine();
+ break;
+ case "wrapFloatArrayBuffer":
+ writer.append("return ").append(parName).ws().append('?').ws();
+ writer.appendFunction("$rt_wrapArray").append('(').appendFunction("$rt_floatcls").append(',').ws();
+ writer.append("new Float32Array(").append(parName).append("))").ws();
+ writer.append(':').ws().append("null;").softNewLine();
+ break;
+ case "wrapShortArrayBuffer":
+ writer.append("return ").append(parName).ws().append('?').ws();
+ writer.appendFunction("$rt_wrapArray").append('(').appendFunction("$rt_shortcls").append(',').ws();
+ writer.append("new Int16Array(").append(parName).append("))").ws();
+ writer.append(':').ws().append("null;").softNewLine();
+ break;
+ default:
+ break;
+ }
+ }
+
+ }
+
+ public static class WrapArrayBufferView implements Generator {
+
+ @Override
+ public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) {
+ String parName = context.getParameterName(1);
+ switch (methodRef.getName()) {
+ case "wrapByteArrayBufferView":
+ case "wrapUnsignedByteArray":
+ writer.append("return ").append(parName).ws().append('?').ws();
+ writer.appendFunction("$rt_wrapArray").append('(').appendFunction("$rt_bytecls").append(',').ws();
+ writer.append("new Int8Array(").append(parName).append(".buffer))").ws();
+ writer.append(':').ws().append("null;").softNewLine();
+ break;
+ case "wrapIntArrayBufferView":
+ writer.append("return ").append(parName).ws().append('?').ws();
+ writer.appendFunction("$rt_wrapArray").append('(').appendFunction("$rt_intcls").append(',').ws();
+ writer.append("new Int32Array(").append(parName).append(".buffer))").ws();
+ writer.append(':').ws().append("null;").softNewLine();
+ break;
+ case "wrapFloatArrayBufferView":
+ writer.append("return ").append(parName).ws().append('?').ws();
+ writer.appendFunction("$rt_wrapArray").append('(').appendFunction("$rt_floatcls").append(',').ws();
+ writer.append("new Float32Array(").append(parName).append(".buffer))").ws();
+ writer.append(':').ws().append("null;").softNewLine();
+ break;
+ case "wrapShortArrayBufferView":
+ writer.append("return ").append(parName).ws().append('?').ws();
+ writer.appendFunction("$rt_wrapArray").append('(').appendFunction("$rt_shortcls").append(',').ws();
+ writer.append("new Int16Array(").append(parName).append(".buffer))").ws();
+ writer.append(':').ws().append("null;").softNewLine();
+ break;
+ default:
+ break;
+ }
+ }
+
+ }
+
+ public static class WrapTypedArray implements Generator {
+
+ @Override
+ public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) {
+ String parName = context.getParameterName(1);
+ switch (methodRef.getName()) {
+ case "wrapByteArray":
+ writer.append("return ").append(parName).ws().append('?').ws();
+ writer.appendFunction("$rt_wrapArray").append('(').appendFunction("$rt_shortcls").append(',').ws();
+ writer.append(parName).append(")").ws();
+ writer.append(':').ws().append("null;").softNewLine();
+ break;
+ case "wrapIntArray":
+ writer.append("return ").append(parName).ws().append('?').ws();
+ writer.appendFunction("$rt_wrapArray").append('(').appendFunction("$rt_intcls").append(',').ws();
+ writer.append(parName).append(")").ws();
+ writer.append(':').ws().append("null;").softNewLine();
+ break;
+ case "wrapFloatArray":
+ writer.append("return ").append(parName).ws().append('?').ws();
+ writer.appendFunction("$rt_wrapArray").append('(').appendFunction("$rt_floatcls").append(',').ws();
+ writer.append(parName).append(")").ws();
+ writer.append(':').ws().append("null;").softNewLine();
+ break;
+ case "wrapShortArray":
+ writer.append("return ").append(parName).ws().append('?').ws();
+ writer.appendFunction("$rt_wrapArray").append('(').appendFunction("$rt_shortcls").append(',').ws();
+ writer.append(parName).append(")").ws();
+ writer.append(':').ws().append("null;").softNewLine();
+ break;
+ default:
+ break;
+ }
+ }
+
+ }
+
+ public static class UnwrapUnsignedTypedArray implements Injector {
+
+ @Override
+ public void generate(InjectorContext context, MethodReference methodRef) {
+ context.getWriter().append("new Uint8Array(");
+ context.writeExpr(context.getArgument(0));
+ context.getWriter().append(".data.buffer)");
+ }
+
+ }
+
+}
diff --git a/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/VFSChunkLoader.java b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/VFSChunkLoader.java
new file mode 100644
index 0000000..d52f920
--- /dev/null
+++ b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/VFSChunkLoader.java
@@ -0,0 +1,307 @@
+package net.lax1dude.eaglercraft.sp;
+
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
+
+import net.minecraft.src.Chunk;
+import net.minecraft.src.ChunkCoordIntPair;
+import net.minecraft.src.CompressedStreamTools;
+import net.minecraft.src.Entity;
+import net.minecraft.src.EntityList;
+import net.minecraft.src.ExtendedBlockStorage;
+import net.minecraft.src.IChunkLoader;
+import net.minecraft.src.MinecraftException;
+import net.minecraft.src.NBTTagCompound;
+import net.minecraft.src.NBTTagList;
+import net.minecraft.src.NextTickListEntry;
+import net.minecraft.src.NibbleArray;
+import net.minecraft.src.TileEntity;
+import net.minecraft.src.World;
+
+public class VFSChunkLoader implements IChunkLoader {
+
+ public final VFile chunkDirectory;
+
+ private static final String hex = "0123456789ABCDEF";
+
+ public static String getChunkPath(int x, int z) {
+ int unsignedX = x + 1900000;
+ int unsignedZ = z + 1900000;
+
+ char[] path = new char[12];
+ for(int i = 5; i >= 0; --i) {
+ path[i] = hex.charAt((unsignedX >> (i * 4)) & 0xF);
+ path[i + 6] = hex.charAt((unsignedZ >> (i * 4)) & 0xF);
+ }
+
+ return new String(path);
+ }
+
+ public static ChunkCoordIntPair getChunkCoords(String filename) {
+ String strX = filename.substring(0, 6);
+ String strZ = filename.substring(6);
+
+ int retX = 0;
+ int retZ = 0;
+
+ for(int i = 0; i < 6; ++i) {
+ retX |= hex.indexOf(strX.charAt(i)) << (i << 2);
+ retZ |= hex.indexOf(strZ.charAt(i)) << (i << 2);
+ }
+
+ return new ChunkCoordIntPair(retX - 1900000, retZ - 1900000);
+ }
+
+ public VFSChunkLoader(VFile chunkDirectory) {
+ this.chunkDirectory = chunkDirectory;
+ }
+
+ @Override
+ public Chunk loadChunk(World var1, int var2, int var3) throws IOException {
+ VFile file = new VFile(chunkDirectory, getChunkPath(var2, var3) + ".dat");
+ byte[] bytes = file.getAllBytes();
+
+ if(bytes == null) {
+ return null;
+ }
+
+ try {
+ NBTTagCompound nbt = CompressedStreamTools.decompress(bytes);
+ nbt = nbt.getCompoundTag("Level");
+ return readChunkFromNBT(var1, nbt, var2, var3);
+ }catch(Throwable t) {
+ file.delete();
+ System.err.println("Corrupted chunk has been deleted: [" + var2 + ", " + var3 + "]");
+ t.printStackTrace();
+ return null;
+ }
+ }
+
+ @Override
+ public void saveChunk(World var1, Chunk var2) throws MinecraftException, IOException {
+
+ NBTTagCompound chunkFile = new NBTTagCompound();
+ this.writeChunkToNBT(var2, var1, chunkFile);
+
+ byte[] save;
+
+ try {
+ NBTTagCompound chunkFileSave = new NBTTagCompound();
+ chunkFileSave.setCompoundTag("Level", chunkFile);
+ save = CompressedStreamTools.compressChunk(chunkFileSave);
+ }catch(IOException e) {
+ System.err.println("Corrupted chunk could not be serialized: [" + var2.xPosition + ", " + var2.zPosition + "]");
+ return;
+ }
+
+ VFile file = new VFile(chunkDirectory, getChunkPath(var2.xPosition, var2.zPosition) + ".dat");
+
+ if(!file.setAllBytes(save)) {
+ System.err.println("Corrupted chunk could not be written: [" + var2.xPosition + ", " + var2.zPosition + "] to file \"" + file.toString() + "\")");
+ }
+
+ }
+
+ @Override
+ public void saveExtraChunkData(World var1, Chunk var2) {
+ // ?
+ }
+
+ @Override
+ public void chunkTick() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void saveExtraData() {
+ // unused
+ }
+
+ private Chunk readChunkFromNBT(World par1World, NBTTagCompound par2NBTTagCompound, int x, int z) {
+ int var3 = x; //par2NBTTagCompound.getInteger("xPos");
+ int var4 = z; //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;
+ }
+
+ 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);
+ }
+ }
+
+}
diff --git a/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/VFSIterator.java b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/VFSIterator.java
new file mode 100644
index 0000000..a8d12c7
--- /dev/null
+++ b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/VFSIterator.java
@@ -0,0 +1,17 @@
+package net.lax1dude.eaglercraft.sp;
+
+public interface VFSIterator {
+
+ public static class BreakLoop extends RuntimeException {
+ public BreakLoop() {
+ super("iterator loop break request");
+ }
+ }
+
+ public default void end() {
+ throw new BreakLoop();
+ }
+
+ public void next(VIteratorFile entry);
+
+}
diff --git a/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/VFSSaveFormat.java b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/VFSSaveFormat.java
new file mode 100644
index 0000000..6a1515d
--- /dev/null
+++ b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/VFSSaveFormat.java
@@ -0,0 +1,39 @@
+package net.lax1dude.eaglercraft.sp;
+
+import net.minecraft.src.IProgressUpdate;
+import net.minecraft.src.ISaveFormat;
+import net.minecraft.src.ISaveHandler;
+
+public class VFSSaveFormat implements ISaveFormat {
+
+ private VFSSaveHandler folder;
+
+ public VFSSaveFormat(VFSSaveHandler dir) {
+ folder = dir;
+ }
+
+ @Override
+ public ISaveHandler getSaveLoader(String var1, boolean var2) {
+ return folder;
+ }
+
+ @Override
+ public void flushCache() {
+ }
+
+ @Override
+ public boolean deleteWorldDirectory(String var1) {
+ return true;
+ }
+
+ @Override
+ public boolean isOldMapFormat(String var1) {
+ return false;
+ }
+
+ @Override
+ public boolean convertMapFormat(String var1, IProgressUpdate var2) {
+ return false;
+ }
+
+}
diff --git a/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/VFSSaveHandler.java b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/VFSSaveHandler.java
new file mode 100644
index 0000000..a4c8927
--- /dev/null
+++ b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/VFSSaveHandler.java
@@ -0,0 +1,172 @@
+package net.lax1dude.eaglercraft.sp;
+
+import java.io.IOException;
+import java.util.HashMap;
+
+import net.minecraft.src.CompressedStreamTools;
+import net.minecraft.src.EntityPlayer;
+import net.minecraft.src.IChunkLoader;
+import net.minecraft.src.IPlayerFileData;
+import net.minecraft.src.ISaveHandler;
+import net.minecraft.src.MinecraftException;
+import net.minecraft.src.NBTTagCompound;
+import net.minecraft.src.WorldInfo;
+import net.minecraft.src.WorldProvider;
+
+public class VFSSaveHandler implements ISaveHandler, IPlayerFileData {
+
+ public final VFile worldDirectory;
+
+ private final HashMap chunkLoaders = new HashMap<>();
+
+ public VFSSaveHandler(VFile worldDirectory) {
+ this.worldDirectory = worldDirectory;
+ }
+
+ @Override
+ public WorldInfo loadWorldInfo() {
+
+ byte[] level_dat_bin = (new VFile(worldDirectory, "level.dat")).getAllBytes();
+
+ if(level_dat_bin == null) {
+ return null;
+ }
+
+ try {
+ NBTTagCompound level_dat = CompressedStreamTools.decompress(level_dat_bin);
+ return new WorldInfo(level_dat.getCompoundTag("Data"));
+ }catch(Throwable t) {
+ System.err.println("Could not parse level.dat!");
+ t.printStackTrace();
+ }
+
+ return null;
+ }
+
+ @Override
+ public void checkSessionLock() throws MinecraftException {
+ // no
+ }
+
+ @Override
+ public IChunkLoader getChunkLoader(WorldProvider var1) {
+ VFSChunkLoader loader = chunkLoaders.get(var1.dimensionId);
+
+ if(loader == null) {
+ loader = new VFSChunkLoader(new VFile(worldDirectory, "level" + var1.dimensionId));
+ chunkLoaders.put(var1.dimensionId, loader);
+ }
+
+ return loader;
+ }
+
+ @Override
+ public void saveWorldInfoWithPlayer(WorldInfo var1, NBTTagCompound var2) {
+ NBTTagCompound var3 = var2 != null ? var1.cloneNBTCompound(var2) : var1.getNBTTagCompound();
+ NBTTagCompound var4 = new NBTTagCompound();
+ var4.setTag("Data", var3);
+
+ VFile level_dat = new VFile(worldDirectory, "level.dat");
+
+ byte[] compressed;
+
+ try {
+ compressed = CompressedStreamTools.compress(var4);
+ }catch(IOException e) {
+ System.err.println("Could not serialize \"" + level_dat + "\"");
+ e.printStackTrace();
+ return;
+ }
+
+ if(!level_dat.setAllBytes(compressed)) {
+ System.err.println("Could not save \"" + level_dat + "\" to filesystem");
+ }
+ }
+
+ @Override
+ public void saveWorldInfo(WorldInfo var1) {
+ saveWorldInfoWithPlayer(var1, null);
+ }
+
+ @Override
+ public IPlayerFileData getPlayerNBTManager() {
+ return this;
+ }
+
+ @Override
+ public void flush() {
+
+ }
+
+ @Override
+ public VFile getMapFileFromName(String var1) {
+ return new VFile(worldDirectory, "data", var1 + ".dat");
+ }
+
+ @Override
+ public String getWorldDirectoryName() {
+ return worldDirectory.toString();
+ }
+
+ @Override
+ public void writePlayerData(EntityPlayer var1) {
+ NBTTagCompound var2 = new NBTTagCompound();
+ var1.writeToNBT(var2);
+
+ byte[] bin;
+
+ try {
+ bin = CompressedStreamTools.compress(var2);
+ }catch(Throwable t) {
+ System.err.println("Could not serialize player data for \"" + var1.username + "\"");
+ t.printStackTrace();
+ return;
+ }
+
+ VFile playerData = new VFile(worldDirectory, "player", var1.username.toLowerCase() + ".dat");
+
+ if(!playerData.setAllBytes(bin)) {
+ System.err.println("Could not write player data for \"" + var1.username + "\" to file \"" + playerData.toString() + "\"");
+ }
+ }
+
+ @Override
+ public NBTTagCompound readPlayerData(EntityPlayer var1) {
+ VFile playerData = new VFile(worldDirectory, "player", var1.username.toLowerCase() + ".dat");
+
+ NBTTagCompound ret = null;
+
+ byte[] playerBin = playerData.getAllBytes();
+ if(playerBin != null) {
+ try {
+ ret = CompressedStreamTools.decompress(playerBin);
+ var1.readFromNBT(ret);
+ }catch(IOException e) {
+ System.err.println("Could not deserialize player data for \"" + var1.username + "\"");
+ e.printStackTrace();
+ }
+ }
+
+ return ret;
+ }
+
+ @Override
+ public String[] getAvailablePlayerDat() {
+ return null;
+ }
+
+ public static String worldNameToFolderName(String par1Str) {
+ par1Str = par1Str.replaceAll("[\\./\"]", "_");
+
+ boolean shit = true;
+ while(shit) {
+ shit = (new VFile("worlds", par1Str, "level.dat")).exists();
+ if(shit) {
+ par1Str = par1Str + "_";
+ }
+ }
+
+ return par1Str;
+ }
+
+}
diff --git a/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/VFSTestClass.java b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/VFSTestClass.java
new file mode 100644
index 0000000..e354489
--- /dev/null
+++ b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/VFSTestClass.java
@@ -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);
+ }
+
+}
diff --git a/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/VFile.java b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/VFile.java
new file mode 100644
index 0000000..f07daa5
--- /dev/null
+++ b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/VFile.java
@@ -0,0 +1,227 @@
+package net.lax1dude.eaglercraft.sp;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+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(1);
+ }
+ 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;
+ }
+
+ protected String path;
+
+ public static String createPath(Object... p) {
+ ArrayList 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.lastIndexOf(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, boolean copy) {
+ if(!isRelative() && SYS.VFS.renameFile(path, p, copy)) {
+ 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);
+ }
+
+ public List list() {
+ if(isRelative()) {
+ return Arrays.asList(path);
+ }
+ return SYS.VFS.listFiles(path);
+ }
+
+ public int deleteAll() {
+ return isRelative() ? 0 : SYS.VFS.deleteFiles(path);
+ }
+
+}
diff --git a/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/VIteratorFile.java b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/VIteratorFile.java
new file mode 100644
index 0000000..5ba3d8b
--- /dev/null
+++ b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/VIteratorFile.java
@@ -0,0 +1,289 @@
+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.util.List;
+
+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.IDBCursor;
+import org.teavm.jso.indexeddb.IDBRequest;
+import org.teavm.jso.typedarrays.ArrayBuffer;
+import org.teavm.jso.typedarrays.Uint8Array;
+
+/**
+ * Do not use an instance of this class outside of the VFSIterator.next() method
+ */
+public class VIteratorFile extends VFile {
+
+ static final VIteratorFile instance = new VIteratorFile();
+
+ private VIteratorFile() {
+ super("");
+ this.idx = -1;
+ this.cur = null;
+ this.vfs = null;
+ }
+
+ private static class VirtualIteratorOutputStream extends ByteArrayOutputStream {
+
+ private final VIteratorFile itr;
+
+ protected VirtualIteratorOutputStream(VIteratorFile itr) {
+ this.itr = itr;
+ }
+
+ public void close() throws IOException {
+ if(!itr.setAllBytes(super.toByteArray(), false)) {
+ throw new IOException("Could not close stream and write to \"" + itr.path + "\" on VFS \"" + itr.vfs.database + "\" (the file was probably deleted)");
+ }
+ }
+
+ }
+
+ private int idx;
+ private IDBCursor cur;
+ private VirtualFilesystem vfs;
+ private boolean wasDeleted;
+
+ @JSBody(params = { "k" }, script = "return ((typeof k) === \"string\") ? k : (((typeof k) === \"undefined\") ? null : (((typeof k[0]) === \"string\") ? k[0] : null));")
+ private static native String readKey(JSObject k);
+
+ static VIteratorFile create(int idx, VirtualFilesystem vfs, IDBCursor cur) {
+ String k = readKey(cur.getKey());
+ if(k == null) {
+ return null;
+ }
+ instance.update(idx, k, vfs, cur);
+ return instance;
+ }
+
+ public VFile makeVFile() {
+ return new VFile(path);
+ }
+
+ private void update(int idx, String path, VirtualFilesystem vfs, IDBCursor cur) {
+ this.idx = idx;
+ this.path = path;
+ this.vfs = vfs;
+ this.cur = cur;
+ this.wasDeleted = false;
+ }
+
+ public InputStream getInputStream() {
+ return !wasDeleted ? new ByteArrayInputStream(getAllBytes()) : null;
+ }
+
+ public OutputStream getOutputStream() {
+ return !wasDeleted ? new VirtualIteratorOutputStream(this) : null;
+ }
+
+ public String toString() {
+ return path;
+ }
+
+ public boolean isRelative() {
+ return false;
+ }
+
+ public boolean canRead() {
+ return !wasDeleted;
+ }
+
+ public String getPath() {
+ return 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 !wasDeleted;
+ }
+
+ 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 !wasDeleted;
+ }
+
+ public boolean delete() {
+ return wasDeleted = AsyncHandlers.awaitRequest(cur.delete()).bool;
+ }
+
+ public boolean renameTo(String p) {
+ byte[] data = getAllBytes();
+ String op = path;
+ path = p;
+ if(!setAllBytes(data)) {
+ path = op;
+ return false;
+ }
+ path = op;
+ if(!delete()) {
+ return false;
+ }
+ path = p;
+ return true;
+ }
+
+ public int length() {
+ JSObject obj = cur.getValue();
+
+ if(obj == null) {
+ throw new RuntimeException("Value of entry is missing");
+ }
+
+ ArrayBuffer arr = readRow(obj);
+
+ if(arr == null) {
+ throw new RuntimeException("Value of the fucking value of the entry is missing");
+ }
+
+ return arr.getByteLength();
+ }
+
+ public void getBytes(int fileOffset, byte[] array, int offset, int length) {
+ JSObject obj = cur.getValue();
+
+ if(obj == null) {
+ throw new ArrayIndexOutOfBoundsException("Value of entry is missing");
+ }
+
+ ArrayBuffer arr = readRow(obj);
+
+ if(arr == null) {
+ throw new ArrayIndexOutOfBoundsException("Value of the fucking value of the entry is missing");
+ }
+
+ Uint8Array a = new Uint8Array(arr);
+
+ if(a.getLength() < fileOffset + length) {
+ throw new ArrayIndexOutOfBoundsException("file '" + path + "' 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() {
+ // no
+ }
+
+ @JSBody(params = { "obj" }, script = "return (typeof obj === 'undefined') ? null : ((typeof obj.data === 'undefined') ? null : obj.data);")
+ private static native ArrayBuffer readRow(JSObject obj);
+
+ public byte[] getAllBytes() {
+ JSObject obj = cur.getValue();
+
+ if(obj == null) {
+ return null;
+ }
+
+ ArrayBuffer arr = readRow(obj);
+
+ if(arr == null) {
+ return null;
+ }
+
+ Uint8Array a = new Uint8Array(arr);
+ int ii = a.getByteLength();
+
+ byte[] array = new byte[ii];
+ for(int i = 0; i < ii; ++i) {
+ array[i] = (byte)a.get(i);
+ }
+
+ return array;
+ }
+
+ public String getAllChars() {
+ return VirtualFilesystem.utf8(getAllBytes());
+ }
+
+ public String[] getAllLines() {
+ return VirtualFilesystem.lines(VirtualFilesystem.utf8(getAllBytes()));
+ }
+
+ public byte[] getAllBytes(boolean copy) {
+ return getAllBytes();
+ }
+
+ public boolean setAllChars(String bytes) {
+ return setAllBytes(VirtualFilesystem.utf8(bytes));
+ }
+
+ public List list() {
+ throw new RuntimeException("Cannot perform list all in VFS callback");
+ }
+
+ public int deleteAll() {
+ throw new RuntimeException("Cannot perform delete all in VFS callback");
+ }
+
+ @JSBody(params = { "pat", "dat" }, script = "return { path: pat, data: dat };")
+ private static native JSObject writeRow(String name, ArrayBuffer data);
+
+ public boolean setAllBytes(byte[] bytes) {
+ ArrayBuffer a = new ArrayBuffer(bytes.length);
+ Uint8Array ar = new Uint8Array(a);
+ ar.set(bytes);
+ JSObject obj = writeRow(path, a);
+ BooleanResult r = AsyncHandlers.awaitRequest(cur.update(obj));
+ return r.bool;
+ }
+
+ public boolean setAllBytes(byte[] bytes, boolean copy) {
+ return setAllBytes(bytes);
+ }
+
+ public static class AsyncHandlers {
+
+ @Async
+ public static native BooleanResult awaitRequest(IDBRequest r);
+
+ private static void awaitRequest(IDBRequest r, final AsyncCallback cb) {
+ r.addEventListener("success", new EventListener() {
+ @Override
+ public void handleEvent(Event evt) {
+ cb.complete(BooleanResult._new(true));
+ }
+ });
+ r.addEventListener("error", new EventListener() {
+ @Override
+ public void handleEvent(Event evt) {
+ cb.complete(BooleanResult._new(false));
+ }
+ });
+ }
+
+ }
+
+}
diff --git a/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/VirtualFilesystem.java b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/VirtualFilesystem.java
new file mode 100644
index 0000000..c441824
--- /dev/null
+++ b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/VirtualFilesystem.java
@@ -0,0 +1,688 @@
+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.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+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.EventListener;
+import org.teavm.jso.indexeddb.EventHandler;
+import org.teavm.jso.indexeddb.IDBCountRequest;
+import org.teavm.jso.indexeddb.IDBCursor;
+import org.teavm.jso.indexeddb.IDBCursorRequest;
+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.Int8Array;
+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 = SysUtil.steadyTimeMillis();
+ 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 = SysUtil.steadyTimeMillis();
+ 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 = SysUtil.steadyTimeMillis();
+ 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");
+ }
+ this.fileSize = aa.getByteLength();
+ if(cacheEnabled) {
+ cache = TeaVMUtils.wrapByteArrayBuffer(aa);
+ }
+ if(fileSize < fileOffset + length) {
+ throw new ArrayIndexOutOfBoundsException("file '" + filePath + "' size was "+fileSize+" but user tried to read index "+(fileOffset + length - 1));
+ }
+ TeaVMUtils.unwrapByteArray(array).set(new Int8Array(aa, fileOffset, length), offset);
+ }
+ }
+
+ public void setCacheEnabled() {
+ if(!cacheEnabled && !hasBeenDeleted && !(hasBeenAccessed && !exists)) {
+ cacheHit = SysUtil.steadyTimeMillis();
+ 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 = SysUtil.steadyTimeMillis();
+ 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;
+ }
+ this.fileSize = b.getByteLength();
+ if(cacheEnabled) {
+ if(copy) {
+ cache = new byte[fileSize];
+ TeaVMUtils.unwrapByteArray(cache).set(new Int8Array(b));
+ }else {
+ cache = TeaVMUtils.wrapByteArrayBuffer(b);
+ }
+ }
+ return TeaVMUtils.wrapByteArrayBuffer(b);
+ }
+ }
+
+ 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 = SysUtil.steadyTimeMillis();
+ 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 {
+ boolean s = AsyncHandlers.writeWholeFile(virtualFilesystem.indexeddb, filePath,
+ TeaVMUtils.unwrapArrayBuffer(bytes)).bool;
+ hasBeenAccessed = true;
+ exists = exists || s;
+ return s;
+ }
+ }
+
+ public boolean sync() {
+ if(cacheEnabled && cache != null && !hasBeenDeleted) {
+ cacheHit = SysUtil.steadyTimeMillis();
+ boolean tryWrite = AsyncHandlers.writeWholeFile(virtualFilesystem.indexeddb, filePath,
+ TeaVMUtils.unwrapArrayBuffer(cache)).bool;
+ hasBeenAccessed = true;
+ exists = exists || tryWrite;
+ return tryWrite;
+ }
+ return false;
+ }
+
+ public boolean delete() {
+ if(!hasBeenDeleted && !(hasBeenAccessed && !exists)) {
+ cacheHit = SysUtil.steadyTimeMillis();
+ 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, boolean copy) {
+ if(!hasBeenDeleted && !(hasBeenAccessed && !exists)) {
+ cacheHit = SysUtil.steadyTimeMillis();
+ 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(!copy && !AsyncHandlers.deleteFile(virtualFilesystem.indexeddb, filePath).bool) {
+ return false;
+ }
+ }else {
+ exists = false;
+ }
+ if(!copy) {
+ virtualFilesystem.fileMap.remove(filePath);
+ filePath = newName;
+ virtualFilesystem.fileMap.put(newName, this);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ public boolean exists() {
+ if(hasBeenDeleted) {
+ return false;
+ }
+ cacheHit = SysUtil.steadyTimeMillis();
+ if(hasBeenAccessed) {
+ return exists;
+ }
+ exists = AsyncHandlers.fileExists(virtualFilesystem.indexeddb, filePath).bool;
+ hasBeenAccessed = true;
+ return exists;
+ }
+
+ }
+
+ private final HashMap 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, boolean copy) {
+ return getFile(oldName).rename(newName, copy);
+ }
+
+ public boolean deleteFile(String path) {
+ return getFile(path).delete();
+ }
+
+ public boolean fileExists(String path) {
+ return getFile(path).exists();
+ }
+
+ public List listFiles(String prefix) {
+ final ArrayList list = new ArrayList<>();
+ AsyncHandlers.iterateFiles(indexeddb, this, prefix, false, (v) -> {
+ list.add(v.getPath());
+ });
+ return list;
+ }
+
+ public List listVFiles(String prefix) {
+ final ArrayList list = new ArrayList<>();
+ AsyncHandlers.iterateFiles(indexeddb, this, prefix, false, (v) -> {
+ list.add(new VFile(v.getPath()));
+ });
+ return list;
+ }
+
+ public int deleteFiles(String prefix) {
+ return AsyncHandlers.deleteFiles(indexeddb, prefix);
+ }
+
+ public int iterateFiles(String prefix, boolean rw, VFSIterator itr) {
+ return AsyncHandlers.iterateFiles(indexeddb, this, prefix, rw, itr);
+ }
+
+ public int renameFiles(String oldPrefix, String newPrefix, boolean copy) {
+ List filesToCopy = listFiles(oldPrefix);
+ int i = 0;
+ for(String str : filesToCopy) {
+ String f = VFile.createPath(newPrefix, str.substring(oldPrefix.length()));
+ if(!renameFile(str, f, copy)) {
+ System.err.println("Could not " + (copy ? "copy" : "rename") + " file \"" + str + "\" to \"" + f + "\" for some reason");
+ }else {
+ ++i;
+ }
+ }
+ return i;
+ }
+
+ public void flushCache(long age) {
+ long curr = SysUtil.steadyTimeMillis();
+ Iterator 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;
+ }
+
+ }
+
+ @JSBody(script = "return ((typeof indexedDB) !== 'undefined') ? indexedDB : null;")
+ protected static native IDBFactory createIDBFactory();
+
+ protected static class AsyncHandlers {
+
+ @Async
+ protected static native DatabaseOpen openDB(String name);
+
+ private static void openDB(String name, final AsyncCallback cb) {
+ IDBFactory i = createIDBFactory();
+ if(i == null) {
+ cb.complete(new DatabaseOpen(false, false, "window.indexedDB was null or undefined", null));
+ return;
+ }
+ 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() {
+ @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 cb) {
+ IDBTransaction tx = db.transaction("filesystem", "readwrite");
+ final IDBRequest r = tx.objectStore("filesystem").delete(makeTheFuckingKeyWork(name));
+
+ r.setOnSuccess(new EventHandler() {
+ @Override
+ public void handleEvent() {
+ cb.complete(BooleanResult._new(true));
+ }
+ });
+ r.setOnError(new EventHandler() {
+ @Override
+ public void handleEvent() {
+ 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 cb) {
+ IDBTransaction tx = db.transaction("filesystem", "readonly");
+ final IDBGetRequest r = tx.objectStore("filesystem").get(makeTheFuckingKeyWork(name));
+ r.setOnSuccess(new EventHandler() {
+ @Override
+ public void handleEvent() {
+ cb.complete(readRow(r.getResult()));
+ }
+ });
+ r.setOnError(new EventHandler() {
+ @Override
+ public void handleEvent() {
+ cb.complete(null);
+ }
+ });
+
+ }
+
+ @JSBody(params = { "k" }, script = "return ((typeof k) === \"string\") ? k : (((typeof k) === \"undefined\") ? null : (((typeof k[0]) === \"string\") ? k[0] : null));")
+ private static native String readKey(JSObject k);
+
+ @JSBody(params = { "k" }, script = "return ((typeof k) === \"undefined\") ? null : (((typeof k.path) === \"undefined\") ? null : (((typeof k.path) === \"string\") ? k[0] : null));")
+ private static native String readRowKey(JSObject r);
+
+ @Async
+ protected static native Integer iterateFiles(IDBDatabase db, final VirtualFilesystem vfs, final String prefix, boolean rw, final VFSIterator itr);
+
+ private static void iterateFiles(IDBDatabase db, final VirtualFilesystem vfs, final String prefix, boolean rw, final VFSIterator itr, final AsyncCallback cb) {
+ IDBTransaction tx = db.transaction("filesystem", rw ? "readwrite" : "readonly");
+ final IDBCursorRequest r = tx.objectStore("filesystem").openCursor();
+ final int[] res = new int[1];
+ r.setOnSuccess(new EventHandler() {
+ @Override
+ public void handleEvent() {
+ IDBCursor c = r.getResult();
+ if(c == null || c.getKey() == null || c.getValue() == null) {
+ cb.complete(res[0]);
+ return;
+ }
+ String k = readKey(c.getKey());
+ if(k != null) {
+ if(k.startsWith(prefix)) {
+ int ci = res[0]++;
+ try {
+ itr.next(VIteratorFile.create(ci, vfs, c));
+ }catch(VFSIterator.BreakLoop ex) {
+ cb.complete(res[0]);
+ return;
+ }
+ }
+ }
+ c.doContinue();
+ }
+ });
+ r.setOnError(new EventHandler() {
+ @Override
+ public void handleEvent() {
+ cb.complete(res[0] > 0 ? res[0] : -1);
+ }
+ });
+ }
+
+ @Async
+ protected static native Integer deleteFiles(IDBDatabase db, final String prefix);
+
+ private static void deleteFiles(IDBDatabase db, final String prefix, final AsyncCallback cb) {
+ IDBTransaction tx = db.transaction("filesystem", "readwrite");
+ final IDBCursorRequest r = tx.objectStore("filesystem").openCursor();
+ final int[] res = new int[1];
+ r.setOnSuccess(new EventHandler() {
+ @Override
+ public void handleEvent() {
+ IDBCursor c = r.getResult();
+ if(c == null || c.getKey() == null || c.getValue() == null) {
+ cb.complete(res[0]);
+ return;
+ }
+ String k = readKey(c.getKey());
+ if(k != null) {
+ if(k.startsWith(prefix)) {
+ c.delete();
+ ++res[0];
+ }
+ }
+ c.doContinue();
+ }
+ });
+ r.setOnError(new EventHandler() {
+ @Override
+ public void handleEvent() {
+ cb.complete(res[0] > 0 ? res[0] : -1);
+ }
+ });
+ }
+
+ @Async
+ protected static native BooleanResult fileExists(IDBDatabase db, String name);
+
+ private static void fileExists(IDBDatabase db, String name, final AsyncCallback cb) {
+ IDBTransaction tx = db.transaction("filesystem", "readonly");
+ final IDBCountRequest r = tx.objectStore("filesystem").count(makeTheFuckingKeyWork(name));
+ r.setOnSuccess(new EventHandler() {
+ @Override
+ public void handleEvent() {
+ cb.complete(BooleanResult._new(r.getResult() > 0));
+ }
+ });
+ r.setOnError(new EventHandler() {
+ @Override
+ public void handleEvent() {
+ 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 cb) {
+ IDBTransaction tx = db.transaction("filesystem", "readwrite");
+ final IDBRequest r = tx.objectStore("filesystem").put(writeRow(name, data));
+
+ r.setOnSuccess(new EventHandler() {
+ @Override
+ public void handleEvent() {
+ cb.complete(BooleanResult._new(true));
+ }
+ });
+ r.setOnError(new EventHandler() {
+ @Override
+ public void handleEvent() {
+ 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;
+ str = str.indexOf('\r') != -1 ? str.replace("\r", "") : str;
+ str = str.trim();
+ if(str.endsWith("\n")) {
+ str = str.substring(0, str.length() - 1);
+ }
+ if(str.startsWith("\n")) {
+ str = str.substring(1);
+ }
+ return str;
+ }
+
+ public static String[] lines(String str) {
+ if(str == null) return null;
+ return CRLFtoLF(str).split("\n");
+ }
+
+}
\ No newline at end of file
diff --git a/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/VoiceChatPlugin.java b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/VoiceChatPlugin.java
new file mode 100644
index 0000000..a786875
--- /dev/null
+++ b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/VoiceChatPlugin.java
@@ -0,0 +1,289 @@
+package net.lax1dude.eaglercraft.sp;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Predicate;
+
+import net.minecraft.server.MinecraftServer;
+import net.minecraft.src.EntityPlayerMP;
+import net.minecraft.src.Packet250CustomPayload;
+
+public class VoiceChatPlugin {
+
+ private static final Map voicePlayers = new HashMap<>();
+ private static final Map> voiceRequests = new HashMap<>();
+ private static final Set voicePairs = new HashSet<>();
+
+ private static final List iceServers = new ArrayList<>();
+
+ private static final int VOICE_SIGNAL_ALLOWED = 0;
+ private static final int VOICE_SIGNAL_REQUEST = 0;
+ private static final int VOICE_SIGNAL_CONNECT = 1;
+ private static final int VOICE_SIGNAL_DISCONNECT = 2;
+ private static final int VOICE_SIGNAL_ICE = 3;
+ private static final int VOICE_SIGNAL_DESC = 4;
+ private static final int VOICE_SIGNAL_GLOBAL = 5;
+
+ public static boolean handleMessage(EntityPlayerMP player, Packet250CustomPayload payload) {
+ if ("EAG|Voice".equals(payload.channel) && payload.data.length > 0) {
+ deev: {
+ String user = player.username;
+ byte[] msg = payload.data;
+ try {
+ DataInputStream streamIn = new DataInputStream(new ByteArrayInputStream(msg));
+ int sig = streamIn.read();
+ switch (sig) {
+ case VOICE_SIGNAL_CONNECT:
+ if (voicePlayers.containsKey(user))
+ break deev; // user is already using voice chat
+ // send out packet for player joined voice
+ // notice: everyone on the server can see this packet!! however, it doesn't do
+ // anything but let clients know that the player has turned on voice chat
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ DataOutputStream dos = new DataOutputStream(baos);
+ dos.write(VOICE_SIGNAL_CONNECT);
+ dos.writeUTF(user);
+ byte[] out = baos.toByteArray();
+ for (EntityPlayerMP conn : voicePlayers.values())
+ conn.playerNetServerHandler.sendPacket(new Packet250CustomPayload("EAG|Voice", out));
+ voicePlayers.put(user, player);
+ for (String username : voicePlayers.keySet())
+ sendVoicePlayers(username);
+ break;
+ case VOICE_SIGNAL_DISCONNECT:
+ if (!voicePlayers.containsKey(user))
+ break deev; // user is not using voice chat
+ try {
+ String user2 = streamIn.readUTF();
+ if (!voicePlayers.containsKey(user2))
+ break deev;
+ if (removeIf(voicePairs, pair -> (pair[0].equals(user) && pair[1].equals(user2))
+ || (pair[0].equals(user2) && pair[1].equals(user)))) {
+ ByteArrayOutputStream baos2 = new ByteArrayOutputStream();
+ DataOutputStream dos2 = new DataOutputStream(baos2);
+ dos2.write(VOICE_SIGNAL_DISCONNECT);
+ dos2.writeUTF(user);
+ voicePlayers.get(user2).playerNetServerHandler.sendPacket(
+ new Packet250CustomPayload("EAG|Voice", baos2.toByteArray()));
+ baos2 = new ByteArrayOutputStream();
+ dos2 = new DataOutputStream(baos2);
+ dos2.write(VOICE_SIGNAL_DISCONNECT);
+ dos2.writeUTF(user2);
+ player.playerNetServerHandler.sendPacket(new Packet250CustomPayload("EAG|Voice", baos2.toByteArray()));
+ }
+ } catch (EOFException e) {
+ removeUser(user);
+ }
+ break;
+ case VOICE_SIGNAL_REQUEST:
+ if (!voicePlayers.containsKey(user))
+ break deev; // user is not using voice chat
+ String targetUser = streamIn.readUTF();
+ if (user.equals(targetUser))
+ break deev; // prevent duplicates
+ if (checkVoicePair(user, targetUser))
+ break deev; // already paired
+ if (!voicePlayers.containsKey(targetUser))
+ break deev; // target user is not using voice chat
+ if (!voiceRequests.containsKey(user))
+ voiceRequests.put(user, new ExpiringSet<>(2000));
+ if (voiceRequests.get(user).contains(targetUser))
+ break deev;
+ voiceRequests.get(user).add(targetUser);
+
+ // check if other has requested earlier
+ if (voiceRequests.containsKey(targetUser) && voiceRequests.get(targetUser).contains(user)) {
+ if (voiceRequests.containsKey(targetUser)) {
+ voiceRequests.get(targetUser).remove(user);
+ if (voiceRequests.get(targetUser).isEmpty())
+ voiceRequests.remove(targetUser);
+ }
+ if (voiceRequests.containsKey(user)) {
+ voiceRequests.get(user).remove(targetUser);
+ if (voiceRequests.get(user).isEmpty())
+ voiceRequests.remove(user);
+ }
+ // send each other add data
+ voicePairs.add(new String[] { user, targetUser });
+ ByteArrayOutputStream baos2 = new ByteArrayOutputStream();
+ DataOutputStream dos2 = new DataOutputStream(baos2);
+ dos2.write(VOICE_SIGNAL_CONNECT);
+ dos2.writeUTF(user);
+ dos2.writeBoolean(false);
+ voicePlayers.get(targetUser).playerNetServerHandler.sendPacket(
+ new Packet250CustomPayload("EAG|Voice", baos2.toByteArray()));
+ baos2 = new ByteArrayOutputStream();
+ dos2 = new DataOutputStream(baos2);
+ dos2.write(VOICE_SIGNAL_CONNECT);
+ dos2.writeUTF(targetUser);
+ dos2.writeBoolean(true);
+ player.playerNetServerHandler.sendPacket(new Packet250CustomPayload("EAG|Voice", baos2.toByteArray()));
+ }
+ break;
+ case VOICE_SIGNAL_ICE:
+ case VOICE_SIGNAL_DESC:
+ if (!voicePlayers.containsKey(user))
+ break deev; // user is not using voice chat
+ String targetUser2 = streamIn.readUTF();
+ if (checkVoicePair(user, targetUser2)) {
+ String data = streamIn.readUTF();
+ ByteArrayOutputStream baos2 = new ByteArrayOutputStream();
+ DataOutputStream dos2 = new DataOutputStream(baos2);
+ dos2.write(sig);
+ dos2.writeUTF(user);
+ dos2.writeUTF(data);
+ voicePlayers.get(targetUser2).playerNetServerHandler.sendPacket(new Packet250CustomPayload("EAG|Voice", baos2.toByteArray()));
+ }
+ break;
+ default:
+ break;
+ }
+ } catch (Throwable t) {
+ // hacker
+ // t.printStackTrace(); // todo: remove in production
+ removeUser(user);
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ public static void activate(List ice) {
+ if(iceServers.size() == 0) {
+ iceServers.addAll(ice);
+ for(Object o : MinecraftServer.getServer().getConfigurationManager().playerEntityList) {
+ handleConnect((EntityPlayerMP) o);
+ }
+ }
+ }
+
+ public static void handleConnect(EntityPlayerMP player) {
+ if(iceServers.size() > 0) {
+ try {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ DataOutputStream dos = new DataOutputStream(baos);
+ dos.write(VOICE_SIGNAL_ALLOWED);
+ dos.writeBoolean(true);
+ dos.write(iceServers.size());
+ for (String str : iceServers) {
+ dos.writeUTF(str);
+ }
+ player.playerNetServerHandler.sendPacket(new Packet250CustomPayload("EAG|Voice", baos.toByteArray()));
+ sendVoicePlayers(player.username);
+ } catch (IOException ignored) {
+ }
+ }
+ }
+
+ public static void handleDisconnect(EntityPlayerMP player) {
+ removeUser(player.username);
+ }
+
+ private static void removeUser(String name) {
+ voicePlayers.remove(name);
+ for (String username : voicePlayers.keySet()) {
+ if (!name.equals(username))
+ sendVoicePlayers(username);
+ }
+ for (String[] voicePair : voicePairs) {
+ String target = null;
+ if (voicePair[0].equals(name)) {
+ target = voicePair[1];
+ } else if (voicePair[1].equals(name)) {
+ target = voicePair[0];
+ }
+ if (target != null && voicePlayers.containsKey(target)) {
+ try {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ DataOutputStream dos = new DataOutputStream(baos);
+ dos.write(VOICE_SIGNAL_DISCONNECT);
+ dos.writeUTF(name);
+ voicePlayers.get(target).playerNetServerHandler.sendPacket(new Packet250CustomPayload("EAG|Voice", baos.toByteArray()));
+ } catch (IOException ignored) {
+ }
+ }
+ }
+ removeIf(voicePairs, pair -> pair[0].equals(name) || pair[1].equals(name));
+ }
+
+ public static void reset() {
+ voicePlayers.clear();
+ voiceRequests.clear();
+ voicePairs.clear();
+ iceServers.clear();
+ }
+
+ private static void sendVoicePlayers(String name) {
+ if (!voicePlayers.containsKey(name))
+ return;
+ try {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ DataOutputStream dos = new DataOutputStream(baos);
+ dos.write(VOICE_SIGNAL_GLOBAL);
+ Set mostlyGlobalPlayers = new HashSet<>();
+ for (String username : voicePlayers.keySet()) {
+ if (username.equals(name))
+ continue;
+ if (anyMatch(voicePairs, pair -> (pair[0].equals(name) && pair[1].equals(username))
+ || (pair[0].equals(username) && pair[1].equals(name))))
+ continue;
+ mostlyGlobalPlayers.add(username);
+ }
+ if (mostlyGlobalPlayers.size() > 0) {
+ dos.writeInt(mostlyGlobalPlayers.size());
+ for (String username : mostlyGlobalPlayers)
+ dos.writeUTF(username);
+ voicePlayers.get(name).playerNetServerHandler.sendPacket(new Packet250CustomPayload("EAG|Voice", baos.toByteArray()));
+ }
+ } catch (IOException ignored) {
+ }
+ }
+
+ private static boolean checkVoicePair(String user1, String user2) {
+ return anyMatch(voicePairs, pair -> (pair[0].equals(user1) && pair[1].equals(user2))
+ || (pair[0].equals(user2) && pair[1].equals(user1)));
+ }
+
+ /**
+ * JDK 8 function not available in TeaVM
+ */
+ private static boolean removeIf(Collection collection, Predicate pre) {
+ boolean ret = false;
+ Iterator itr = collection.iterator();
+ while(itr.hasNext()) {
+ if(pre.test(itr.next())) {
+ itr.remove();
+ ret = true;
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * JDK 8 function not available in TeaVM
+ */
+ private static boolean anyMatch(Collection collection, Predicate pre) {
+ boolean ret = false;
+ Iterator itr = collection.iterator();
+ while(itr.hasNext()) {
+ if(pre.test(itr.next())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/WorkerListenThread.java b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/WorkerListenThread.java
new file mode 100644
index 0000000..ea49888
--- /dev/null
+++ b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/WorkerListenThread.java
@@ -0,0 +1,96 @@
+package net.lax1dude.eaglercraft.sp;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+
+import net.minecraft.server.MinecraftServer;
+import net.minecraft.src.NetHandler;
+
+public class WorkerListenThread {
+ /** Reference to the MinecraftServer object. */
+ private final MinecraftServer mcServer;
+ private final HashSet connections = new HashSet<>();
+ private final HashMap channels = new HashMap<>();
+
+ /** Whether the network listener object is listening. */
+ public volatile boolean isListening = false;
+
+ public WorkerListenThread(MinecraftServer par1MinecraftServer) {
+ this.mcServer = par1MinecraftServer;
+ this.isListening = true;
+ }
+
+ /**
+ * adds this connection to the list of currently connected players
+ */
+ public void addPlayer(NetHandler par1NetServerHandler) {
+ System.out.println("[Server][ADDPLAYER][" + par1NetServerHandler.getClass().getSimpleName() + "]");
+ this.connections.add(par1NetServerHandler);
+ }
+
+ public void stopListening() {
+ this.isListening = false;
+ List names = new ArrayList<>(channels.keySet());
+ for(int i = 0, l = names.size(); i < l; ++i) {
+ closeChannel(names.get(i));
+ }
+ }
+
+ public boolean openChannel(String player) {
+ System.out.println("[Server][OPENCHANNEL][" + player + "]");
+ return channels.put(player, new WorkerNetworkManager(player, mcServer, this)) == null;
+ }
+
+ public void recievePacket(String player, byte[] data) {
+ WorkerNetworkManager channel = channels.get(player);
+ if(channel == null) {
+ return;
+ }
+ channel.addToRecieveQueue(data);
+ }
+
+ public boolean closeChannel(String player) {
+ System.out.println("[Server][CLOSECHANNEL][" + player + "]");
+ WorkerNetworkManager channel = channels.get(player);
+ if(channel == null) {
+ return false;
+ }
+ channels.remove(player);
+ channel.networkShutdown(null, null, null);
+ return true;
+ }
+
+ private void deleteDeadConnections() {
+ Iterator itr = this.connections.iterator();
+ while (itr.hasNext()) {
+ NetHandler handler = itr.next();
+ if (handler.shouldBeRemoved()) {
+ itr.remove();
+ //System.out.println("[Client][REMOVEDEAD]");
+ }
+ }
+ }
+
+ /**
+ * Handles all incoming connections and packets
+ */
+ public void handleNetworkListenThread() {
+
+ deleteDeadConnections();
+
+ List conns = new ArrayList<>(this.connections);
+ for (NetHandler var2 : conns) {
+ var2.handlePackets();
+ }
+
+ deleteDeadConnections();
+
+ }
+
+ public MinecraftServer getServer() {
+ return this.mcServer;
+ }
+}
diff --git a/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/WorkerNetworkManager.java b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/WorkerNetworkManager.java
new file mode 100644
index 0000000..a85f6dd
--- /dev/null
+++ b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/WorkerNetworkManager.java
@@ -0,0 +1,146 @@
+package net.lax1dude.eaglercraft.sp;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.LinkedList;
+import net.lax1dude.eaglercraft.sp.ipc.IPCPacket0CPlayerChannel;
+import net.minecraft.server.MinecraftServer;
+import net.minecraft.src.INetworkManager;
+import net.minecraft.src.NetHandler;
+import net.minecraft.src.NetLoginHandler;
+import net.minecraft.src.NetServerHandler;
+import net.minecraft.src.Packet;
+
+public class WorkerNetworkManager implements INetworkManager {
+
+ private NetHandler theNetHandler;
+ private MinecraftServer minecraftServer;
+ private String ipcChannel;
+ private boolean isAlive;
+ private WorkerListenThread listenThread;
+
+ private LinkedList frags = new LinkedList<>();
+
+ public WorkerNetworkManager(String ipcChannel, MinecraftServer srv, WorkerListenThread th) {
+ this.ipcChannel = ipcChannel;
+ this.theNetHandler = new NetLoginHandler(srv, this);
+ th.addPlayer(theNetHandler);
+ this.minecraftServer = srv;
+ this.isAlive = true;
+ this.listenThread = th;
+ }
+
+ @Override
+ public void setNetHandler(NetHandler var1) {
+ theNetHandler = var1;
+ listenThread.addPlayer(theNetHandler);
+ }
+
+ @Override
+ public void addToSendQueue(Packet var1) {
+ if(!isAlive) {
+ return;
+ }
+ try {
+ ByteArrayOutputStream bao = new ByteArrayOutputStream(var1.getPacketSize() + 1);
+ Packet.writePacket(var1, new DataOutputStream(bao));
+ IntegratedServer.sendPlayerPacket(ipcChannel, bao.toByteArray());
+ }catch(IOException e) {
+ System.err.println("Failed to serialize minecraft packet '" + var1.getPacketId() + "' for IPC channel 'NET|" + ipcChannel + "'");
+ e.printStackTrace();
+ return;
+ }
+ }
+
+ public void addToRecieveQueue(byte[] fragment) {
+ //System.out.println("[Server][READ][QUEUE][" + ipcChannel + "]: " + fragment.length);
+ if(!isAlive) {
+ return;
+ }
+ frags.add(fragment);
+ }
+
+ @Override
+ public void wakeThreads() {
+ // no
+ }
+
+ @Override
+ public void processReadPackets() {
+ while(frags.size() > 0) {
+ byte[] pktBytes = frags.remove(0);
+ try {
+ ByteArrayInputStream bai = new ByteArrayInputStream(pktBytes);
+ int pktId = bai.read();
+
+ if(pktId == -1) {
+ System.err.println("Recieved invalid '-1' packet");
+ continue;
+ }
+
+ Packet pkt = Packet.getNewPacket(minecraftServer.getLogAgent(), pktId);
+
+ if(pkt == null) {
+ System.err.println("Recieved invalid '" + pktId + "' packet");
+ continue;
+ }
+
+ pkt.readPacketData(new DataInputStream(bai));
+
+ //System.out.println("[Server][" + ipcChannel + "]: packet '" + pkt.getClass().getSimpleName() + "' recieved");
+
+ try {
+ pkt.processPacket(theNetHandler);
+ }catch(Throwable t) {
+ System.err.println("Could not process minecraft packet 0x" + Integer.toHexString(pkt.getPacketId()) + " class '" + pkt.getClass().getSimpleName() + "' on channel 'NET|" + ipcChannel + "'");
+ t.printStackTrace();
+ }
+
+ }catch(IOException ex) {
+ System.err.println("Could not deserialize a " + pktBytes.length + " byte long minecraft packet of type '" + (pktBytes.length <= 0 ? -1 : (int)(pktBytes[0] & 0xFF)) + "' on channel 'NET|" + ipcChannel + "'");
+ }
+ }
+
+ }
+
+ @Override
+ public void serverShutdown() {
+ if(isAlive) {
+ listenThread.closeChannel(ipcChannel);
+ IntegratedServer.sendIPCPacket(new IPCPacket0CPlayerChannel(ipcChannel, false));
+ }
+ if(theNetHandler != null && (theNetHandler instanceof NetServerHandler)) {
+ ((NetServerHandler)theNetHandler).kickPlayer(null);
+ }
+ isAlive = false;
+ }
+
+ @Override
+ public int getNumChunkDataPackets() { // why is this a thing
+ return 0;
+ }
+
+ @Override
+ public void networkShutdown(String var1, Object... var2) {
+ if(isAlive) {
+ listenThread.closeChannel(ipcChannel);
+ IntegratedServer.sendIPCPacket(new IPCPacket0CPlayerChannel(ipcChannel, false));
+ }
+ if(theNetHandler != null && (theNetHandler instanceof NetServerHandler)) {
+ ((NetServerHandler)theNetHandler).kickPlayer(null);
+ }
+ isAlive = false;
+ }
+
+ public boolean equals(Object o) {
+ return (o instanceof WorkerNetworkManager) && ((WorkerNetworkManager)o).ipcChannel.equals(ipcChannel);
+ }
+
+ public int hashCode() {
+ return ipcChannel.hashCode();
+ }
+
+}
diff --git a/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/WorldConverterEPK.java b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/WorldConverterEPK.java
new file mode 100644
index 0000000..3164e2d
--- /dev/null
+++ b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/WorldConverterEPK.java
@@ -0,0 +1,80 @@
+package net.lax1dude.eaglercraft.sp;
+
+import java.io.IOException;
+
+import net.minecraft.src.CompressedStreamTools;
+import net.minecraft.src.NBTTagCompound;
+
+public class WorldConverterEPK {
+
+ public static void importWorld(byte[] archiveContents, String newName) throws IOException {
+ String folder = VFSSaveHandler.worldNameToFolderName(newName);
+ VFile dir = new VFile("worlds", folder);
+ EPKDecompiler dc = new EPKDecompiler(archiveContents);
+ EPKDecompiler.FileEntry f = null;
+ int lastProgUpdate = 0;
+ int prog = 0;
+ boolean hasReadType = dc.isOld();
+ while((f = dc.readFile()) != null) {
+ byte[] b = f.data;
+ if(!hasReadType) {
+ if(f.type.equals("HEAD") && f.name.equals("file-type") && EPKDecompiler.readASCII(f.data).equals("epk/world152")) {
+ hasReadType = true;
+ continue;
+ }else {
+ throw new IOException("file does not contain a singleplayer 1.5.2 world!");
+ }
+ }
+ if(f.type.equals("FILE")) {
+ if(f.name.equals("level.dat")) {
+ NBTTagCompound worldDatNBT = CompressedStreamTools.decompress(b);
+ worldDatNBT.getCompoundTag("Data").setString("LevelName", newName);
+ worldDatNBT.getCompoundTag("Data").setLong("LastPlayed", System.currentTimeMillis());
+ b = CompressedStreamTools.compress(worldDatNBT);
+ }
+ VFile ff = new VFile(dir, f.name);
+ ff.setAllBytes(b);
+ prog += b.length;
+ if(prog - lastProgUpdate > 10000) {
+ lastProgUpdate = prog;
+ IntegratedServer.updateStatusString("selectWorld.progress.importing.0", prog);
+ }
+ }
+ }
+ String[] worldsTxt = SYS.VFS.getFile("worlds.txt").getAllLines();
+ if(worldsTxt == null || worldsTxt.length <= 0) {
+ worldsTxt = new String[] { folder };
+ }else {
+ String[] tmp = worldsTxt;
+ worldsTxt = new String[worldsTxt.length + 1];
+ System.arraycopy(tmp, 0, worldsTxt, 0, tmp.length);
+ worldsTxt[worldsTxt.length - 1] = folder;
+ }
+ SYS.VFS.getFile("worlds.txt").setAllChars(String.join("\n", worldsTxt));
+ }
+
+ public static byte[] exportWorld(String worldName) {
+ String realWorldName = worldName;
+ String worldOwner = "UNKNOWN";
+ int j = realWorldName.lastIndexOf(new String(new char[] { (char)253, (char)233, (char)233 }));
+ if(j != -1) {
+ worldOwner = realWorldName.substring(j + 3);
+ realWorldName = realWorldName.substring(0, j);
+ }
+ final int[] bytesWritten = new int[1];
+ final int[] lastUpdate = new int[1];
+ String pfx = "worlds/" + realWorldName + "/";
+ EPK2Compiler c = new EPK2Compiler(realWorldName, worldOwner, "epk/world152");
+ SYS.VFS.iterateFiles(pfx, false, (i) -> {
+ byte[] b = i.getAllBytes();
+ c.append(i.path.substring(pfx.length()), b);
+ bytesWritten[0] += b.length;
+ if (bytesWritten[0] - lastUpdate[0] > 10000) {
+ lastUpdate[0] = bytesWritten[0];
+ IntegratedServer.updateStatusString("selectWorld.progress.exporting.1", bytesWritten[0]);
+ }
+ });
+ return c.complete();
+ }
+
+}
diff --git a/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/WorldConverterMCA.java b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/WorldConverterMCA.java
new file mode 100644
index 0000000..efea349
--- /dev/null
+++ b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/WorldConverterMCA.java
@@ -0,0 +1,255 @@
+package net.lax1dude.eaglercraft.sp;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+import java.util.zip.ZipOutputStream;
+
+import net.minecraft.src.CompressedStreamTools;
+import net.minecraft.src.NBTTagCompound;
+import net.minecraft.src.RegionFile;
+
+public class WorldConverterMCA {
+
+ public static void importWorld(byte[] archiveContents, String newName) throws IOException {
+ String folderName = newName.replaceAll("[\\./\"]", "_");
+ VFile worldDir = new VFile("worlds", folderName);
+ while((new VFile(worldDir, "level.dat")).exists() || (new VFile(worldDir, "level.dat_old")).exists()) {
+ folderName += "_";
+ worldDir = new VFile("worlds", folderName);
+ }
+ List fileNames = new ArrayList<>();
+ try(ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(archiveContents))) {
+ ZipEntry folderNameFile = null;
+ while((folderNameFile = zis.getNextEntry()) != null) {
+ if (folderNameFile.getName().contains("__MACOSX/")) continue;
+ if (folderNameFile.isDirectory()) continue;
+ String lowerName = folderNameFile.getName().toLowerCase();
+ if (!(lowerName.endsWith(".dat") || lowerName.endsWith(".dat_old") || lowerName.endsWith(".mca") || lowerName.endsWith(".mcr"))) continue;
+ fileNames.add(folderNameFile.getName().toCharArray());
+ }
+ }
+ final int[] i = new int[] { 0 };
+ while(fileNames.get(0).length > i[0] && fileNames.stream().allMatch(w -> w[i[0]] == fileNames.get(0)[i[0]])) i[0]++;
+ int folderPrefixOffset = i[0];
+ try(ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(archiveContents))) {
+ ZipEntry f = null;
+ int lastProgUpdate = 0;
+ int prog = 0;
+ while ((f = zis.getNextEntry()) != null) {
+ if (f.getName().contains("__MACOSX/")) continue;
+ if (f.isDirectory()) continue;
+ String lowerName = f.getName().toLowerCase();
+ if (!(lowerName.endsWith(".dat") || lowerName.endsWith(".dat_old") || lowerName.endsWith(".mca") || lowerName.endsWith(".mcr") || lowerName.endsWith(".bmp"))) continue;
+ byte[] b;
+ int sz = (int)f.getSize();
+ if(sz >= 0) {
+ b = new byte[sz];
+ int j = 0, k;
+ while(j < b.length && (k = zis.read(b, j, b.length - j)) != -1) {
+ j += k;
+ }
+ }else {
+ b = inputStreamToBytesNoClose(zis);
+ }
+ String fileName = f.getName().substring(folderPrefixOffset);
+ if (fileName.equals("level.dat") || fileName.equals("level.dat_old")) {
+ NBTTagCompound worldDatNBT = CompressedStreamTools.readCompressed(new ByteArrayInputStream(b));
+ worldDatNBT.getCompoundTag("Data").setString("LevelName", newName);
+ worldDatNBT.getCompoundTag("Data").setLong("LastPlayed", System.currentTimeMillis());
+ ByteArrayOutputStream bo = new ByteArrayOutputStream();
+ CompressedStreamTools.writeCompressed(worldDatNBT, bo);
+ b = bo.toByteArray();
+ VFile ff = new VFile(worldDir, fileName);
+ ff.setAllBytes(b);
+ prog += b.length;
+ } else if ((fileName.endsWith(".mcr") || fileName.endsWith(".mca")) && (fileName.startsWith("region/") || fileName.startsWith("DIM1/region/") || fileName.startsWith("DIM-1/region/"))) {
+ VFile chunkFolder = new VFile(worldDir, fileName.startsWith("DIM1") ? "level1" : (fileName.startsWith("DIM-1") ? "level-1" : "level0"));
+ RegionFile mca = new RegionFile(new RandomAccessMemoryFile(b, b.length));
+ for(int j = 0; j < 32; ++j) {
+ for(int k = 0; k < 32; ++k) {
+ if(mca.isChunkSaved(j, k)) {
+ NBTTagCompound chunkNBT;
+ NBTTagCompound chunkLevel;
+ try {
+ chunkNBT = CompressedStreamTools.read(mca.getChunkDataInputStream(j, k));
+ if(!chunkNBT.hasKey("Level")) {
+ throw new IOException("Chunk is missing level data!");
+ }
+ chunkLevel = chunkNBT.getCompoundTag("Level");
+ }catch(Throwable t) {
+ System.err.println("Could not read chunk: " + j + ", " + k);
+ t.printStackTrace();
+ continue;
+ }
+ int chunkX = chunkLevel.getInteger("xPos");
+ int chunkZ = chunkLevel.getInteger("zPos");
+ VFile chunkOut = new VFile(chunkFolder, VFSChunkLoader.getChunkPath(chunkX, chunkZ) + ".dat");
+ if(chunkOut.exists()) {
+ System.err.println("Chunk already exists: " + chunkOut.getPath());
+ continue;
+ }
+ ByteArrayOutputStream bao = new ByteArrayOutputStream();
+ CompressedStreamTools.writeCompressed(chunkNBT, bao);
+ b = bao.toByteArray();
+ chunkOut.setAllBytes(b);
+ prog += b.length;
+ if (prog - lastProgUpdate > 25000) {
+ lastProgUpdate = prog;
+ IntegratedServer.updateStatusString("selectWorld.progress.importing.1", prog);
+ }
+ }
+ }
+ }
+ } else if (fileName.startsWith("data/") || fileName.startsWith("players/")) {
+ VFile ff = new VFile(worldDir, fileName);
+ ff.setAllBytes(b);
+ prog += b.length;
+ }
+ }
+ }
+ String[] worldsTxt = SYS.VFS.getFile("worlds.txt").getAllLines();
+ if(worldsTxt == null || worldsTxt.length <= 0 || (worldsTxt.length == 1 && worldsTxt[0].trim().length() <= 0)) {
+ worldsTxt = new String[] { folderName };
+ }else {
+ String[] tmp = worldsTxt;
+ worldsTxt = new String[worldsTxt.length + 1];
+ System.arraycopy(tmp, 0, worldsTxt, 0, tmp.length);
+ worldsTxt[worldsTxt.length - 1] = folderName;
+ }
+ SYS.VFS.getFile("worlds.txt").setAllChars(String.join("\n", worldsTxt));
+ }
+
+ public static byte[] exportWorld(String folderName) throws IOException {
+ ByteArrayOutputStream bao = new ByteArrayOutputStream();
+ VFile worldFolder;
+ try(ZipOutputStream zos = new ZipOutputStream(bao)) {
+ zos.setComment("contains backup of world '" + folderName + "'");
+ worldFolder = new VFile("worlds", folderName);
+ VFile vf = new VFile(worldFolder, "level.dat");
+ byte[] b;
+ int lastProgUpdate = 0;
+ int prog = 0;
+ boolean safe = false;
+ if(vf.exists()) {
+ zos.putNextEntry(new ZipEntry(folderName + "/level.dat"));
+ b = vf.getAllBytes();
+ zos.write(b);
+ prog += b.length;
+ safe = true;
+ }
+ vf = new VFile(worldFolder, "level.dat_old");
+ if(vf.exists()) {
+ zos.putNextEntry(new ZipEntry(folderName + "/level.dat_old"));
+ b = vf.getAllBytes();
+ zos.write(b);
+ prog += b.length;
+ safe = true;
+ }
+ if (prog - lastProgUpdate > 25000) {
+ lastProgUpdate = prog;
+ IntegratedServer.updateStatusString("selectWorld.progress.exporting.2", prog);
+ }
+ String[] srcFolderNames = new String[] { "level0", "level-1", "level1" };
+ String[] dstFolderNames = new String[] { "/region/", "/DIM-1/region/", "/DIM1/region/" };
+ List fileList;
+ for(int i = 0; i < 3; ++i) {
+ vf = new VFile(worldFolder, srcFolderNames[i]);
+ fileList = SYS.VFS.listVFiles(vf.getPath());
+ String regionFolder = folderName + dstFolderNames[i];
+ Map regionFiles = new HashMap<>();
+ for(int k = 0, l = fileList.size(); k < l; ++k) {
+ VFile chunkFile = fileList.get(k);
+ NBTTagCompound chunkNBT;
+ NBTTagCompound chunkLevel;
+ try {
+ b = chunkFile.getAllBytes();
+ chunkNBT = CompressedStreamTools.readCompressed(new ByteArrayInputStream(b));
+ if(!chunkNBT.hasKey("Level")) {
+ throw new IOException("Chunk is missing level data!");
+ }
+ chunkLevel = chunkNBT.getCompoundTag("Level");
+ }catch(IOException t) {
+ System.err.println("Could not read chunk: " + chunkFile.getPath());
+ t.printStackTrace();
+ continue;
+ }
+ int chunkX = chunkLevel.getInteger("xPos");
+ int chunkZ = chunkLevel.getInteger("zPos");
+ String regionFileName = "r." + (chunkX >> 5) + "." + (chunkZ >> 5) + ".mca";
+ RegionFile rf = regionFiles.get(regionFileName);
+ if(rf == null) {
+ rf = new RegionFile(new RandomAccessMemoryFile(new byte[65536], 0));
+ regionFiles.put(regionFileName, rf);
+ }
+ try(DataOutputStream dos = rf.getChunkDataOutputStream(chunkX & 31, chunkZ & 31)) {
+ CompressedStreamTools.write(chunkNBT, dos);
+ }catch(IOException t) {
+ System.err.println("Could not write chunk to " + regionFileName + ": " + chunkFile.getPath());
+ t.printStackTrace();
+ continue;
+ }
+ prog += b.length;
+ if (prog - lastProgUpdate > 25000) {
+ lastProgUpdate = prog;
+ IntegratedServer.updateStatusString("selectWorld.progress.exporting.2", prog);
+ }
+ }
+ if(regionFiles.isEmpty()) {
+ System.err.println("No region files were generated");
+ continue;
+ }
+ for(Entry etr : regionFiles.entrySet()) {
+ String regionPath = regionFolder + etr.getKey();
+ zos.putNextEntry(new ZipEntry(regionPath));
+ zos.write(etr.getValue().getFile().getByteArray());
+ }
+ }
+ fileList = SYS.VFS.listVFiles((new VFile(worldFolder, "data")).getPath());
+ for(int k = 0, l = fileList.size(); k < l; ++k) {
+ VFile dataFile = fileList.get(k);
+ zos.putNextEntry(new ZipEntry(folderName + "/data/" + dataFile.getName()));
+ b = dataFile.getAllBytes();
+ zos.write(b);
+ prog += b.length;
+ if (prog - lastProgUpdate > 25000) {
+ lastProgUpdate = prog;
+ IntegratedServer.updateStatusString("selectWorld.progress.exporting.2", prog);
+ }
+ }
+ fileList = SYS.VFS.listVFiles((new VFile(worldFolder, "players")).getPath());
+ for(int k = 0, l = fileList.size(); k < l; ++k) {
+ VFile dataFile = fileList.get(k);
+ zos.putNextEntry(new ZipEntry(folderName + "/players/" + dataFile.getName()));
+ b = dataFile.getAllBytes();
+ zos.write(b);
+ prog += b.length;
+ if (prog - lastProgUpdate > 25000) {
+ lastProgUpdate = prog;
+ IntegratedServer.updateStatusString("selectWorld.progress.exporting.2", prog);
+ }
+ }
+ }
+ return bao.toByteArray();
+ }
+
+ private static byte[] inputStreamToBytesNoClose(InputStream is) throws IOException {
+ ByteArrayOutputStream os = new ByteArrayOutputStream(1024);
+ byte[] buf = new byte[1024];
+ int i;
+ while ((i = is.read(buf)) != -1) {
+ os.write(buf, 0, i);
+ }
+ return os.toByteArray();
+ }
+
+}
diff --git a/sp-server/src/main/java/net/minecraft/server/MinecraftServer.java b/sp-server/src/main/java/net/minecraft/server/MinecraftServer.java
new file mode 100644
index 0000000..626baa8
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -0,0 +1,979 @@
+package net.minecraft.server;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.IntegratedServer;
+import net.lax1dude.eaglercraft.sp.SYS;
+import net.lax1dude.eaglercraft.sp.SysUtil;
+import net.lax1dude.eaglercraft.sp.VFSSaveHandler;
+import net.lax1dude.eaglercraft.sp.VFile;
+import net.lax1dude.eaglercraft.sp.WorkerListenThread;
+import net.lax1dude.eaglercraft.sp.ipc.IPCPacket0DProgressUpdate;
+import net.lax1dude.eaglercraft.sp.ipc.IPCPacket14StringList;
+import net.minecraft.src.AxisAlignedBB;
+import net.minecraft.src.ChunkCoordinates;
+import net.minecraft.src.CommandBase;
+import net.minecraft.src.DispenserBehaviors;
+import net.minecraft.src.EntityPlayer;
+import net.minecraft.src.EntityPlayerMP;
+import net.minecraft.src.EnumGameType;
+import net.minecraft.src.ICommandManager;
+import net.minecraft.src.ICommandSender;
+import net.minecraft.src.ILogAgent;
+import net.minecraft.src.IProgressUpdate;
+import net.minecraft.src.ISaveHandler;
+import net.minecraft.src.IUpdatePlayerListBox;
+import net.minecraft.src.MinecraftException;
+import net.minecraft.src.Packet;
+import net.minecraft.src.Packet4UpdateTime;
+import net.minecraft.src.ServerCommandManager;
+import net.minecraft.src.ServerConfigurationManager;
+import net.minecraft.src.StringTranslate;
+import net.minecraft.src.StringUtils;
+import net.minecraft.src.World;
+import net.minecraft.src.WorldInfo;
+import net.minecraft.src.WorldManager;
+import net.minecraft.src.WorldServer;
+import net.minecraft.src.WorldServerMulti;
+import net.minecraft.src.WorldSettings;
+
+public abstract class MinecraftServer implements ICommandSender, Runnable {
+ /** Instance of Minecraft Server. */
+ protected static MinecraftServer mcServer = null;
+
+ /** List of names of players who are online. */
+ protected final List playersOnline = new ArrayList();
+ protected final ICommandManager commandManager;
+
+ /** The server world instances. */
+ public WorldServer[] worldServers;
+
+ /** The ServerConfigurationManager instance. */
+ protected ServerConfigurationManager serverConfigManager;
+
+ /**
+ * Indicates whether the server is running or not. Set to false to initiate a
+ * shutdown.
+ */
+ protected boolean serverRunning = true;
+
+ /** Indicates to other classes that the server is safely stopped. */
+ protected boolean serverStopped = false;
+
+ /** Incremented every tick. */
+ protected int tickCounter = 0;
+
+ /**
+ * The task the server is currently working on(and will output on
+ * outputPercentRemaining).
+ */
+ protected String currentTask;
+
+ /** The percentage of the current task finished so far. */
+ protected int percentDone;
+
+ /** True if the server has animals turned on. */
+ protected boolean canSpawnAnimals;
+ protected boolean canSpawnNPCs;
+
+ /** Indicates whether PvP is active on the server or not. */
+ protected boolean pvpEnabled;
+
+ /** Determines if flight is allowed or not. */
+ protected boolean allowFlight;
+
+ /** The server MOTD string. */
+ protected String motd;
+
+ /** Maximum build height. */
+ protected int buildLimit;
+ protected long lastSentPacketID;
+ protected long lastSentPacketSize;
+ protected long lastReceivedID;
+ protected long lastReceivedSize;
+ public final long[] sentPacketCountArray = new long[100];
+ public final long[] sentPacketSizeArray = new long[100];
+ public final long[] receivedPacketCountArray = new long[100];
+ public final long[] receivedPacketSizeArray = new long[100];
+ public final long[] tickTimeArray = new long[100];
+
+ /** Stats are [dimension][tick%100] system.nanoTime is stored. */
+ public long[][] timeOfLastDimensionTick;
+
+ /** Username of the server owner (for integrated servers) */
+ protected String serverOwner;
+ protected String folderName;
+
+ /**
+ * If true, there is no need to save chunks or stop the server, because that is
+ * already being done.
+ */
+ protected boolean worldIsBeingDeleted;
+ protected String texturePack = "";
+ protected boolean serverIsRunning = false;
+
+ /**
+ * Set when warned for "Can't keep up", which triggers again after 15 seconds.
+ */
+ protected long timeOfLastWarning;
+ protected String userMessage;
+ protected boolean field_104057_T = false;
+
+ public MinecraftServer(String folder) {
+ mcServer = this;
+ this.folderName = folder;
+ this.commandManager = new ServerCommandManager();
+ this.registerDispenseBehaviors();
+ }
+
+ /**
+ * Register all dispense behaviors.
+ */
+ private void registerDispenseBehaviors() {
+ DispenserBehaviors.func_96467_a();
+ }
+
+ /**
+ * Initialises the server and starts it.
+ */
+ protected abstract boolean startServer() throws IOException;
+
+ protected void convertMapIfNeeded(String par1Str) {
+ // no
+ }
+
+ /**
+ * Typically "menu.convertingLevel", "menu.loadingLevel" or others.
+ */
+ protected void setUserMessage(String par1Str) {
+ IntegratedServer.sendIPCPacket(new IPCPacket0DProgressUpdate(par1Str, 0.0f));
+ this.logInfo(par1Str);
+ this.userMessage = par1Str;
+ }
+
+ protected void setUserMessage(String par1Str, float prog) {
+ IntegratedServer.sendIPCPacket(new IPCPacket0DProgressUpdate(par1Str, prog));
+ this.logInfo(par1Str + ": " + (prog > 1.0f ? "" + (int)prog : "" + (int)(prog * 100.0f) + "%"));
+ this.userMessage = par1Str;
+ }
+
+ protected void loadAllWorlds(String par1Str, long par3, WorldSettings par5WorldType) {
+ this.setUserMessage("menu.loadingLevel");
+ this.worldServers = new WorldServer[3];
+ this.timeOfLastDimensionTick = new long[this.worldServers.length][100];
+ ISaveHandler var7 = new VFSSaveHandler(new VFile("worlds", par1Str));
+ WorldInfo var9 = var7.loadWorldInfo();
+ WorldSettings var8;
+
+ if (var9 == null) {
+ if(par5WorldType == null) {
+ throw new IllegalArgumentException("World '" + par1Str + "' does not exist and WorldSettings is null");
+ }
+ var8 = par5WorldType;
+ } else {
+ var8 = new WorldSettings(var9);
+ }
+
+ for (int var10 = 0; var10 < this.worldServers.length; ++var10) {
+ byte var11 = 0;
+
+ if (var10 == 1) {
+ var11 = -1;
+ }
+
+ if (var10 == 2) {
+ var11 = 1;
+ }
+
+ if (var10 == 0) {
+ this.worldServers[var10] = new WorldServer(this, var7, par1Str, var11, var8, this.getLogAgent());
+ } else {
+ this.worldServers[var10] = new WorldServerMulti(this, var7, par1Str, var11, var8, this.worldServers[0], this.getLogAgent());
+ }
+
+ this.worldServers[var10].addWorldAccess(new WorldManager(this, this.worldServers[var10]));
+ this.worldServers[var10].getWorldInfo().setGameType(this.getGameType());
+
+ this.serverConfigManager.setPlayerManager(this.worldServers);
+ }
+
+ this.setDifficultyForAllWorlds(this.getDifficulty());
+ this.setGameType(var8.getGameType());
+ this.initialWorldChunkLoad();
+ }
+
+ protected void initialWorldChunkLoad() {
+ int var5 = 0;
+ //this.setUserMessage("menu.generatingTerrain");
+ byte var6 = 0;
+ this.setUserMessage("Preparing start region for level " + var6);
+
+ // Removed 'spawn chunks' for performance, they are unnecessary
+
+ /*
+ WorldServer var7 = this.worldServers[var6];
+ ChunkCoordinates var8 = var7.getSpawnPoint();
+ long var9 = System.currentTimeMillis();
+
+ int prepareRadius = 64;
+
+ for (int var11 = -prepareRadius; var11 <= prepareRadius && this.isServerRunning(); var11 += 16) {
+ for (int var12 = -prepareRadius; var12 <= prepareRadius && this.isServerRunning(); var12 += 16) {
+ long var13 = System.currentTimeMillis();
+
+ if (var13 - var9 > 1000L) {
+ setUserMessage("Preparing spawn area", Math.min(var5 / 64.0f, 0.99f));
+ var9 = var13;
+ }
+
+ ++var5;
+ var7.theChunkProviderServer.loadChunk(var8.posX + var11 >> 4, var8.posZ + var12 >> 4);
+ }
+ }
+ */
+
+ this.clearCurrentTask();
+ }
+
+ public abstract boolean canStructuresSpawn();
+
+ public abstract EnumGameType getGameType();
+
+ /**
+ * Defaults to "1" (Easy) for the dedicated server, defaults to "2" (Normal) on
+ * the client.
+ */
+ public abstract int getDifficulty();
+
+ /**
+ * Defaults to false.
+ */
+ public abstract boolean isHardcore();
+
+ /**
+ * Used to display a percent remaining given text and the percentage.
+ */
+ protected void outputPercentRemaining(String par1Str, int par2) {
+ this.currentTask = par1Str;
+ this.percentDone = par2;
+ setUserMessage(par1Str, (par2 / 100.0f));
+ }
+
+ /**
+ * Set current task to null and set its percentage to 0.
+ */
+ protected void clearCurrentTask() {
+ this.currentTask = null;
+ this.percentDone = 0;
+ }
+
+ /**
+ * par1 indicates if a log message should be output.
+ */
+ public void saveAllWorlds(boolean par1) {
+ if (!this.worldIsBeingDeleted) {
+ WorldServer[] var2 = this.worldServers;
+ int var3 = var2.length;
+
+ for (int var4 = 0; var4 < var3; ++var4) {
+ WorldServer var5 = var2[var4];
+
+ if (var5 != null) {
+ setUserMessage("Saving chunks for level \'" + var5.getWorldInfo().getWorldName() + "\'/" + var5.provider.getDimensionName());
+
+ try {
+ var5.saveAllChunks(true, (IProgressUpdate) null);
+ } catch (MinecraftException var7) {
+ this.getLogAgent().func_98236_b(var7.getMessage());
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Saves all necessary data as preparation for stopping the server.
+ */
+ public void stopServer() {
+ if (!this.worldIsBeingDeleted) {
+ setUserMessage("Stopping server");
+
+ if (this.getNetworkThread() != null) {
+ this.getNetworkThread().stopListening();
+ }
+
+ if (this.serverConfigManager != null) {
+ this.getLogAgent().func_98233_a("Saving players");
+ this.serverConfigManager.saveAllPlayerData();
+ this.serverConfigManager.removeAllPlayers();
+ }
+
+ setUserMessage("Saving worlds");
+ this.saveAllWorlds(false);
+
+ for (int var1 = 0; var1 < this.worldServers.length; ++var1) {
+ WorldServer var2 = this.worldServers[var1];
+ var2.flush();
+ }
+ }
+ }
+
+ /**
+ * "getHostname" is already taken, but both return the hostname.
+ */
+ public String getServerHostname() {
+ return "127.1.1.1";
+ }
+
+ public void setHostname(String par1Str) {
+ throw new IllegalArgumentException("variable removed");
+ }
+
+ public boolean isServerRunning() {
+ return this.serverRunning;
+ }
+
+ /**
+ * Sets the serverRunning variable to false, in order to get the server to shut
+ * down.
+ */
+ public void initiateShutdown() {
+ this.serverRunning = false;
+ }
+
+ public void run() {
+ try {
+ if (this.startServer()) {
+ long var1 = SysUtil.steadyTimeMillis();
+
+ for (long var50 = 0L; this.serverRunning; this.serverIsRunning = true) {
+ long var5 = SysUtil.steadyTimeMillis();
+ long var7 = var5 - var1;
+
+ if (var7 > 2000L && var1 - this.timeOfLastWarning >= 15000L) {
+ this.getLogAgent().func_98236_b(
+ "Can\'t keep up! Did the system time change, or is the server overloaded?");
+ var7 = 2000L;
+ this.timeOfLastWarning = var1;
+ }
+
+ if (var7 < 0L) {
+ this.getLogAgent().func_98236_b("Time ran backwards! Did the system time change?");
+ var7 = 0L;
+ }
+
+ var50 += var7;
+ var1 = var5;
+
+ if (this.worldServers[0].areAllPlayersAsleep()) {
+ this.tick();
+ var50 = 0L;
+ } else {
+ while (var50 > 50L) {
+ var50 -= 50L;
+ this.tick();
+ }
+ }
+
+ SysUtil.sleep(1);
+ }
+ } else {
+ throw new RuntimeException("Server did not init correctly");
+ }
+ } catch (Throwable var48) {
+ this.getLogAgent().logSevereException(
+ "Encountered an unexpected exception " + var48.getClass().getSimpleName(), var48);
+ var48.printStackTrace();
+ IntegratedServer.throwExceptionToClient("Encountered an unexpected exception", var48);
+ } finally {
+ try {
+ this.stopServer();
+ this.serverStopped = true;
+ } catch (Throwable var46) {
+ var46.printStackTrace();
+ } finally {
+ this.systemExitNow();
+ }
+ }
+ }
+
+ protected VFile getDataDirectory() {
+ return new VFile(".");
+ }
+
+ /**
+ * Directly calls System.exit(0), instantly killing the program.
+ */
+ protected void systemExitNow() {
+ }
+
+ /**
+ * Main function called by run() every loop.
+ */
+ protected void tick() {
+ long var1 = System.nanoTime();
+ AxisAlignedBB.getAABBPool().cleanPool();
+ ++this.tickCounter;
+
+ this.updateTimeLightAndEntities();
+
+ if (this.tickCounter % 900 == 0) {
+ this.serverConfigManager.saveAllPlayerData();
+ this.saveAllWorlds(true);
+ }
+
+ this.tickTimeArray[this.tickCounter % 100] = System.nanoTime() - var1;
+ this.sentPacketCountArray[this.tickCounter % 100] = Packet.sentID - this.lastSentPacketID;
+ this.lastSentPacketID = Packet.sentID;
+ this.sentPacketSizeArray[this.tickCounter % 100] = Packet.sentSize - this.lastSentPacketSize;
+ this.lastSentPacketSize = Packet.sentSize;
+ this.receivedPacketCountArray[this.tickCounter % 100] = Packet.receivedID - this.lastReceivedID;
+ this.lastReceivedID = Packet.receivedID;
+ this.receivedPacketSizeArray[this.tickCounter % 100] = Packet.receivedSize - this.lastReceivedSize;
+ this.lastReceivedSize = Packet.receivedSize;
+ }
+
+ public List getTPSAndChunkBuffer(int tpsCounter) {
+ ArrayList strs = new ArrayList();
+ strs.add("Ticks/Second: " + tpsCounter + "/20");
+
+ int c = 0;
+ int oc = 0;
+ int e = 0;
+ int te = 0;
+ int r = 0;
+ int w = 0;
+ int g = 0;
+ int tu = 0;
+ int lu = 0;
+ for(int i = 0; i < worldServers.length; ++i) {
+ c += worldServers[i].getChunkProvider().getLoadedChunkCount();
+ e += worldServers[i].loadedEntityList.size();
+ te += worldServers[i].loadedTileEntityList.size();
+ r += worldServers[i].getR();
+ w += worldServers[i].getW();
+ g += worldServers[i].getG();
+ lu += worldServers[i].getLU();
+ tu += worldServers[i].getTU();
+ }
+ for(EntityPlayerMP p : (List)this.playersOnline) {
+ oc += p.loadedChunks.size();
+ }
+
+ strs.add("Chunks: " + c + "/" + (c + oc));
+ strs.add("Entities: " + e + "+" + te);
+ strs.add("R: " + r + ", G: " + g + ", W: " + w);
+ strs.add("TU: " + tu + " LU: " + lu);
+ int pp = this.playersOnline.size();
+ if(pp > 1) {
+ strs.add("Players: " + pp);
+ }
+ return strs;
+ }
+
+ public void updateTimeLightAndEntities() {
+ int var1;
+
+ for (var1 = 0; var1 < this.worldServers.length; ++var1) {
+ long var2 = System.nanoTime();
+
+ if (var1 == 0 || this.getAllowNether()) {
+ WorldServer var4 = this.worldServers[var1];
+ var4.getWorldVec3Pool().clear();
+
+ if (this.tickCounter % 20 == 0) {
+ this.serverConfigManager.sendPacketToAllPlayersInDimension(
+ new Packet4UpdateTime(var4.getTotalWorldTime(), var4.getWorldTime()),
+ var4.provider.dimensionId);
+ }
+
+ var4.tick();
+ var4.updateEntities();
+
+ var4.getEntityTracker().updateTrackedEntities();
+ }
+
+ this.timeOfLastDimensionTick[var1][this.tickCounter % 100] = System.nanoTime() - var2;
+ }
+
+ this.getNetworkThread().handleNetworkListenThread();
+ this.serverConfigManager.onTick();
+
+ for (var1 = 0; var1 < this.playersOnline.size(); ++var1) {
+ ((IUpdatePlayerListBox) this.playersOnline.get(var1)).update();
+ }
+ }
+
+ public boolean getAllowNether() {
+ return true;
+ }
+
+ public void func_82010_a(IUpdatePlayerListBox par1IUpdatePlayerListBox) {
+ this.playersOnline.add(par1IUpdatePlayerListBox);
+ }
+
+ /**
+ * Returns a File object from the specified string.
+ */
+ public VFile getFile(String par1Str) {
+ return new VFile(folderName, par1Str);
+ }
+
+ /**
+ * Logs the message with a level of INFO.
+ */
+ public void logInfo(String par1Str) {
+ this.getLogAgent().func_98233_a(par1Str);
+ }
+
+ /**
+ * Logs the message with a level of WARN.
+ */
+ public void logWarning(String par1Str) {
+ this.getLogAgent().func_98236_b(par1Str);
+ }
+
+ /**
+ * Gets the worldServer by the given dimension.
+ */
+ public WorldServer worldServerForDimension(int par1) {
+ return par1 == -1 ? this.worldServers[1] : (par1 == 1 ? this.worldServers[2] : this.worldServers[0]);
+ }
+
+ /**
+ * Returns the server's hostname.
+ */
+ public String getHostname() {
+ return this.getServerHostname();
+ }
+
+ /**
+ * Never used, but "getServerPort" is already taken.
+ */
+ public int getPort() {
+ return this.getServerPort();
+ }
+
+ /**
+ * Returns the server message of the day
+ */
+ public String getMotd() {
+ return this.motd;
+ }
+
+ /**
+ * Returns the server's Minecraft version as string.
+ */
+ public String getMinecraftVersion() {
+ return "1.5.2";
+ }
+
+ /**
+ * Returns the number of players currently on the server.
+ */
+ public int getCurrentPlayerCount() {
+ return this.serverConfigManager.getCurrentPlayerCount();
+ }
+
+ /**
+ * Returns the maximum number of players allowed on the server.
+ */
+ public int getMaxPlayers() {
+ return this.serverConfigManager.getMaxPlayers();
+ }
+
+ /**
+ * Returns an array of the usernames of all the connected players.
+ */
+ public String[] getAllUsernames() {
+ return this.serverConfigManager.getAllUsernames();
+ }
+
+ /**
+ * Used by RCon's Query in the form of "MajorServerMod 1.2.3: MyPlugin 1.3;
+ * AnotherPlugin 2.1; AndSoForth 1.0".
+ */
+ public String getPlugins() {
+ return "";
+ }
+
+ /**
+ * Handle a command received by an RCon instance
+ */
+ public String handleRConCommand(String par1Str) {
+ return "fuck off";
+ }
+
+ /**
+ * Returns true if debugging is enabled, false otherwise.
+ */
+ public boolean isDebuggingEnabled() {
+ return true;
+ }
+
+ /**
+ * Logs the error message with a level of SEVERE.
+ */
+ public void logSevere(String par1Str) {
+ this.getLogAgent().logSevere(par1Str);
+ }
+
+ /**
+ * If isDebuggingEnabled(), logs the message with a level of INFO.
+ */
+ public void logDebug(String par1Str) {
+ if (this.isDebuggingEnabled()) {
+ this.getLogAgent().func_98233_a(par1Str);
+ }
+ }
+
+ public String getServerModName() {
+ return "eaglercraft";
+ }
+
+ /**
+ * If par2Str begins with /, then it searches for commands, otherwise it returns
+ * players.
+ */
+ public List getPossibleCompletions(ICommandSender par1ICommandSender, String par2Str) {
+ ArrayList var3 = new ArrayList();
+
+ if (par2Str.startsWith("/")) {
+ par2Str = par2Str.substring(1);
+ boolean var10 = !par2Str.contains(" ");
+ List var11 = this.commandManager.getPossibleCommands(par1ICommandSender, par2Str);
+
+ if (var11 != null) {
+ Iterator var12 = var11.iterator();
+
+ while (var12.hasNext()) {
+ String var13 = (String) var12.next();
+
+ if (var10) {
+ var3.add("/" + var13);
+ } else {
+ var3.add(var13);
+ }
+ }
+ }
+
+ return var3;
+ } else {
+ String[] var4 = par2Str.split(" ", -1);
+ String var5 = var4[var4.length - 1];
+ String[] var6 = this.serverConfigManager.getAllUsernames();
+ int var7 = var6.length;
+
+ for (int var8 = 0; var8 < var7; ++var8) {
+ String var9 = var6[var8];
+
+ if (CommandBase.doesStringStartWith(var5, var9)) {
+ var3.add(var9);
+ }
+ }
+
+ return var3;
+ }
+ }
+
+ /**
+ * Gets mcServer.
+ */
+ public static MinecraftServer getServer() {
+ return mcServer;
+ }
+
+ /**
+ * Gets the name of this command sender (usually username, but possibly "Rcon")
+ */
+ public String getCommandSenderName() {
+ return "Host";
+ }
+
+ public void sendChatToPlayer(String par1Str) {
+ this.getLogAgent().func_98233_a(StringUtils.stripControlCodes(par1Str));
+ }
+
+ /**
+ * Returns true if the command sender is allowed to use the given command.
+ */
+ public boolean canCommandSenderUseCommand(int par1, String par2Str) {
+ return par2Str.equals(this.getServerOwner());
+ }
+
+ /**
+ * Translates and formats the given string key with the given arguments.
+ */
+ public String translateString(String par1Str, Object... par2ArrayOfObj) {
+ return StringTranslate.getInstance().translateKeyFormat(par1Str, par2ArrayOfObj);
+ }
+
+ public ICommandManager getCommandManager() {
+ return this.commandManager;
+ }
+
+ /**
+ * Gets serverPort.
+ */
+ public int getServerPort() {
+ return 1;
+ }
+
+ public void setServerPort(int par1) {
+ throw new IllegalArgumentException("variable removed");
+ }
+
+ /**
+ * Returns the username of the server owner (for integrated servers)
+ */
+ public String getServerOwner() {
+ return this.serverOwner;
+ }
+
+ /**
+ * Sets the username of the owner of this server (in the case of an integrated
+ * server)
+ */
+ public void setServerOwner(String par1Str) {
+ this.serverOwner = par1Str;
+ }
+
+ public boolean isSinglePlayer() {
+ return this.serverOwner != null;
+ }
+
+ public String getFolderName() {
+ return this.folderName;
+ }
+
+ public void setFolderName(String par1Str) {
+ this.folderName = par1Str;
+ }
+
+ public void setDifficultyForAllWorlds(int par1) {
+ for (int var2 = 0; var2 < this.worldServers.length; ++var2) {
+ WorldServer var3 = this.worldServers[var2];
+
+ if (var3 != null) {
+ if (var3.getWorldInfo().isHardcoreModeEnabled()) {
+ var3.difficultySetting = 3;
+ var3.setAllowedSpawnTypes(true, true);
+ } else if (this.isSinglePlayer()) {
+ var3.difficultySetting = par1;
+ var3.setAllowedSpawnTypes(var3.difficultySetting > 0, true);
+ } else {
+ var3.difficultySetting = par1;
+ var3.setAllowedSpawnTypes(this.allowSpawnMonsters(), this.canSpawnAnimals);
+ }
+ }
+ }
+ }
+
+ protected boolean allowSpawnMonsters() {
+ return true;
+ }
+
+ /**
+ * Gets whether this is a demo or not.
+ */
+ public boolean isDemo() {
+ return false;
+ }
+
+ /**
+ * Sets whether this is a demo or not.
+ */
+ public void setDemo(boolean par1) {
+ throw new IllegalArgumentException("variable removed");
+ }
+
+ public void canCreateBonusChest(boolean par1) {
+ throw new IllegalArgumentException("variable removed");
+ }
+
+ /**
+ * WARNING : directly calls
+ * getActiveAnvilConverter().deleteWorldDirectory(theWorldServer[0].getSaveHandler().getWorldDirectoryName());
+ */
+ public void deleteWorldAndStopServer() {
+ this.worldIsBeingDeleted = true;
+
+ for (int var1 = 0; var1 < this.worldServers.length; ++var1) {
+ WorldServer var2 = this.worldServers[var1];
+
+ if (var2 != null) {
+ var2.flush();
+ }
+ }
+
+ String dir = this.worldServers[0].getSaveHandler().getWorldDirectoryName();
+ SYS.VFS.deleteFiles(dir);
+ String[] worldsTxt = SYS.VFS.getFile("worlds.txt").getAllLines();
+ if(worldsTxt != null) {
+ LinkedList newWorlds = new LinkedList();
+ for(String str : worldsTxt) {
+ if(!str.equalsIgnoreCase(dir)) {
+ newWorlds.add(str);
+ }
+ }
+ SYS.VFS.getFile("worlds.txt").setAllChars(String.join("\n", newWorlds));
+ }
+
+ this.initiateShutdown();
+ }
+
+ public String getTexturePack() {
+ return null;
+ }
+
+ public void setTexturePack(String par1Str) {
+ throw new IllegalArgumentException("variable removed");
+ }
+
+ /**
+ * This is checked to be 16 upon receiving the packet, otherwise the packet is
+ * ignored.
+ */
+ public int textureSize() {
+ return 16;
+ }
+
+ public abstract boolean isDedicatedServer();
+
+ public boolean isServerInOnlineMode() {
+ return false;
+ }
+
+ public void setOnlineMode(boolean par1) {
+ throw new IllegalArgumentException("variable removed");
+ }
+
+ public boolean getCanSpawnAnimals() {
+ return this.canSpawnAnimals;
+ }
+
+ public void setCanSpawnAnimals(boolean par1) {
+ this.canSpawnAnimals = par1;
+ }
+
+ public boolean getCanSpawnNPCs() {
+ return this.canSpawnNPCs;
+ }
+
+ public void setCanSpawnNPCs(boolean par1) {
+ this.canSpawnNPCs = par1;
+ }
+
+ public boolean isPVPEnabled() {
+ return this.pvpEnabled;
+ }
+
+ public void setAllowPvp(boolean par1) {
+ this.pvpEnabled = par1;
+ }
+
+ public boolean isFlightAllowed() {
+ return this.allowFlight;
+ }
+
+ public void setAllowFlight(boolean par1) {
+ this.allowFlight = par1;
+ }
+
+ /**
+ * Return whether command blocks are enabled.
+ */
+ public abstract boolean isCommandBlockEnabled();
+
+ public String getMOTD() {
+ return this.motd;
+ }
+
+ public void setMOTD(String par1Str) {
+ this.motd = par1Str;
+ }
+
+ public int getBuildLimit() {
+ return 256;
+ }
+
+ public void setBuildLimit(int par1) {
+ throw new IllegalArgumentException("variable removed");
+ }
+
+ public boolean isServerStopped() {
+ return this.serverStopped;
+ }
+
+ public ServerConfigurationManager getConfigurationManager() {
+ return this.serverConfigManager;
+ }
+
+ public void setConfigurationManager(ServerConfigurationManager par1ServerConfigurationManager) {
+ this.serverConfigManager = par1ServerConfigurationManager;
+ }
+
+ /**
+ * Sets the game type for all worlds.
+ */
+ public void setGameType(EnumGameType par1EnumGameType) {
+ for (int var2 = 0; var2 < this.worldServers.length; ++var2) {
+ getServer().worldServers[var2].getWorldInfo().setGameType(par1EnumGameType);
+ }
+ }
+
+ public abstract WorkerListenThread getNetworkThread();
+
+ public boolean getGuiEnabled() {
+ return false;
+ }
+
+ /**
+ * On dedicated does nothing. On integrated, sets commandsAllowedForAll,
+ * gameType and allows external connections.
+ */
+ public abstract String shareToLAN(EnumGameType var1, boolean var2);
+
+ public int getTickCounter() {
+ return this.tickCounter;
+ }
+
+ /**
+ * Return the position for this command sender.
+ */
+ public ChunkCoordinates getCommandSenderPosition() {
+ return new ChunkCoordinates(0, 0, 0);
+ }
+
+ /**
+ * Return the spawn protection area's size.
+ */
+ public int getSpawnProtectionSize() {
+ return 0;
+ }
+
+ public boolean func_96290_a(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer) {
+ return false;
+ }
+
+ public abstract ILogAgent getLogAgent();
+
+ public void func_104055_i(boolean par1) {
+ this.field_104057_T = par1;
+ }
+
+ public boolean func_104056_am() {
+ return this.field_104057_T;
+ }
+
+ /**
+ * Gets the current player count, maximum player count, and player entity list.
+ */
+ public static ServerConfigurationManager getServerConfigurationManager(MinecraftServer par0MinecraftServer) {
+ return par0MinecraftServer.serverConfigManager;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/AABBPool.java b/sp-server/src/main/java/net/minecraft/src/AABBPool.java
new file mode 100644
index 0000000..0279dc1
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/AABBPool.java
@@ -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;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Achievement.java b/sp-server/src/main/java/net/minecraft/src/Achievement.java
new file mode 100644
index 0000000..1ac36e0
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Achievement.java
@@ -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();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/AchievementList.java b/sp-server/src/main/java/net/minecraft/src/AchievementList.java
new file mode 100644
index 0000000..9eacd0c
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/AchievementList.java
@@ -0,0 +1,187 @@
+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 = null;
+
+ /** Is the 'getting wood' achievement. */
+ public static Achievement mineWood = null;
+
+ /** Is the 'benchmarking' achievement. */
+ public static Achievement buildWorkBench = null;
+
+ /** Is the 'time to mine' achievement. */
+ public static Achievement buildPickaxe = null;
+
+ /** Is the 'hot topic' achievement. */
+ public static Achievement buildFurnace = null;
+
+ /** Is the 'acquire hardware' achievement. */
+ public static Achievement acquireIron = null;
+
+ /** Is the 'time to farm' achievement. */
+ public static Achievement buildHoe = null;
+
+ /** Is the 'bake bread' achievement. */
+ public static Achievement makeBread = null;
+
+ /** Is the 'the lie' achievement. */
+ public static Achievement bakeCake = null;
+
+ /** Is the 'getting a upgrade' achievement. */
+ public static Achievement buildBetterPickaxe = null;
+
+ /** Is the 'delicious fish' achievement. */
+ public static Achievement cookFish = null;
+
+ /** Is the 'on a rail' achievement */
+ public static Achievement onARail = null;
+
+ /** Is the 'time to strike' achievement. */
+ public static Achievement buildSword = null;
+
+ /** Is the 'monster hunter' achievement. */
+ public static Achievement killEnemy = null;
+
+ /** is the 'cow tipper' achievement. */
+ public static Achievement killCow = null;
+
+ /** Is the 'when pig fly' achievement. */
+ public static Achievement flyPig = null;
+
+ /** The achievement for killing a Skeleton from 50 meters aways. */
+ public static Achievement snipeSkeleton = null;
+
+ /** Is the 'DIAMONDS!' achievement */
+ public static Achievement diamonds = null;
+
+ /** Is the 'We Need to Go Deeper' achievement */
+ public static Achievement portal = null;
+
+ /** Is the 'Return to Sender' achievement */
+ public static Achievement ghast = null;
+
+ /** Is the 'Into Fire' achievement */
+ public static Achievement blazeRod = null;
+
+ /** Is the 'Local Brewery' achievement */
+ public static Achievement potion = null;
+
+ /** Is the 'The End?' achievement */
+ public static Achievement theEnd = null;
+
+ /** Is the 'The End.' achievement */
+ public static Achievement theEnd2 = null;
+
+ /** Is the 'Enchanter' achievement */
+ public static Achievement enchantments = null;
+
+ public static Achievement overkill = null;
+
+ /** Is the 'Librarian' achievement */
+ public static Achievement bookcase = null;
+
+ public static void init() {
+ achievementList = new ArrayList();
+
+ openInventory = (new Achievement(0, "openInventory", 0, 0, Item.book, (Achievement) null))
+ .setIndependent().registerAchievement();
+
+ mineWood = (new Achievement(1, "mineWood", 2, 1, Block.wood, openInventory))
+ .registerAchievement();
+
+ buildWorkBench = (new Achievement(2, "buildWorkBench", 4, -1, Block.workbench, mineWood))
+ .registerAchievement();
+
+ buildPickaxe = (new Achievement(3, "buildPickaxe", 4, 2, Item.pickaxeWood,
+ buildWorkBench)).registerAchievement();
+
+ buildFurnace = (new Achievement(4, "buildFurnace", 3, 4, Block.furnaceIdle, buildPickaxe))
+ .registerAchievement();
+
+ acquireIron = (new Achievement(5, "acquireIron", 1, 4, Item.ingotIron, buildFurnace))
+ .registerAchievement();
+
+ buildHoe = (new Achievement(6, "buildHoe", 2, -3, Item.hoeWood, buildWorkBench))
+ .registerAchievement();
+
+ makeBread = (new Achievement(7, "makeBread", -1, -3, Item.bread, buildHoe))
+ .registerAchievement();
+
+ bakeCake = (new Achievement(8, "bakeCake", 0, -5, Item.cake, buildHoe))
+ .registerAchievement();
+
+ buildBetterPickaxe = (new Achievement(9, "buildBetterPickaxe", 6, 2, Item.pickaxeStone,
+ buildPickaxe)).registerAchievement();
+
+ cookFish = (new Achievement(10, "cookFish", 2, 6, Item.fishCooked, buildFurnace))
+ .registerAchievement();
+
+ onARail = (new Achievement(11, "onARail", 2, 3, Block.rail, acquireIron)).setSpecial()
+ .registerAchievement();
+
+ buildSword = (new Achievement(12, "buildSword", 6, -1, Item.swordWood, buildWorkBench))
+ .registerAchievement();
+
+ killEnemy = (new Achievement(13, "killEnemy", 8, -1, Item.bone, buildSword))
+ .registerAchievement();
+
+ killCow = (new Achievement(14, "killCow", 7, -3, Item.leather, buildSword))
+ .registerAchievement();
+
+ flyPig = (new Achievement(15, "flyPig", 8, -4, Item.saddle, killCow)).setSpecial()
+ .registerAchievement();
+
+ snipeSkeleton = (new Achievement(16, "snipeSkeleton", 7, 0, Item.bow, killEnemy))
+ .setSpecial().registerAchievement();
+
+ diamonds = (new Achievement(17, "diamonds", -1, 5, Item.diamond, acquireIron))
+ .registerAchievement();
+
+ portal = (new Achievement(18, "portal", -1, 7, Block.obsidian, diamonds))
+ .registerAchievement();
+
+ ghast = (new Achievement(19, "ghast", -4, 8, Item.ghastTear, portal)).setSpecial()
+ .registerAchievement();
+
+ blazeRod = (new Achievement(20, "blazeRod", 0, 9, Item.blazeRod, portal))
+ .registerAchievement();
+
+ potion = (new Achievement(21, "potion", 2, 8, Item.potion, blazeRod))
+ .registerAchievement();
+
+ theEnd = (new Achievement(22, "theEnd", 3, 10, Item.eyeOfEnder, blazeRod)).setSpecial()
+ .registerAchievement();
+
+ theEnd2 = (new Achievement(23, "theEnd2", 4, 13, Block.dragonEgg, theEnd)).setSpecial()
+ .registerAchievement();
+
+ enchantments = (new Achievement(24, "enchantments", -4, 4, Block.enchantmentTable,
+ diamonds)).registerAchievement();
+
+ overkill = (new Achievement(25, "overkill", -4, 1, Item.swordDiamond, enchantments))
+ .setSpecial().registerAchievement();
+
+ bookcase = (new Achievement(26, "bookcase", -3, 6, Block.bookShelf, enchantments))
+ .registerAchievement();
+ }
+
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/AchievementMap.java b/sp-server/src/main/java/net/minecraft/src/AchievementMap.java
new file mode 100644
index 0000000..4733bef
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/AchievementMap.java
@@ -0,0 +1,33 @@
+package net.minecraft.src;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class AchievementMap {
+ /** Holds the singleton instance of AchievementMap. */
+ public static AchievementMap instance = null;
+
+ public static void init(List guid) {
+ instance = new AchievementMap(guid);
+ StatList.initAll();
+ }
+
+ /** Maps a achievement id with it's unique GUID. */
+ private Map guidMap = new HashMap();
+
+ private AchievementMap(List guid) {
+ for (String var2 : guid) {
+ String[] var3 = var2.split(",");
+ int var4 = Integer.parseInt(var3[0]);
+ this.guidMap.put(Integer.valueOf(var4), var3[1]);
+ }
+ }
+
+ /**
+ * Returns the unique GUID of a achievement id.
+ */
+ public static String getGuid(int par0) {
+ return (String) instance.guidMap.get(Integer.valueOf(par0));
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/AxisAlignedBB.java b/sp-server/src/main/java/net/minecraft/src/AxisAlignedBB.java
new file mode 100644
index 0000000..4c1f68d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/AxisAlignedBB.java
@@ -0,0 +1,425 @@
+package net.minecraft.src;
+
+public class AxisAlignedBB {
+ /** ThreadLocal AABBPool */
+ private static final AABBPool theAABBLocalPool = new AABBPool(300, 2000);
+ 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 theAABBLocalPool;
+ }
+
+ 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 + "]";
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BehaviorDefaultDispenseItem.java b/sp-server/src/main/java/net/minecraft/src/BehaviorDefaultDispenseItem.java
new file mode 100644
index 0000000..cdbf256
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BehaviorDefaultDispenseItem.java
@@ -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;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BehaviorDispenseArmor.java b/sp-server/src/main/java/net/minecraft/src/BehaviorDispenseArmor.java
new file mode 100644
index 0000000..3ac432c
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BehaviorDispenseArmor.java
@@ -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);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BehaviorDispenseItemProvider.java b/sp-server/src/main/java/net/minecraft/src/BehaviorDispenseItemProvider.java
new file mode 100644
index 0000000..631a62f
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BehaviorDispenseItemProvider.java
@@ -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;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BehaviorDispenseMinecart.java b/sp-server/src/main/java/net/minecraft/src/BehaviorDispenseMinecart.java
new file mode 100644
index 0000000..a307cc1
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BehaviorDispenseMinecart.java
@@ -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);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BehaviorProjectileDispense.java b/sp-server/src/main/java/net/minecraft/src/BehaviorProjectileDispense.java
new file mode 100644
index 0000000..3fbd858
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BehaviorProjectileDispense.java
@@ -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;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BiomeCache.java b/sp-server/src/main/java/net/minecraft/src/BiomeCache.java
new file mode 100644
index 0000000..e2a8060
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BiomeCache.java
@@ -0,0 +1,92 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.SysUtil;
+
+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 = SysUtil.steadyTimeMillis();
+ 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 = SysUtil.steadyTimeMillis();
+ 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;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BiomeCacheBlock.java b/sp-server/src/main/java/net/minecraft/src/BiomeCacheBlock.java
new file mode 100644
index 0000000..7a625d6
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BiomeCacheBlock.java
@@ -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];
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BiomeDecorator.java b/sp-server/src/main/java/net/minecraft/src/BiomeDecorator.java
new file mode 100644
index 0000000..133c03c
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BiomeDecorator.java
@@ -0,0 +1,405 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BiomeDecorator {
+ /** The world the BiomeDecorator is currently decorating */
+ protected World currentWorld;
+
+ /** The Biome Decorator's random number generator. */
+ protected EaglercraftRandom 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, EaglercraftRandom 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);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BiomeEndDecorator.java b/sp-server/src/main/java/net/minecraft/src/BiomeEndDecorator.java
new file mode 100644
index 0000000..ad21990
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BiomeEndDecorator.java
@@ -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);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BiomeGenBase.java b/sp-server/src/main/java/net/minecraft/src/BiomeGenBase.java
new file mode 100644
index 0000000..b882bd6
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BiomeGenBase.java
@@ -0,0 +1,319 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public abstract class BiomeGenBase {
+ /** An array of all the biomes, indexed by biome id. */
+ public static final BiomeGenBase[] biomeList = new BiomeGenBase[256];
+ public static final BiomeGenBase ocean = (new BiomeGenOcean(0)).setColor(112).setBiomeName("Ocean")
+ .setMinMaxHeight(-1.0F, 0.4F);
+ public static final BiomeGenBase plains = (new BiomeGenPlains(1)).setColor(9286496).setBiomeName("Plains")
+ .setTemperatureRainfall(0.8F, 0.4F);
+ public static final BiomeGenBase desert = (new BiomeGenDesert(2)).setColor(16421912).setBiomeName("Desert")
+ .setDisableRain().setTemperatureRainfall(2.0F, 0.0F).setMinMaxHeight(0.1F, 0.2F);
+ public static final BiomeGenBase extremeHills = (new BiomeGenHills(3)).setColor(6316128)
+ .setBiomeName("Extreme Hills").setMinMaxHeight(0.3F, 1.5F).setTemperatureRainfall(0.2F, 0.3F);
+ public static final BiomeGenBase forest = (new BiomeGenForest(4)).setColor(353825).setBiomeName("Forest")
+ .func_76733_a(5159473).setTemperatureRainfall(0.7F, 0.8F);
+ public static final BiomeGenBase taiga = (new BiomeGenTaiga(5)).setColor(747097).setBiomeName("Taiga")
+ .func_76733_a(5159473).setEnableSnow().setTemperatureRainfall(0.05F, 0.8F).setMinMaxHeight(0.1F, 0.4F);
+ public static final BiomeGenBase swampland = (new BiomeGenSwamp(6)).setColor(522674).setBiomeName("Swampland")
+ .func_76733_a(9154376).setMinMaxHeight(-0.2F, 0.1F).setTemperatureRainfall(0.8F, 0.9F);
+ public static final BiomeGenBase river = (new BiomeGenRiver(7)).setColor(255).setBiomeName("River")
+ .setMinMaxHeight(-0.5F, 0.0F);
+ public static final BiomeGenBase hell = (new BiomeGenHell(8)).setColor(16711680).setBiomeName("Hell")
+ .setDisableRain().setTemperatureRainfall(2.0F, 0.0F);
+
+ /** Is the biome used for sky world. */
+ public static final BiomeGenBase sky = (new BiomeGenEnd(9)).setColor(8421631).setBiomeName("Sky").setDisableRain();
+ public static final BiomeGenBase frozenOcean = (new BiomeGenOcean(10)).setColor(9474208).setBiomeName("FrozenOcean")
+ .setEnableSnow().setMinMaxHeight(-1.0F, 0.5F).setTemperatureRainfall(0.0F, 0.5F);
+ public static final BiomeGenBase frozenRiver = (new BiomeGenRiver(11)).setColor(10526975)
+ .setBiomeName("FrozenRiver").setEnableSnow().setMinMaxHeight(-0.5F, 0.0F)
+ .setTemperatureRainfall(0.0F, 0.5F);
+ public static final BiomeGenBase icePlains = (new BiomeGenSnow(12)).setColor(16777215).setBiomeName("Ice Plains")
+ .setEnableSnow().setTemperatureRainfall(0.0F, 0.5F);
+ public static final BiomeGenBase iceMountains = (new BiomeGenSnow(13)).setColor(10526880)
+ .setBiomeName("Ice Mountains").setEnableSnow().setMinMaxHeight(0.3F, 1.3F)
+ .setTemperatureRainfall(0.0F, 0.5F);
+ public static final BiomeGenBase mushroomIsland = (new BiomeGenMushroomIsland(14)).setColor(16711935)
+ .setBiomeName("MushroomIsland").setTemperatureRainfall(0.9F, 1.0F).setMinMaxHeight(0.2F, 1.0F);
+ public static final BiomeGenBase mushroomIslandShore = (new BiomeGenMushroomIsland(15)).setColor(10486015)
+ .setBiomeName("MushroomIslandShore").setTemperatureRainfall(0.9F, 1.0F).setMinMaxHeight(-1.0F, 0.1F);
+
+ /** Beach biome. */
+ public static final BiomeGenBase beach = (new BiomeGenBeach(16)).setColor(16440917).setBiomeName("Beach")
+ .setTemperatureRainfall(0.8F, 0.4F).setMinMaxHeight(0.0F, 0.1F);
+
+ /** Desert Hills biome. */
+ public static final BiomeGenBase desertHills = (new BiomeGenDesert(17)).setColor(13786898)
+ .setBiomeName("DesertHills").setDisableRain().setTemperatureRainfall(2.0F, 0.0F)
+ .setMinMaxHeight(0.3F, 0.8F);
+
+ /** Forest Hills biome. */
+ public static final BiomeGenBase forestHills = (new BiomeGenForest(18)).setColor(2250012)
+ .setBiomeName("ForestHills").func_76733_a(5159473).setTemperatureRainfall(0.7F, 0.8F)
+ .setMinMaxHeight(0.3F, 0.7F);
+
+ /** Taiga Hills biome. */
+ public static final BiomeGenBase taigaHills = (new BiomeGenTaiga(19)).setColor(1456435).setBiomeName("TaigaHills")
+ .setEnableSnow().func_76733_a(5159473).setTemperatureRainfall(0.05F, 0.8F).setMinMaxHeight(0.3F, 0.8F);
+
+ /** Extreme Hills Edge biome. */
+ public static final BiomeGenBase extremeHillsEdge = (new BiomeGenHills(20)).setColor(7501978)
+ .setBiomeName("Extreme Hills Edge").setMinMaxHeight(0.2F, 0.8F).setTemperatureRainfall(0.2F, 0.3F);
+
+ /** Jungle biome identifier */
+ public static final BiomeGenBase jungle = (new BiomeGenJungle(21)).setColor(5470985).setBiomeName("Jungle")
+ .func_76733_a(5470985).setTemperatureRainfall(1.2F, 0.9F).setMinMaxHeight(0.2F, 0.4F);
+ public static final BiomeGenBase jungleHills = (new BiomeGenJungle(22)).setColor(2900485)
+ .setBiomeName("JungleHills").func_76733_a(5470985).setTemperatureRainfall(1.2F, 0.9F)
+ .setMinMaxHeight(1.8F, 0.5F);
+ public String biomeName;
+ public int color;
+
+ /** The block expected to be on the top of this biome */
+ public byte topBlock;
+
+ /** The block to fill spots in when not on the top */
+ public byte fillerBlock;
+ public int field_76754_C;
+
+ /** The minimum height of this biome. Default 0.1. */
+ public float minHeight;
+
+ /** The maximum height of this biome. Default 0.3. */
+ public float maxHeight;
+
+ /** The temperature of this biome. */
+ public float temperature;
+
+ /** The rainfall in this biome. */
+ public float rainfall;
+
+ /** Color tint applied to water depending on biome */
+ public int waterColorMultiplier;
+
+ /** The biome decorator. */
+ public BiomeDecorator theBiomeDecorator;
+
+ /**
+ * Holds the classes of IMobs (hostile mobs) that can be spawned in the biome.
+ */
+ protected List spawnableMonsterList;
+
+ /**
+ * Holds the classes of any creature that can be spawned in the biome as
+ * friendly creature.
+ */
+ protected List spawnableCreatureList;
+
+ /**
+ * Holds the classes of any aquatic creature that can be spawned in the water of
+ * the biome.
+ */
+ protected List spawnableWaterCreatureList;
+ protected List spawnableCaveCreatureList;
+
+ /** Set to true if snow is enabled for this biome. */
+ private boolean enableSnow;
+
+ /**
+ * Is true (default) if the biome support rain (desert and nether can't have
+ * rain)
+ */
+ private boolean enableRain;
+
+ /** The id number to this biome, and its index in the biomeList array. */
+ public final int biomeID;
+
+ /** The tree generator. */
+ protected WorldGenTrees worldGeneratorTrees;
+
+ /** The big tree generator. */
+ protected WorldGenBigTree worldGeneratorBigTree;
+
+ /** The forest generator. */
+ protected WorldGenForest worldGeneratorForest;
+
+ /** The swamp tree generator. */
+ protected WorldGenSwamp worldGeneratorSwamp;
+
+ protected BiomeGenBase(int par1) {
+ this.topBlock = (byte) Block.grass.blockID;
+ this.fillerBlock = (byte) Block.dirt.blockID;
+ this.field_76754_C = 5169201;
+ this.minHeight = 0.1F;
+ this.maxHeight = 0.3F;
+ this.temperature = 0.5F;
+ this.rainfall = 0.5F;
+ this.waterColorMultiplier = 16777215;
+ this.spawnableMonsterList = new ArrayList();
+ this.spawnableCreatureList = new ArrayList();
+ this.spawnableWaterCreatureList = new ArrayList();
+ this.spawnableCaveCreatureList = new ArrayList();
+ this.enableRain = true;
+ this.worldGeneratorTrees = new WorldGenTrees(false);
+ this.worldGeneratorBigTree = new WorldGenBigTree(false);
+ this.worldGeneratorForest = new WorldGenForest(false);
+ this.worldGeneratorSwamp = new WorldGenSwamp();
+ this.biomeID = par1;
+ biomeList[par1] = this;
+ this.theBiomeDecorator = this.createBiomeDecorator();
+ this.spawnableCreatureList.add(new SpawnListEntry((w) -> new EntitySheep(w), 12, 4, 4));
+ this.spawnableCreatureList.add(new SpawnListEntry((w) -> new EntityPig(w), 10, 4, 4));
+ this.spawnableCreatureList.add(new SpawnListEntry((w) -> new EntityChicken(w), 10, 4, 4));
+ this.spawnableCreatureList.add(new SpawnListEntry((w) -> new EntityCow(w), 8, 4, 4));
+ this.spawnableMonsterList.add(new SpawnListEntry((w) -> new EntitySpider(w), 10, 4, 4));
+ this.spawnableMonsterList.add(new SpawnListEntry((w) -> new EntityZombie(w), 10, 4, 4));
+ this.spawnableMonsterList.add(new SpawnListEntry((w) -> new EntitySkeleton(w), 10, 4, 4));
+ this.spawnableMonsterList.add(new SpawnListEntry((w) -> new EntityCreeper(w), 10, 4, 4));
+ this.spawnableMonsterList.add(new SpawnListEntry((w) -> new EntitySlime(w), 10, 4, 4));
+ this.spawnableMonsterList.add(new SpawnListEntry((w) -> new EntityEnderman(w), 1, 1, 4));
+ this.spawnableWaterCreatureList.add(new SpawnListEntry((w) -> new EntitySquid(w), 10, 4, 4));
+ this.spawnableCaveCreatureList.add(new SpawnListEntry((w) -> new EntityBat(w), 10, 8, 8));
+ }
+
+ /**
+ * Allocate a new BiomeDecorator for this BiomeGenBase
+ */
+ protected BiomeDecorator createBiomeDecorator() {
+ return new BiomeDecorator(this);
+ }
+
+ /**
+ * Sets the temperature and rainfall of this biome.
+ */
+ private BiomeGenBase setTemperatureRainfall(float par1, float par2) {
+ if (par1 > 0.1F && par1 < 0.2F) {
+ throw new IllegalArgumentException("Please avoid temperatures in the range 0.1 - 0.2 because of snow");
+ } else {
+ this.temperature = par1;
+ this.rainfall = par2;
+ return this;
+ }
+ }
+
+ /**
+ * Sets the minimum and maximum height of this biome. Seems to go from -2.0 to
+ * 2.0.
+ */
+ private BiomeGenBase setMinMaxHeight(float par1, float par2) {
+ this.minHeight = par1;
+ this.maxHeight = par2;
+ return this;
+ }
+
+ /**
+ * Disable the rain for the biome.
+ */
+ private BiomeGenBase setDisableRain() {
+ this.enableRain = false;
+ return this;
+ }
+
+ /**
+ * Gets a WorldGen appropriate for this biome.
+ */
+ public WorldGenerator getRandomWorldGenForTrees(EaglercraftRandom par1Random) {
+ return (WorldGenerator) (par1Random.nextInt(10) == 0 ? this.worldGeneratorBigTree : this.worldGeneratorTrees);
+ }
+
+ /**
+ * Gets a WorldGen appropriate for this biome.
+ */
+ public WorldGenerator getRandomWorldGenForGrass(EaglercraftRandom par1Random) {
+ return new WorldGenTallGrass(Block.tallGrass.blockID, 1);
+ }
+
+ /**
+ * sets enableSnow to true during biome initialization. returns BiomeGenBase.
+ */
+ protected BiomeGenBase setEnableSnow() {
+ this.enableSnow = true;
+ return this;
+ }
+
+ protected BiomeGenBase setBiomeName(String par1Str) {
+ this.biomeName = par1Str;
+ return this;
+ }
+
+ protected BiomeGenBase func_76733_a(int par1) {
+ this.field_76754_C = par1;
+ return this;
+ }
+
+ protected BiomeGenBase setColor(int par1) {
+ this.color = par1;
+ return this;
+ }
+
+ /**
+ * Returns the correspondent list of the EnumCreatureType informed.
+ */
+ public List getSpawnableList(EnumCreatureType par1EnumCreatureType) {
+ return par1EnumCreatureType == EnumCreatureType.monster ? this.spawnableMonsterList
+ : (par1EnumCreatureType == EnumCreatureType.creature ? this.spawnableCreatureList
+ : (par1EnumCreatureType == EnumCreatureType.waterCreature ? this.spawnableWaterCreatureList
+ : (par1EnumCreatureType == EnumCreatureType.ambient ? this.spawnableCaveCreatureList
+ : null)));
+ }
+
+ /**
+ * Returns true if the biome have snowfall instead a normal rain.
+ */
+ public boolean getEnableSnow() {
+ return this.enableSnow;
+ }
+
+ /**
+ * Return true if the biome supports lightning bolt spawn, either by have the
+ * bolts enabled and have rain enabled.
+ */
+ public boolean canSpawnLightningBolt() {
+ return this.enableSnow ? false : this.enableRain;
+ }
+
+ /**
+ * Checks to see if the rainfall level of the biome is extremely high
+ */
+ public boolean isHighHumidity() {
+ return this.rainfall > 0.85F;
+ }
+
+ /**
+ * returns the chance a creature has to spawn.
+ */
+ public float getSpawningChance() {
+ return 0.1F;
+ }
+
+ /**
+ * Gets an integer representation of this biome's rainfall
+ */
+ public final int getIntRainfall() {
+ return (int) (this.rainfall * 65536.0F);
+ }
+
+ /**
+ * Gets an integer representation of this biome's temperature
+ */
+ public final int getIntTemperature() {
+ return (int) (this.temperature * 65536.0F);
+ }
+
+ /**
+ * Gets a floating point representation of this biome's temperature
+ */
+ public final float getFloatTemperature() {
+ return this.temperature;
+ }
+
+ public void decorate(World par1World, EaglercraftRandom par2Random, int par3, int par4) {
+ this.theBiomeDecorator.decorate(par1World, par2Random, par3, par4);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BiomeGenBeach.java b/sp-server/src/main/java/net/minecraft/src/BiomeGenBeach.java
new file mode 100644
index 0000000..7a53cfb
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BiomeGenBeach.java
@@ -0,0 +1,14 @@
+package net.minecraft.src;
+
+public class BiomeGenBeach extends BiomeGenBase {
+ public BiomeGenBeach(int par1) {
+ super(par1);
+ this.spawnableCreatureList.clear();
+ this.topBlock = (byte) Block.sand.blockID;
+ this.fillerBlock = (byte) Block.sand.blockID;
+ this.theBiomeDecorator.treesPerChunk = -999;
+ this.theBiomeDecorator.deadBushPerChunk = 0;
+ this.theBiomeDecorator.reedsPerChunk = 0;
+ this.theBiomeDecorator.cactiPerChunk = 0;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BiomeGenDesert.java b/sp-server/src/main/java/net/minecraft/src/BiomeGenDesert.java
new file mode 100644
index 0000000..441fa19
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BiomeGenDesert.java
@@ -0,0 +1,27 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BiomeGenDesert extends BiomeGenBase {
+ public BiomeGenDesert(int par1) {
+ super(par1);
+ this.spawnableCreatureList.clear();
+ this.topBlock = (byte) Block.sand.blockID;
+ this.fillerBlock = (byte) Block.sand.blockID;
+ this.theBiomeDecorator.treesPerChunk = -999;
+ this.theBiomeDecorator.deadBushPerChunk = 2;
+ this.theBiomeDecorator.reedsPerChunk = 50;
+ this.theBiomeDecorator.cactiPerChunk = 10;
+ }
+
+ public void decorate(World par1World, EaglercraftRandom par2Random, int par3, int par4) {
+ super.decorate(par1World, par2Random, par3, par4);
+
+ if (par2Random.nextInt(1000) == 0) {
+ int var5 = par3 + par2Random.nextInt(16) + 8;
+ int var6 = par4 + par2Random.nextInt(16) + 8;
+ WorldGenDesertWells var7 = new WorldGenDesertWells();
+ var7.generate(par1World, par2Random, var5, par1World.getHeightValue(var5, var6) + 1, var6);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BiomeGenEnd.java b/sp-server/src/main/java/net/minecraft/src/BiomeGenEnd.java
new file mode 100644
index 0000000..3317877
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BiomeGenEnd.java
@@ -0,0 +1,15 @@
+package net.minecraft.src;
+
+public class BiomeGenEnd extends BiomeGenBase {
+ public BiomeGenEnd(int par1) {
+ super(par1);
+ this.spawnableMonsterList.clear();
+ this.spawnableCreatureList.clear();
+ this.spawnableWaterCreatureList.clear();
+ this.spawnableCaveCreatureList.clear();
+ this.spawnableMonsterList.add(new SpawnListEntry((w) -> new EntityEnderman(w), 10, 4, 4));
+ this.topBlock = (byte) Block.dirt.blockID;
+ this.fillerBlock = (byte) Block.dirt.blockID;
+ this.theBiomeDecorator = new BiomeEndDecorator(this);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BiomeGenForest.java b/sp-server/src/main/java/net/minecraft/src/BiomeGenForest.java
new file mode 100644
index 0000000..fa931da
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BiomeGenForest.java
@@ -0,0 +1,20 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BiomeGenForest extends BiomeGenBase {
+ public BiomeGenForest(int par1) {
+ super(par1);
+ this.spawnableCreatureList.add(new SpawnListEntry((w) -> new EntityWolf(w), 5, 4, 4));
+ this.theBiomeDecorator.treesPerChunk = 10;
+ this.theBiomeDecorator.grassPerChunk = 2;
+ }
+
+ /**
+ * Gets a WorldGen appropriate for this biome.
+ */
+ public WorldGenerator getRandomWorldGenForTrees(EaglercraftRandom par1Random) {
+ return (WorldGenerator) (par1Random.nextInt(5) == 0 ? this.worldGeneratorForest
+ : (par1Random.nextInt(10) == 0 ? this.worldGeneratorBigTree : this.worldGeneratorTrees));
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BiomeGenHell.java b/sp-server/src/main/java/net/minecraft/src/BiomeGenHell.java
new file mode 100644
index 0000000..6829814
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BiomeGenHell.java
@@ -0,0 +1,14 @@
+package net.minecraft.src;
+
+public class BiomeGenHell extends BiomeGenBase {
+ public BiomeGenHell(int par1) {
+ super(par1);
+ this.spawnableMonsterList.clear();
+ this.spawnableCreatureList.clear();
+ this.spawnableWaterCreatureList.clear();
+ this.spawnableCaveCreatureList.clear();
+ this.spawnableMonsterList.add(new SpawnListEntry((w) -> new EntityGhast(w), 50, 4, 4));
+ this.spawnableMonsterList.add(new SpawnListEntry((w) -> new EntityPigZombie(w), 100, 4, 4));
+ this.spawnableMonsterList.add(new SpawnListEntry((w) -> new EntityMagmaCube(w), 1, 4, 4));
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BiomeGenHills.java b/sp-server/src/main/java/net/minecraft/src/BiomeGenHills.java
new file mode 100644
index 0000000..30a9f72
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BiomeGenHills.java
@@ -0,0 +1,38 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BiomeGenHills extends BiomeGenBase {
+ private WorldGenerator theWorldGenerator;
+
+ protected BiomeGenHills(int par1) {
+ super(par1);
+ this.theWorldGenerator = new WorldGenMinable(Block.silverfish.blockID, 8);
+ }
+
+ public void decorate(World par1World, EaglercraftRandom par2Random, int par3, int par4) {
+ super.decorate(par1World, par2Random, par3, par4);
+ int var5 = 3 + par2Random.nextInt(6);
+ int var6;
+ int var7;
+ int var8;
+
+ for (var6 = 0; var6 < var5; ++var6) {
+ var7 = par3 + par2Random.nextInt(16);
+ var8 = par2Random.nextInt(28) + 4;
+ int var9 = par4 + par2Random.nextInt(16);
+ int var10 = par1World.getBlockId(var7, var8, var9);
+
+ if (var10 == Block.stone.blockID) {
+ par1World.setBlock(var7, var8, var9, Block.oreEmerald.blockID, 0, 2);
+ }
+ }
+
+ for (var5 = 0; var5 < 7; ++var5) {
+ var6 = par3 + par2Random.nextInt(16);
+ var7 = par2Random.nextInt(64);
+ var8 = par4 + par2Random.nextInt(16);
+ this.theWorldGenerator.generate(par1World, par2Random, var6, var7, var8);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BiomeGenJungle.java b/sp-server/src/main/java/net/minecraft/src/BiomeGenJungle.java
new file mode 100644
index 0000000..045f1a8
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BiomeGenJungle.java
@@ -0,0 +1,44 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BiomeGenJungle extends BiomeGenBase {
+ public BiomeGenJungle(int par1) {
+ super(par1);
+ this.theBiomeDecorator.treesPerChunk = 50;
+ this.theBiomeDecorator.grassPerChunk = 25;
+ this.theBiomeDecorator.flowersPerChunk = 4;
+ this.spawnableMonsterList.add(new SpawnListEntry((w) -> new EntityOcelot(w), 2, 1, 1));
+ this.spawnableCreatureList.add(new SpawnListEntry((w) -> new EntityChicken(w), 10, 4, 4));
+ }
+
+ /**
+ * Gets a WorldGen appropriate for this biome.
+ */
+ public WorldGenerator getRandomWorldGenForTrees(EaglercraftRandom par1Random) {
+ return (WorldGenerator) (par1Random.nextInt(10) == 0 ? this.worldGeneratorBigTree
+ : (par1Random.nextInt(2) == 0 ? new WorldGenShrub(3, 0)
+ : (par1Random.nextInt(3) == 0 ? new WorldGenHugeTrees(false, 10 + par1Random.nextInt(20), 3, 3)
+ : new WorldGenTrees(false, 4 + par1Random.nextInt(7), 3, 3, true))));
+ }
+
+ /**
+ * Gets a WorldGen appropriate for this biome.
+ */
+ public WorldGenerator getRandomWorldGenForGrass(EaglercraftRandom par1Random) {
+ return par1Random.nextInt(4) == 0 ? new WorldGenTallGrass(Block.tallGrass.blockID, 2)
+ : new WorldGenTallGrass(Block.tallGrass.blockID, 1);
+ }
+
+ public void decorate(World par1World, EaglercraftRandom par2Random, int par3, int par4) {
+ super.decorate(par1World, par2Random, par3, par4);
+ WorldGenVines var5 = new WorldGenVines();
+
+ for (int var6 = 0; var6 < 50; ++var6) {
+ int var7 = par3 + par2Random.nextInt(16) + 8;
+ byte var8 = 64;
+ int var9 = par4 + par2Random.nextInt(16) + 8;
+ var5.generate(par1World, par2Random, var7, var8, var9);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BiomeGenMushroomIsland.java b/sp-server/src/main/java/net/minecraft/src/BiomeGenMushroomIsland.java
new file mode 100644
index 0000000..96c896a
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BiomeGenMushroomIsland.java
@@ -0,0 +1,17 @@
+package net.minecraft.src;
+
+public class BiomeGenMushroomIsland extends BiomeGenBase {
+ public BiomeGenMushroomIsland(int par1) {
+ super(par1);
+ this.theBiomeDecorator.treesPerChunk = -100;
+ this.theBiomeDecorator.flowersPerChunk = -100;
+ this.theBiomeDecorator.grassPerChunk = -100;
+ this.theBiomeDecorator.mushroomsPerChunk = 1;
+ this.theBiomeDecorator.bigMushroomsPerChunk = 1;
+ this.topBlock = (byte) Block.mycelium.blockID;
+ this.spawnableMonsterList.clear();
+ this.spawnableCreatureList.clear();
+ this.spawnableWaterCreatureList.clear();
+ this.spawnableCreatureList.add(new SpawnListEntry((w) -> new EntityMooshroom(w), 8, 4, 8));
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BiomeGenOcean.java b/sp-server/src/main/java/net/minecraft/src/BiomeGenOcean.java
new file mode 100644
index 0000000..01ac387
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BiomeGenOcean.java
@@ -0,0 +1,8 @@
+package net.minecraft.src;
+
+public class BiomeGenOcean extends BiomeGenBase {
+ public BiomeGenOcean(int par1) {
+ super(par1);
+ this.spawnableCreatureList.clear();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BiomeGenPlains.java b/sp-server/src/main/java/net/minecraft/src/BiomeGenPlains.java
new file mode 100644
index 0000000..36e649f
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BiomeGenPlains.java
@@ -0,0 +1,10 @@
+package net.minecraft.src;
+
+public class BiomeGenPlains extends BiomeGenBase {
+ protected BiomeGenPlains(int par1) {
+ super(par1);
+ this.theBiomeDecorator.treesPerChunk = -999;
+ this.theBiomeDecorator.flowersPerChunk = 4;
+ this.theBiomeDecorator.grassPerChunk = 10;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BiomeGenRiver.java b/sp-server/src/main/java/net/minecraft/src/BiomeGenRiver.java
new file mode 100644
index 0000000..19f823d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BiomeGenRiver.java
@@ -0,0 +1,8 @@
+package net.minecraft.src;
+
+public class BiomeGenRiver extends BiomeGenBase {
+ public BiomeGenRiver(int par1) {
+ super(par1);
+ this.spawnableCreatureList.clear();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BiomeGenSnow.java b/sp-server/src/main/java/net/minecraft/src/BiomeGenSnow.java
new file mode 100644
index 0000000..1352017
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BiomeGenSnow.java
@@ -0,0 +1,7 @@
+package net.minecraft.src;
+
+public class BiomeGenSnow extends BiomeGenBase {
+ public BiomeGenSnow(int par1) {
+ super(par1);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BiomeGenSwamp.java b/sp-server/src/main/java/net/minecraft/src/BiomeGenSwamp.java
new file mode 100644
index 0000000..2015cf3
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BiomeGenSwamp.java
@@ -0,0 +1,25 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BiomeGenSwamp extends BiomeGenBase {
+ protected BiomeGenSwamp(int par1) {
+ super(par1);
+ this.theBiomeDecorator.treesPerChunk = 2;
+ this.theBiomeDecorator.flowersPerChunk = -999;
+ this.theBiomeDecorator.deadBushPerChunk = 1;
+ this.theBiomeDecorator.mushroomsPerChunk = 8;
+ this.theBiomeDecorator.reedsPerChunk = 10;
+ this.theBiomeDecorator.clayPerChunk = 1;
+ this.theBiomeDecorator.waterlilyPerChunk = 4;
+ this.waterColorMultiplier = 14745518;
+ this.spawnableMonsterList.add(new SpawnListEntry((w) -> new EntitySlime(w), 1, 1, 1));
+ }
+
+ /**
+ * Gets a WorldGen appropriate for this biome.
+ */
+ public WorldGenerator getRandomWorldGenForTrees(EaglercraftRandom par1Random) {
+ return this.worldGeneratorSwamp;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BiomeGenTaiga.java b/sp-server/src/main/java/net/minecraft/src/BiomeGenTaiga.java
new file mode 100644
index 0000000..e2e0623
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BiomeGenTaiga.java
@@ -0,0 +1,19 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BiomeGenTaiga extends BiomeGenBase {
+ public BiomeGenTaiga(int par1) {
+ super(par1);
+ this.spawnableCreatureList.add(new SpawnListEntry((w) -> new EntityWolf(w), 8, 4, 4));
+ this.theBiomeDecorator.treesPerChunk = 10;
+ this.theBiomeDecorator.grassPerChunk = 1;
+ }
+
+ /**
+ * Gets a WorldGen appropriate for this biome.
+ */
+ public WorldGenerator getRandomWorldGenForTrees(EaglercraftRandom par1Random) {
+ return (WorldGenerator) (par1Random.nextInt(3) == 0 ? new WorldGenTaiga1() : new WorldGenTaiga2(false));
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Block.java b/sp-server/src/main/java/net/minecraft/src/Block.java
new file mode 100644
index 0000000..ec898db
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Block.java
@@ -0,0 +1,1345 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class Block {
+ /**
+ * used as foreach item, if item.tab = current tab, display it on the screen
+ */
+ private CreativeTabs displayOnCreativeTab;
+ public static final StepSound soundPowderFootstep = new StepSound("stone", 1.0F, 1.0F);
+ public static final StepSound soundWoodFootstep = new StepSound("wood", 1.0F, 1.0F);
+ public static final StepSound soundGravelFootstep = new StepSound("gravel", 1.0F, 1.0F);
+ public static final StepSound soundGrassFootstep = new StepSound("grass", 1.0F, 1.0F);
+ public static final StepSound soundStoneFootstep = new StepSound("stone", 1.0F, 1.0F);
+ public static final StepSound soundMetalFootstep = new StepSound("stone", 1.0F, 1.5F);
+ public static final StepSound soundGlassFootstep = new StepSoundStone("stone", 1.0F, 1.0F);
+ public static final StepSound soundClothFootstep = new StepSound("cloth", 1.0F, 1.0F);
+ public static final StepSound soundSandFootstep = new StepSound("sand", 1.0F, 1.0F);
+ public static final StepSound soundSnowFootstep = new StepSound("snow", 1.0F, 1.0F);
+ public static final StepSound soundLadderFootstep = new StepSoundSand("ladder", 1.0F, 1.0F);
+ public static final StepSound soundAnvilFootstep = new StepSoundAnvil("anvil", 0.3F, 1.0F);
+
+ /** List of ly/ff (BlockType) containing the already registered blocks. */
+ public static final Block[] blocksList = new Block[4096];
+
+ /**
+ * An array of 4096 booleans corresponding to the result of the isOpaqueCube()
+ * method for each block ID
+ */
+ public static final boolean[] opaqueCubeLookup = new boolean[4096];
+
+ /** How much light is subtracted for going through this block */
+ public static final int[] lightOpacity = new int[4096];
+
+ /** Array of booleans that tells if a block can grass */
+ public static final boolean[] canBlockGrass = new boolean[4096];
+
+ /** Amount of light emitted */
+ public static final int[] lightValue = new int[4096];
+
+ /**
+ * Flag if block ID should use the brightest neighbor light value as its own
+ */
+ public static boolean[] useNeighborBrightness = new boolean[4096];
+ public static final Block stone = (new BlockStone(1)).setHardness(1.5F).setResistance(10.0F)
+ .setStepSound(soundStoneFootstep).setUnlocalizedName("stone");
+ public static final BlockGrass grass = (BlockGrass) (new BlockGrass(2)).setHardness(0.6F)
+ .setStepSound(soundGrassFootstep).setUnlocalizedName("grass");
+ public static final Block dirt = (new BlockDirt(3)).setHardness(0.5F).setStepSound(soundGravelFootstep)
+ .setUnlocalizedName("dirt");
+ public static final Block cobblestone = (new Block(4, Material.rock)).setHardness(2.0F).setResistance(10.0F)
+ .setStepSound(soundStoneFootstep).setUnlocalizedName("stonebrick").setCreativeTab(CreativeTabs.tabBlock);
+ public static final Block planks = (new BlockWood(5)).setHardness(2.0F).setResistance(5.0F)
+ .setStepSound(soundWoodFootstep).setUnlocalizedName("wood");
+ public static final Block sapling = (new BlockSapling(6)).setHardness(0.0F).setStepSound(soundGrassFootstep)
+ .setUnlocalizedName("sapling");
+ public static final Block bedrock = (new Block(7, Material.rock)).setBlockUnbreakable().setResistance(6000000.0F)
+ .setStepSound(soundStoneFootstep).setUnlocalizedName("bedrock").disableStats()
+ .setCreativeTab(CreativeTabs.tabBlock);
+ public static final BlockFluid waterMoving = (BlockFluid) (new BlockFlowing(8, Material.water)).setHardness(100.0F)
+ .setLightOpacity(3).setUnlocalizedName("water").disableStats();
+ public static final Block waterStill = (new BlockStationary(9, Material.water)).setHardness(100.0F)
+ .setLightOpacity(3).setUnlocalizedName("water").disableStats();
+ public static final BlockFluid lavaMoving = (BlockFluid) (new BlockFlowing(10, Material.lava)).setHardness(0.0F)
+ .setLightValue(1.0F).setUnlocalizedName("lava").disableStats();
+
+ /** Stationary lava source block */
+ public static final Block lavaStill = (new BlockStationary(11, Material.lava)).setHardness(100.0F)
+ .setLightValue(1.0F).setUnlocalizedName("lava").disableStats();
+ public static final Block sand = (new BlockSand(12)).setHardness(0.5F).setStepSound(soundSandFootstep)
+ .setUnlocalizedName("sand");
+ public static final Block gravel = (new BlockGravel(13)).setHardness(0.6F).setStepSound(soundGravelFootstep)
+ .setUnlocalizedName("gravel");
+ public static final Block oreGold = (new BlockOre(14)).setHardness(3.0F).setResistance(5.0F)
+ .setStepSound(soundStoneFootstep).setUnlocalizedName("oreGold");
+ public static final Block oreIron = (new BlockOre(15)).setHardness(3.0F).setResistance(5.0F)
+ .setStepSound(soundStoneFootstep).setUnlocalizedName("oreIron");
+ public static final Block oreCoal = (new BlockOre(16)).setHardness(3.0F).setResistance(5.0F)
+ .setStepSound(soundStoneFootstep).setUnlocalizedName("oreCoal");
+ public static final Block wood = (new BlockLog(17)).setHardness(2.0F).setStepSound(soundWoodFootstep)
+ .setUnlocalizedName("log");
+ public static final BlockLeaves leaves = (BlockLeaves) (new BlockLeaves(18)).setHardness(0.2F).setLightOpacity(1)
+ .setStepSound(soundGrassFootstep).setUnlocalizedName("leaves");
+ public static final Block sponge = (new BlockSponge(19)).setHardness(0.6F).setStepSound(soundGrassFootstep)
+ .setUnlocalizedName("sponge");
+ public static final Block glass = (new BlockGlass(20, Material.glass, false)).setHardness(0.3F)
+ .setStepSound(soundGlassFootstep).setUnlocalizedName("glass");
+ public static final Block oreLapis = (new BlockOre(21)).setHardness(3.0F).setResistance(5.0F)
+ .setStepSound(soundStoneFootstep).setUnlocalizedName("oreLapis");
+ public static final Block blockLapis = (new Block(22, Material.rock)).setHardness(3.0F).setResistance(5.0F)
+ .setStepSound(soundStoneFootstep).setUnlocalizedName("blockLapis").setCreativeTab(CreativeTabs.tabBlock);
+ public static final Block dispenser = (new BlockDispenser(23)).setHardness(3.5F).setStepSound(soundStoneFootstep)
+ .setUnlocalizedName("dispenser");
+ public static final Block sandStone = (new BlockSandStone(24)).setStepSound(soundStoneFootstep).setHardness(0.8F)
+ .setUnlocalizedName("sandStone");
+ public static final Block music = (new BlockNote(25)).setHardness(0.8F).setUnlocalizedName("musicBlock");
+ public static final Block bed = (new BlockBed(26)).setHardness(0.2F).setUnlocalizedName("bed").disableStats();
+ public static final Block railPowered = (new BlockRailPowered(27)).setHardness(0.7F)
+ .setStepSound(soundMetalFootstep).setUnlocalizedName("goldenRail");
+ public static final Block railDetector = (new BlockDetectorRail(28)).setHardness(0.7F)
+ .setStepSound(soundMetalFootstep).setUnlocalizedName("detectorRail");
+ public static final BlockPistonBase pistonStickyBase = (BlockPistonBase) (new BlockPistonBase(29, true))
+ .setUnlocalizedName("pistonStickyBase");
+ public static final Block web = (new BlockWeb(30)).setLightOpacity(1).setHardness(4.0F).setUnlocalizedName("web");
+ public static final BlockTallGrass tallGrass = (BlockTallGrass) (new BlockTallGrass(31)).setHardness(0.0F)
+ .setStepSound(soundGrassFootstep).setUnlocalizedName("tallgrass");
+ public static final BlockDeadBush deadBush = (BlockDeadBush) (new BlockDeadBush(32)).setHardness(0.0F)
+ .setStepSound(soundGrassFootstep).setUnlocalizedName("deadbush");
+ public static final BlockPistonBase pistonBase = (BlockPistonBase) (new BlockPistonBase(33, false))
+ .setUnlocalizedName("pistonBase");
+ public static final BlockPistonExtension pistonExtension = new BlockPistonExtension(34);
+ public static final Block cloth = (new BlockCloth()).setHardness(0.8F).setStepSound(soundClothFootstep)
+ .setUnlocalizedName("cloth");
+ public static final BlockPistonMoving pistonMoving = new BlockPistonMoving(36);
+ public static final BlockFlower plantYellow = (BlockFlower) (new BlockFlower(37)).setHardness(0.0F)
+ .setStepSound(soundGrassFootstep).setUnlocalizedName("flower");
+ public static final BlockFlower plantRed = (BlockFlower) (new BlockFlower(38)).setHardness(0.0F)
+ .setStepSound(soundGrassFootstep).setUnlocalizedName("rose");
+ public static final BlockFlower mushroomBrown = (BlockFlower) (new BlockMushroom(39, "mushroom_brown"))
+ .setHardness(0.0F).setStepSound(soundGrassFootstep).setLightValue(0.125F).setUnlocalizedName("mushroom");
+ public static final BlockFlower mushroomRed = (BlockFlower) (new BlockMushroom(40, "mushroom_red"))
+ .setHardness(0.0F).setStepSound(soundGrassFootstep).setUnlocalizedName("mushroom");
+ public static final Block blockGold = (new BlockOreStorage(41)).setHardness(3.0F).setResistance(10.0F)
+ .setStepSound(soundMetalFootstep).setUnlocalizedName("blockGold");
+ public static final Block blockIron = (new BlockOreStorage(42)).setHardness(5.0F).setResistance(10.0F)
+ .setStepSound(soundMetalFootstep).setUnlocalizedName("blockIron");
+
+ /** stoneDoubleSlab */
+ public static final BlockHalfSlab stoneDoubleSlab = (BlockHalfSlab) (new BlockStep(43, true)).setHardness(2.0F)
+ .setResistance(10.0F).setStepSound(soundStoneFootstep).setUnlocalizedName("stoneSlab");
+
+ /** stoneSingleSlab */
+ public static final BlockHalfSlab stoneSingleSlab = (BlockHalfSlab) (new BlockStep(44, false)).setHardness(2.0F)
+ .setResistance(10.0F).setStepSound(soundStoneFootstep).setUnlocalizedName("stoneSlab");
+ public static final Block brick = (new Block(45, Material.rock)).setHardness(2.0F).setResistance(10.0F)
+ .setStepSound(soundStoneFootstep).setUnlocalizedName("brick").setCreativeTab(CreativeTabs.tabBlock);
+ public static final Block tnt = (new BlockTNT(46)).setHardness(0.0F).setStepSound(soundGrassFootstep)
+ .setUnlocalizedName("tnt");
+ public static final Block bookShelf = (new BlockBookshelf(47)).setHardness(1.5F).setStepSound(soundWoodFootstep)
+ .setUnlocalizedName("bookshelf");
+ public static final Block cobblestoneMossy = (new Block(48, Material.rock)).setHardness(2.0F).setResistance(10.0F)
+ .setStepSound(soundStoneFootstep).setUnlocalizedName("stoneMoss").setCreativeTab(CreativeTabs.tabBlock);
+ public static final Block obsidian = (new BlockObsidian(49)).setHardness(50.0F).setResistance(2000.0F)
+ .setStepSound(soundStoneFootstep).setUnlocalizedName("obsidian");
+ public static final Block torchWood = (new BlockTorch(50)).setHardness(0.0F).setLightValue(0.9375F)
+ .setStepSound(soundWoodFootstep).setUnlocalizedName("torch");
+ public static final BlockFire fire = (BlockFire) (new BlockFire(51)).setHardness(0.0F).setLightValue(1.0F)
+ .setStepSound(soundWoodFootstep).setUnlocalizedName("fire").disableStats();
+ public static final Block mobSpawner = (new BlockMobSpawner(52)).setHardness(5.0F).setStepSound(soundMetalFootstep)
+ .setUnlocalizedName("mobSpawner").disableStats();
+ public static final Block stairsWoodOak = (new BlockStairs(53, planks, 0)).setUnlocalizedName("stairsWood");
+ public static final BlockChest chest = (BlockChest) (new BlockChest(54, 0)).setHardness(2.5F)
+ .setStepSound(soundWoodFootstep).setUnlocalizedName("chest");
+ public static final BlockRedstoneWire redstoneWire = (BlockRedstoneWire) (new BlockRedstoneWire(55))
+ .setHardness(0.0F).setStepSound(soundPowderFootstep).setUnlocalizedName("redstoneDust").disableStats();
+ public static final Block oreDiamond = (new BlockOre(56)).setHardness(3.0F).setResistance(5.0F)
+ .setStepSound(soundStoneFootstep).setUnlocalizedName("oreDiamond");
+ public static final Block blockDiamond = (new BlockOreStorage(57)).setHardness(5.0F).setResistance(10.0F)
+ .setStepSound(soundMetalFootstep).setUnlocalizedName("blockDiamond");
+ public static final Block workbench = (new BlockWorkbench(58)).setHardness(2.5F).setStepSound(soundWoodFootstep)
+ .setUnlocalizedName("workbench");
+ public static final Block crops = (new BlockCrops(59)).setUnlocalizedName("crops");
+ public static final Block tilledField = (new BlockFarmland(60)).setHardness(0.6F).setStepSound(soundGravelFootstep)
+ .setUnlocalizedName("farmland");
+ public static final Block furnaceIdle = (new BlockFurnace(61, false)).setHardness(3.5F)
+ .setStepSound(soundStoneFootstep).setUnlocalizedName("furnace").setCreativeTab(CreativeTabs.tabDecorations);
+ public static final Block furnaceBurning = (new BlockFurnace(62, true)).setHardness(3.5F)
+ .setStepSound(soundStoneFootstep).setLightValue(0.875F).setUnlocalizedName("furnace");
+ public static final Block signPost = (new BlockSign(63, TileEntitySign.class, true)).setHardness(1.0F)
+ .setStepSound(soundWoodFootstep).setUnlocalizedName("sign").disableStats();
+ public static final Block doorWood = (new BlockDoor(64, Material.wood)).setHardness(3.0F)
+ .setStepSound(soundWoodFootstep).setUnlocalizedName("doorWood").disableStats();
+ public static final Block ladder = (new BlockLadder(65)).setHardness(0.4F).setStepSound(soundLadderFootstep)
+ .setUnlocalizedName("ladder");
+ public static final Block rail = (new BlockRail(66)).setHardness(0.7F).setStepSound(soundMetalFootstep)
+ .setUnlocalizedName("rail");
+ public static final Block stairsCobblestone = (new BlockStairs(67, cobblestone, 0))
+ .setUnlocalizedName("stairsStone");
+ public static final Block signWall = (new BlockSign(68, TileEntitySign.class, false)).setHardness(1.0F)
+ .setStepSound(soundWoodFootstep).setUnlocalizedName("sign").disableStats();
+ public static final Block lever = (new BlockLever(69)).setHardness(0.5F).setStepSound(soundWoodFootstep)
+ .setUnlocalizedName("lever");
+ public static final Block pressurePlateStone = (new BlockPressurePlate(70, "stone", Material.rock,
+ EnumMobType.mobs)).setHardness(0.5F).setStepSound(soundStoneFootstep).setUnlocalizedName("pressurePlate");
+ public static final Block doorIron = (new BlockDoor(71, Material.iron)).setHardness(5.0F)
+ .setStepSound(soundMetalFootstep).setUnlocalizedName("doorIron").disableStats();
+ public static final Block pressurePlatePlanks = (new BlockPressurePlate(72, "wood", Material.wood,
+ EnumMobType.everything)).setHardness(0.5F).setStepSound(soundWoodFootstep)
+ .setUnlocalizedName("pressurePlate");
+ public static final Block oreRedstone = (new BlockRedstoneOre(73, false)).setHardness(3.0F).setResistance(5.0F)
+ .setStepSound(soundStoneFootstep).setUnlocalizedName("oreRedstone").setCreativeTab(CreativeTabs.tabBlock);
+ public static final Block oreRedstoneGlowing = (new BlockRedstoneOre(74, true)).setLightValue(0.625F)
+ .setHardness(3.0F).setResistance(5.0F).setStepSound(soundStoneFootstep).setUnlocalizedName("oreRedstone");
+ public static final Block torchRedstoneIdle = (new BlockRedstoneTorch(75, false)).setHardness(0.0F)
+ .setStepSound(soundWoodFootstep).setUnlocalizedName("notGate");
+ public static final Block torchRedstoneActive = (new BlockRedstoneTorch(76, true)).setHardness(0.0F)
+ .setLightValue(0.5F).setStepSound(soundWoodFootstep).setUnlocalizedName("notGate")
+ .setCreativeTab(CreativeTabs.tabRedstone);
+ public static final Block stoneButton = (new BlockButtonStone(77)).setHardness(0.5F)
+ .setStepSound(soundStoneFootstep).setUnlocalizedName("button");
+ public static final Block snow = (new BlockSnow(78)).setHardness(0.1F).setStepSound(soundSnowFootstep)
+ .setUnlocalizedName("snow").setLightOpacity(0);
+ public static final Block ice = (new BlockIce(79)).setHardness(0.5F).setLightOpacity(3)
+ .setStepSound(soundGlassFootstep).setUnlocalizedName("ice");
+ public static final Block blockSnow = (new BlockSnowBlock(80)).setHardness(0.2F).setStepSound(soundSnowFootstep)
+ .setUnlocalizedName("snow");
+ public static final Block cactus = (new BlockCactus(81)).setHardness(0.4F).setStepSound(soundClothFootstep)
+ .setUnlocalizedName("cactus");
+ public static final Block blockClay = (new BlockClay(82)).setHardness(0.6F).setStepSound(soundGravelFootstep)
+ .setUnlocalizedName("clay");
+ public static final Block reed = (new BlockReed(83)).setHardness(0.0F).setStepSound(soundGrassFootstep)
+ .setUnlocalizedName("reeds").disableStats();
+ public static final Block jukebox = (new BlockJukeBox(84)).setHardness(2.0F).setResistance(10.0F)
+ .setStepSound(soundStoneFootstep).setUnlocalizedName("jukebox");
+ public static final Block fence = (new BlockFence(85, "wood", Material.wood)).setHardness(2.0F).setResistance(5.0F)
+ .setStepSound(soundWoodFootstep).setUnlocalizedName("fence");
+ public static final Block pumpkin = (new BlockPumpkin(86, false)).setHardness(1.0F).setStepSound(soundWoodFootstep)
+ .setUnlocalizedName("pumpkin");
+ public static final Block netherrack = (new BlockNetherrack(87)).setHardness(0.4F).setStepSound(soundStoneFootstep)
+ .setUnlocalizedName("hellrock");
+ public static final Block slowSand = (new BlockSoulSand(88)).setHardness(0.5F).setStepSound(soundSandFootstep)
+ .setUnlocalizedName("hellsand");
+ public static final Block glowStone = (new BlockGlowStone(89, Material.glass)).setHardness(0.3F)
+ .setStepSound(soundGlassFootstep).setLightValue(1.0F).setUnlocalizedName("lightgem");
+
+ /** The purple teleport blocks inside the obsidian circle */
+ public static final BlockPortal portal = (BlockPortal) (new BlockPortal(90)).setHardness(-1.0F)
+ .setStepSound(soundGlassFootstep).setLightValue(0.75F).setUnlocalizedName("portal");
+ public static final Block pumpkinLantern = (new BlockPumpkin(91, true)).setHardness(1.0F)
+ .setStepSound(soundWoodFootstep).setLightValue(1.0F).setUnlocalizedName("litpumpkin");
+ public static final Block cake = (new BlockCake(92)).setHardness(0.5F).setStepSound(soundClothFootstep)
+ .setUnlocalizedName("cake").disableStats();
+ public static final BlockRedstoneRepeater redstoneRepeaterIdle = (BlockRedstoneRepeater) (new BlockRedstoneRepeater(
+ 93, false)).setHardness(0.0F).setStepSound(soundWoodFootstep).setUnlocalizedName("diode").disableStats();
+ public static final BlockRedstoneRepeater redstoneRepeaterActive = (BlockRedstoneRepeater) (new BlockRedstoneRepeater(
+ 94, true)).setHardness(0.0F).setLightValue(0.625F).setStepSound(soundWoodFootstep)
+ .setUnlocalizedName("diode").disableStats();
+
+ /**
+ * April fools secret locked chest, only spawns on new chunks on 1st April.
+ */
+ public static final Block lockedChest = (new BlockLockedChest(95)).setHardness(0.0F).setLightValue(1.0F)
+ .setStepSound(soundWoodFootstep).setUnlocalizedName("lockedchest").setTickRandomly(true);
+ public static final Block trapdoor = (new BlockTrapDoor(96, Material.wood)).setHardness(3.0F)
+ .setStepSound(soundWoodFootstep).setUnlocalizedName("trapdoor").disableStats();
+ public static final Block silverfish = (new BlockSilverfish(97)).setHardness(0.75F)
+ .setUnlocalizedName("monsterStoneEgg");
+ public static final Block stoneBrick = (new BlockStoneBrick(98)).setHardness(1.5F).setResistance(10.0F)
+ .setStepSound(soundStoneFootstep).setUnlocalizedName("stonebricksmooth");
+ public static final Block mushroomCapBrown = (new BlockMushroomCap(99, Material.wood, 0)).setHardness(0.2F)
+ .setStepSound(soundWoodFootstep).setUnlocalizedName("mushroom");
+ public static final Block mushroomCapRed = (new BlockMushroomCap(100, Material.wood, 1)).setHardness(0.2F)
+ .setStepSound(soundWoodFootstep).setUnlocalizedName("mushroom");
+ public static final Block fenceIron = (new BlockPane(101, "fenceIron", "fenceIron", Material.iron, true))
+ .setHardness(5.0F).setResistance(10.0F).setStepSound(soundMetalFootstep).setUnlocalizedName("fenceIron");
+ public static final Block thinGlass = (new BlockPane(102, "glass", "thinglass_top", Material.glass, false))
+ .setHardness(0.3F).setStepSound(soundGlassFootstep).setUnlocalizedName("thinGlass");
+ public static final Block melon = (new BlockMelon(103)).setHardness(1.0F).setStepSound(soundWoodFootstep)
+ .setUnlocalizedName("melon");
+ public static final Block pumpkinStem = (new BlockStem(104, pumpkin)).setHardness(0.0F)
+ .setStepSound(soundWoodFootstep).setUnlocalizedName("pumpkinStem");
+ public static final Block melonStem = (new BlockStem(105, melon)).setHardness(0.0F).setStepSound(soundWoodFootstep)
+ .setUnlocalizedName("pumpkinStem");
+ public static final Block vine = (new BlockVine(106)).setHardness(0.2F).setStepSound(soundGrassFootstep)
+ .setUnlocalizedName("vine");
+ public static final Block fenceGate = (new BlockFenceGate(107)).setHardness(2.0F).setResistance(5.0F)
+ .setStepSound(soundWoodFootstep).setUnlocalizedName("fenceGate");
+ public static final Block stairsBrick = (new BlockStairs(108, brick, 0)).setUnlocalizedName("stairsBrick");
+ public static final Block stairsStoneBrick = (new BlockStairs(109, stoneBrick, 0))
+ .setUnlocalizedName("stairsStoneBrickSmooth");
+ public static final BlockMycelium mycelium = (BlockMycelium) (new BlockMycelium(110)).setHardness(0.6F)
+ .setStepSound(soundGrassFootstep).setUnlocalizedName("mycel");
+ public static final Block waterlily = (new BlockLilyPad(111)).setHardness(0.0F).setStepSound(soundGrassFootstep)
+ .setUnlocalizedName("waterlily");
+ public static final Block netherBrick = (new Block(112, Material.rock)).setHardness(2.0F).setResistance(10.0F)
+ .setStepSound(soundStoneFootstep).setUnlocalizedName("netherBrick").setCreativeTab(CreativeTabs.tabBlock);
+ public static final Block netherFence = (new BlockFence(113, "netherBrick", Material.rock)).setHardness(2.0F)
+ .setResistance(10.0F).setStepSound(soundStoneFootstep).setUnlocalizedName("netherFence");
+ public static final Block stairsNetherBrick = (new BlockStairs(114, netherBrick, 0))
+ .setUnlocalizedName("stairsNetherBrick");
+ public static final Block netherStalk = (new BlockNetherStalk(115)).setUnlocalizedName("netherStalk");
+ public static final Block enchantmentTable = (new BlockEnchantmentTable(116)).setHardness(5.0F)
+ .setResistance(2000.0F).setUnlocalizedName("enchantmentTable");
+ public static final Block brewingStand = (new BlockBrewingStand(117)).setHardness(0.5F).setLightValue(0.125F)
+ .setUnlocalizedName("brewingStand");
+ public static final BlockCauldron cauldron = (BlockCauldron) (new BlockCauldron(118)).setHardness(2.0F)
+ .setUnlocalizedName("cauldron");
+ public static final Block endPortal = (new BlockEndPortal(119, Material.portal)).setHardness(-1.0F)
+ .setResistance(6000000.0F);
+ public static final Block endPortalFrame = (new BlockEndPortalFrame(120)).setStepSound(soundGlassFootstep)
+ .setLightValue(0.125F).setHardness(-1.0F).setUnlocalizedName("endPortalFrame").setResistance(6000000.0F)
+ .setCreativeTab(CreativeTabs.tabDecorations);
+ public static final Block whiteStone = (new Block(121, Material.rock)).setHardness(3.0F).setResistance(15.0F)
+ .setStepSound(soundStoneFootstep).setUnlocalizedName("whiteStone").setCreativeTab(CreativeTabs.tabBlock);
+ public static final Block dragonEgg = (new BlockDragonEgg(122)).setHardness(3.0F).setResistance(15.0F)
+ .setStepSound(soundStoneFootstep).setLightValue(0.125F).setUnlocalizedName("dragonEgg");
+ public static final Block redstoneLampIdle = (new BlockRedstoneLight(123, false)).setHardness(0.3F)
+ .setStepSound(soundGlassFootstep).setUnlocalizedName("redstoneLight")
+ .setCreativeTab(CreativeTabs.tabRedstone);
+ public static final Block redstoneLampActive = (new BlockRedstoneLight(124, true)).setHardness(0.3F)
+ .setStepSound(soundGlassFootstep).setUnlocalizedName("redstoneLight");
+ public static final BlockHalfSlab woodDoubleSlab = (BlockHalfSlab) (new BlockWoodSlab(125, true)).setHardness(2.0F)
+ .setResistance(5.0F).setStepSound(soundWoodFootstep).setUnlocalizedName("woodSlab");
+ public static final BlockHalfSlab woodSingleSlab = (BlockHalfSlab) (new BlockWoodSlab(126, false)).setHardness(2.0F)
+ .setResistance(5.0F).setStepSound(soundWoodFootstep).setUnlocalizedName("woodSlab");
+ public static final Block cocoaPlant = (new BlockCocoa(127)).setHardness(0.2F).setResistance(5.0F)
+ .setStepSound(soundWoodFootstep).setUnlocalizedName("cocoa");
+ public static final Block stairsSandStone = (new BlockStairs(128, sandStone, 0))
+ .setUnlocalizedName("stairsSandStone");
+ public static final Block oreEmerald = (new BlockOre(129)).setHardness(3.0F).setResistance(5.0F)
+ .setStepSound(soundStoneFootstep).setUnlocalizedName("oreEmerald");
+ public static final Block enderChest = (new BlockEnderChest(130)).setHardness(22.5F).setResistance(1000.0F)
+ .setStepSound(soundStoneFootstep).setUnlocalizedName("enderChest").setLightValue(0.5F);
+ public static final BlockTripWireSource tripWireSource = (BlockTripWireSource) (new BlockTripWireSource(131))
+ .setUnlocalizedName("tripWireSource");
+ public static final Block tripWire = (new BlockTripWire(132)).setUnlocalizedName("tripWire");
+ public static final Block blockEmerald = (new BlockOreStorage(133)).setHardness(5.0F).setResistance(10.0F)
+ .setStepSound(soundMetalFootstep).setUnlocalizedName("blockEmerald");
+ public static final Block stairsWoodSpruce = (new BlockStairs(134, planks, 1))
+ .setUnlocalizedName("stairsWoodSpruce");
+ public static final Block stairsWoodBirch = (new BlockStairs(135, planks, 2)).setUnlocalizedName("stairsWoodBirch");
+ public static final Block stairsWoodJungle = (new BlockStairs(136, planks, 3))
+ .setUnlocalizedName("stairsWoodJungle");
+ public static final Block commandBlock = (new BlockCommandBlock(137)).setUnlocalizedName("commandBlock");
+ public static final BlockBeacon beacon = (BlockBeacon) (new BlockBeacon(138)).setUnlocalizedName("beacon")
+ .setLightValue(1.0F);
+ public static final Block cobblestoneWall = (new BlockWall(139, cobblestone)).setUnlocalizedName("cobbleWall");
+ public static final Block flowerPot = (new BlockFlowerPot(140)).setHardness(0.0F).setStepSound(soundPowderFootstep)
+ .setUnlocalizedName("flowerPot");
+ public static final Block carrot = (new BlockCarrot(141)).setUnlocalizedName("carrots");
+ public static final Block potato = (new BlockPotato(142)).setUnlocalizedName("potatoes");
+ public static final Block woodenButton = (new BlockButtonWood(143)).setHardness(0.5F)
+ .setStepSound(soundWoodFootstep).setUnlocalizedName("button");
+ public static final Block skull = (new BlockSkull(144)).setHardness(1.0F).setStepSound(soundStoneFootstep)
+ .setUnlocalizedName("skull");
+ public static final Block anvil = (new BlockAnvil(145)).setHardness(5.0F).setStepSound(soundAnvilFootstep)
+ .setResistance(2000.0F).setUnlocalizedName("anvil");
+ public static final Block chestTrapped = (new BlockChest(146, 1)).setHardness(2.5F).setStepSound(soundWoodFootstep)
+ .setUnlocalizedName("chestTrap");
+ public static final Block pressurePlateGold = (new BlockPressurePlateWeighted(147, "blockGold", Material.iron, 64))
+ .setHardness(0.5F).setStepSound(soundWoodFootstep).setUnlocalizedName("weightedPlate_light");
+ public static final Block pressurePlateIron = (new BlockPressurePlateWeighted(148, "blockIron", Material.iron, 640))
+ .setHardness(0.5F).setStepSound(soundWoodFootstep).setUnlocalizedName("weightedPlate_heavy");
+ public static final BlockComparator redstoneComparatorIdle = (BlockComparator) (new BlockComparator(149, false))
+ .setHardness(0.0F).setStepSound(soundWoodFootstep).setUnlocalizedName("comparator").disableStats();
+ public static final BlockComparator redstoneComparatorActive = (BlockComparator) (new BlockComparator(150, true))
+ .setHardness(0.0F).setLightValue(0.625F).setStepSound(soundWoodFootstep).setUnlocalizedName("comparator")
+ .disableStats();
+ public static final BlockDaylightDetector daylightSensor = (BlockDaylightDetector) (new BlockDaylightDetector(151))
+ .setHardness(0.2F).setStepSound(soundWoodFootstep).setUnlocalizedName("daylightDetector");
+ public static final Block blockRedstone = (new BlockPoweredOre(152)).setHardness(5.0F).setResistance(10.0F)
+ .setStepSound(soundMetalFootstep).setUnlocalizedName("blockRedstone");
+ public static final Block oreNetherQuartz = (new BlockOre(153)).setHardness(3.0F).setResistance(5.0F)
+ .setStepSound(soundStoneFootstep).setUnlocalizedName("netherquartz");
+ public static final BlockHopper hopperBlock = (BlockHopper) (new BlockHopper(154)).setHardness(3.0F)
+ .setResistance(8.0F).setStepSound(soundWoodFootstep).setUnlocalizedName("hopper");
+ public static final Block blockNetherQuartz = (new BlockQuartz(155)).setStepSound(soundStoneFootstep)
+ .setHardness(0.8F).setUnlocalizedName("quartzBlock");
+ public static final Block stairsNetherQuartz = (new BlockStairs(156, blockNetherQuartz, 0))
+ .setUnlocalizedName("stairsQuartz");
+ public static final Block railActivator = (new BlockRailPowered(157)).setHardness(0.7F)
+ .setStepSound(soundMetalFootstep).setUnlocalizedName("activatorRail");
+ public static final Block dropper = (new BlockDropper(158)).setHardness(3.5F).setStepSound(soundStoneFootstep)
+ .setUnlocalizedName("dropper");
+
+ /** ID of the block. */
+ public final int blockID;
+
+ /** Indicates how many hits it takes to break a block. */
+ protected float blockHardness;
+
+ /** Indicates the blocks resistance to explosions. */
+ protected float blockResistance;
+
+ /**
+ * set to true when Block's constructor is called through the chain of
+ * super()'s. Note: Never used
+ */
+ protected boolean blockConstructorCalled = true;
+
+ /**
+ * If this field is true, the block is counted for statistics (mined or placed)
+ */
+ protected boolean enableStats = true;
+
+ /**
+ * Flags whether or not this block is of a type that needs random ticking.
+ * Ref-counted by ExtendedBlockStorage in order to broadly cull a chunk from the
+ * random chunk update list for efficiency's sake.
+ */
+ protected boolean needsRandomTick;
+
+ /** true if the Block contains a Tile Entity */
+ protected boolean isBlockContainer;
+
+ /** minimum X for the block bounds (local coordinates) */
+ protected double minX;
+
+ /** minimum Y for the block bounds (local coordinates) */
+ protected double minY;
+
+ /** minimum Z for the block bounds (local coordinates) */
+ protected double minZ;
+
+ /** maximum X for the block bounds (local coordinates) */
+ protected double maxX;
+
+ /** maximum Y for the block bounds (local coordinates) */
+ protected double maxY;
+
+ /** maximum Z for the block bounds (local coordinates) */
+ protected double maxZ;
+
+ /** Sound of stepping on the block */
+ public StepSound stepSound;
+ public float blockParticleGravity;
+
+ /** Block material definition. */
+ public final Material blockMaterial;
+
+ /**
+ * Determines how much velocity is maintained while moving on top of this block
+ */
+ public float slipperiness;
+
+ /** The unlocalized name of this block. */
+ private String unlocalizedName;
+
+ protected Block(int par1, Material par2Material) {
+ this.stepSound = soundPowderFootstep;
+ this.blockParticleGravity = 1.0F;
+ this.slipperiness = 0.6F;
+
+ if (blocksList[par1] != null) {
+ throw new IllegalArgumentException(
+ "Slot " + par1 + " is already occupied by " + blocksList[par1] + " when adding " + this);
+ } else {
+ this.blockMaterial = par2Material;
+ blocksList[par1] = this;
+ this.blockID = par1;
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
+ opaqueCubeLookup[par1] = this.isOpaqueCube();
+ lightOpacity[par1] = this.isOpaqueCube() ? 255 : 0;
+ canBlockGrass[par1] = !par2Material.getCanBlockGrass();
+ }
+ }
+
+ /**
+ * This method is called on a block after all other blocks gets already created.
+ * You can use it to reference and configure something on the block that needs
+ * the others ones.
+ */
+ protected void initializeBlock() {
+ }
+
+ /**
+ * Sets the footstep sound for the block. Returns the object for convenience in
+ * constructing.
+ */
+ protected Block setStepSound(StepSound par1StepSound) {
+ this.stepSound = par1StepSound;
+ return this;
+ }
+
+ /**
+ * Sets how much light is blocked going through this block. Returns the object
+ * for convenience in constructing.
+ */
+ protected Block setLightOpacity(int par1) {
+ lightOpacity[this.blockID] = par1;
+ return this;
+ }
+
+ /**
+ * Sets the amount of light emitted by a block from 0.0f to 1.0f (converts
+ * internally to 0-15). Returns the object for convenience in constructing.
+ */
+ protected Block setLightValue(float par1) {
+ lightValue[this.blockID] = (int) (15.0F * par1);
+ return this;
+ }
+
+ /**
+ * Sets the the blocks resistance to explosions. Returns the object for
+ * convenience in constructing.
+ */
+ protected Block setResistance(float par1) {
+ this.blockResistance = par1 * 3.0F;
+ return this;
+ }
+
+ public static boolean isNormalCube(int par0) {
+ Block var1 = blocksList[par0];
+ return var1 == null ? false
+ : var1.blockMaterial.isOpaque() && var1.renderAsNormalBlock() && !var1.canProvidePower();
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return true;
+ }
+
+ public boolean getBlocksMovement(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ return !this.blockMaterial.blocksMovement();
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 0;
+ }
+
+ /**
+ * Sets how many hits it takes to break a block.
+ */
+ protected Block setHardness(float par1) {
+ this.blockHardness = par1;
+
+ if (this.blockResistance < par1 * 5.0F) {
+ this.blockResistance = par1 * 5.0F;
+ }
+
+ return this;
+ }
+
+ /**
+ * This method will make the hardness of the block equals to -1, and the block
+ * is indestructible.
+ */
+ protected Block setBlockUnbreakable() {
+ this.setHardness(-1.0F);
+ return this;
+ }
+
+ /**
+ * Returns the block hardness at a location. Args: world, x, y, z
+ */
+ public float getBlockHardness(World par1World, int par2, int par3, int par4) {
+ return this.blockHardness;
+ }
+
+ /**
+ * Sets whether this block type will receive random update ticks
+ */
+ protected Block setTickRandomly(boolean par1) {
+ this.needsRandomTick = par1;
+ return this;
+ }
+
+ /**
+ * Returns whether or not this block is of a type that needs random ticking.
+ * Called for ref-counting purposes by ExtendedBlockStorage in order to broadly
+ * cull a chunk from the random chunk update list for efficiency's sake.
+ */
+ public boolean getTickRandomly() {
+ return this.needsRandomTick;
+ }
+
+ public boolean hasTileEntity() {
+ return this.isBlockContainer;
+ }
+
+ /**
+ * Sets the bounds of the block. minX, minY, minZ, maxX, maxY, maxZ
+ */
+ protected final void setBlockBounds(float par1, float par2, float par3, float par4, float par5, float par6) {
+ this.minX = (double) par1;
+ this.minY = (double) par2;
+ this.minZ = (double) par3;
+ this.maxX = (double) par4;
+ this.maxY = (double) par5;
+ this.maxZ = (double) par6;
+ }
+
+ /**
+ * Returns Returns true if the given side of this block type should be rendered
+ * (if it's solid or not), if the adjacent block is at the given coordinates.
+ * Args: blockAccess, x, y, z, side
+ */
+ public boolean isBlockSolid(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) {
+ return par1IBlockAccess.getBlockMaterial(par2, par3, par4).isSolid();
+ }
+
+ /**
+ * Adds all intersecting collision boxes to a list. (Be sure to only add boxes
+ * to the list if they intersect the mask.) Parameters: World, X, Y, Z, mask,
+ * list, colliding entity
+ */
+ public void addCollisionBoxesToList(World par1World, int par2, int par3, int par4, AxisAlignedBB par5AxisAlignedBB,
+ List par6List, Entity par7Entity) {
+ AxisAlignedBB var8 = this.getCollisionBoundingBoxFromPool(par1World, par2, par3, par4);
+
+ if (var8 != null && par5AxisAlignedBB.intersectsWith(var8)) {
+ par6List.add(var8);
+ }
+ }
+
+ /**
+ * Returns a bounding box from the pool of bounding boxes (this means this box
+ * can change after the pool has been cleared to be reused)
+ */
+ public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) {
+ return AxisAlignedBB.getAABBPool().getAABB((double) par2 + this.minX, (double) par3 + this.minY,
+ (double) par4 + this.minZ, (double) par2 + this.maxX, (double) par3 + this.maxY,
+ (double) par4 + this.maxZ);
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return true;
+ }
+
+ /**
+ * Returns whether this block is collideable based on the arguments passed in
+ * Args: blockMetaData, unknownFlag
+ */
+ public boolean canCollideCheck(int par1, boolean par2) {
+ return this.isCollidable();
+ }
+
+ /**
+ * Returns if this block is collidable (only used by Fire). Args: x, y, z
+ */
+ public boolean isCollidable() {
+ return true;
+ }
+
+ /**
+ * Ticks the block if it's been scheduled
+ */
+ public void updateTick(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ }
+
+ /**
+ * Called right before the block is destroyed by a player. Args: world, x, y, z,
+ * metaData
+ */
+ public void onBlockDestroyedByPlayer(World par1World, int par2, int par3, int par4, int par5) {
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ }
+
+ /**
+ * How many world ticks before ticking
+ */
+ public int tickRate(World par1World) {
+ return 10;
+ }
+
+ /**
+ * Called whenever the block is added into the world. Args: world, x, y, z
+ */
+ public void onBlockAdded(World par1World, int par2, int par3, int par4) {
+ }
+
+ /**
+ * ejects contained items into the world, and notifies neighbours of an update,
+ * as appropriate
+ */
+ public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) {
+ }
+
+ /**
+ * Returns the quantity of items to drop on block destruction.
+ */
+ public int quantityDropped(EaglercraftRandom par1Random) {
+ return 1;
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return this.blockID;
+ }
+
+ /**
+ * Gets the hardness of block at the given coordinates in the given world,
+ * relative to the ability of the given EntityPlayer.
+ */
+ public float getPlayerRelativeBlockHardness(EntityPlayer par1EntityPlayer, World par2World, int par3, int par4,
+ int par5) {
+ float var6 = this.getBlockHardness(par2World, par3, par4, par5);
+ return var6 < 0.0F ? 0.0F
+ : (!par1EntityPlayer.canHarvestBlock(this)
+ ? par1EntityPlayer.getCurrentPlayerStrVsBlock(this, false) / var6 / 100.0F
+ : par1EntityPlayer.getCurrentPlayerStrVsBlock(this, true) / var6 / 30.0F);
+ }
+
+ /**
+ * Drops the specified block items
+ */
+ public final void dropBlockAsItem(World par1World, int par2, int par3, int par4, int par5, int par6) {
+ this.dropBlockAsItemWithChance(par1World, par2, par3, par4, par5, 1.0F, par6);
+ }
+
+ /**
+ * Drops the block items with a specified chance of dropping the specified items
+ */
+ public void dropBlockAsItemWithChance(World par1World, int par2, int par3, int par4, int par5, float par6,
+ int par7) {
+ if (!par1World.isRemote) {
+ int var8 = this.quantityDroppedWithBonus(par7, par1World.rand);
+
+ for (int var9 = 0; var9 < var8; ++var9) {
+ if (par1World.rand.nextFloat() <= par6) {
+ int var10 = this.idDropped(par5, par1World.rand, par7);
+
+ if (var10 > 0) {
+ this.dropBlockAsItem_do(par1World, par2, par3, par4,
+ new ItemStack(var10, 1, this.damageDropped(par5)));
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Spawns EntityItem in the world for the given ItemStack if the world is not
+ * remote.
+ */
+ protected void dropBlockAsItem_do(World par1World, int par2, int par3, int par4, ItemStack par5ItemStack) {
+ if (!par1World.isRemote && par1World.getGameRules().getGameRuleBooleanValue("doTileDrops")) {
+ float var6 = 0.7F;
+ double var7 = (double) (par1World.rand.nextFloat() * var6) + (double) (1.0F - var6) * 0.5D;
+ double var9 = (double) (par1World.rand.nextFloat() * var6) + (double) (1.0F - var6) * 0.5D;
+ double var11 = (double) (par1World.rand.nextFloat() * var6) + (double) (1.0F - var6) * 0.5D;
+ EntityItem var13 = new EntityItem(par1World, (double) par2 + var7, (double) par3 + var9,
+ (double) par4 + var11, par5ItemStack);
+ var13.delayBeforeCanPickup = 10;
+ par1World.spawnEntityInWorld(var13);
+ }
+ }
+
+ /**
+ * called by spawner, ore, redstoneOre blocks
+ */
+ protected void dropXpOnBlockBreak(World par1World, int par2, int par3, int par4, int par5) {
+ if (!par1World.isRemote) {
+ while (par5 > 0) {
+ int var6 = EntityXPOrb.getXPSplit(par5);
+ par5 -= var6;
+ par1World.spawnEntityInWorld(new EntityXPOrb(par1World, (double) par2 + 0.5D, (double) par3 + 0.5D,
+ (double) par4 + 0.5D, var6));
+ }
+ }
+ }
+
+ /**
+ * Determines the damage on the item the block drops. Used in cloth and wood.
+ */
+ public int damageDropped(int par1) {
+ return 0;
+ }
+
+ /**
+ * Returns how much this block can resist explosions from the passed in entity.
+ */
+ public float getExplosionResistance(Entity par1Entity) {
+ return this.blockResistance / 5.0F;
+ }
+
+ /**
+ * Ray traces through the blocks collision from start vector to end vector
+ * returning a ray trace hit. Args: world, x, y, z, startVec, endVec
+ */
+ public MovingObjectPosition collisionRayTrace(World par1World, int par2, int par3, int par4, Vec3 par5Vec3,
+ Vec3 par6Vec3) {
+ this.setBlockBoundsBasedOnState(par1World, par2, par3, par4);
+ par5Vec3 = par5Vec3.addVector((double) (-par2), (double) (-par3), (double) (-par4));
+ par6Vec3 = par6Vec3.addVector((double) (-par2), (double) (-par3), (double) (-par4));
+ Vec3 var7 = par5Vec3.getIntermediateWithXValue(par6Vec3, this.minX);
+ Vec3 var8 = par5Vec3.getIntermediateWithXValue(par6Vec3, this.maxX);
+ Vec3 var9 = par5Vec3.getIntermediateWithYValue(par6Vec3, this.minY);
+ Vec3 var10 = par5Vec3.getIntermediateWithYValue(par6Vec3, this.maxY);
+ Vec3 var11 = par5Vec3.getIntermediateWithZValue(par6Vec3, this.minZ);
+ Vec3 var12 = par5Vec3.getIntermediateWithZValue(par6Vec3, this.maxZ);
+
+ if (!this.isVecInsideYZBounds(var7)) {
+ var7 = null;
+ }
+
+ if (!this.isVecInsideYZBounds(var8)) {
+ var8 = null;
+ }
+
+ if (!this.isVecInsideXZBounds(var9)) {
+ var9 = null;
+ }
+
+ if (!this.isVecInsideXZBounds(var10)) {
+ var10 = null;
+ }
+
+ if (!this.isVecInsideXYBounds(var11)) {
+ var11 = null;
+ }
+
+ if (!this.isVecInsideXYBounds(var12)) {
+ var12 = null;
+ }
+
+ Vec3 var13 = null;
+
+ if (var7 != null && (var13 == null || par5Vec3.squareDistanceTo(var7) < par5Vec3.squareDistanceTo(var13))) {
+ var13 = var7;
+ }
+
+ if (var8 != null && (var13 == null || par5Vec3.squareDistanceTo(var8) < par5Vec3.squareDistanceTo(var13))) {
+ var13 = var8;
+ }
+
+ if (var9 != null && (var13 == null || par5Vec3.squareDistanceTo(var9) < par5Vec3.squareDistanceTo(var13))) {
+ var13 = var9;
+ }
+
+ if (var10 != null && (var13 == null || par5Vec3.squareDistanceTo(var10) < par5Vec3.squareDistanceTo(var13))) {
+ var13 = var10;
+ }
+
+ if (var11 != null && (var13 == null || par5Vec3.squareDistanceTo(var11) < par5Vec3.squareDistanceTo(var13))) {
+ var13 = var11;
+ }
+
+ if (var12 != null && (var13 == null || par5Vec3.squareDistanceTo(var12) < par5Vec3.squareDistanceTo(var13))) {
+ var13 = var12;
+ }
+
+ if (var13 == null) {
+ return null;
+ } else {
+ byte var14 = -1;
+
+ if (var13 == var7) {
+ var14 = 4;
+ }
+
+ if (var13 == var8) {
+ var14 = 5;
+ }
+
+ if (var13 == var9) {
+ var14 = 0;
+ }
+
+ if (var13 == var10) {
+ var14 = 1;
+ }
+
+ if (var13 == var11) {
+ var14 = 2;
+ }
+
+ if (var13 == var12) {
+ var14 = 3;
+ }
+
+ return new MovingObjectPosition(par2, par3, par4, var14,
+ var13.addVector((double) par2, (double) par3, (double) par4));
+ }
+ }
+
+ /**
+ * Checks if a vector is within the Y and Z bounds of the block.
+ */
+ private boolean isVecInsideYZBounds(Vec3 par1Vec3) {
+ return par1Vec3 == null ? false
+ : par1Vec3.yCoord >= this.minY && par1Vec3.yCoord <= this.maxY && par1Vec3.zCoord >= this.minZ
+ && par1Vec3.zCoord <= this.maxZ;
+ }
+
+ /**
+ * Checks if a vector is within the X and Z bounds of the block.
+ */
+ private boolean isVecInsideXZBounds(Vec3 par1Vec3) {
+ return par1Vec3 == null ? false
+ : par1Vec3.xCoord >= this.minX && par1Vec3.xCoord <= this.maxX && par1Vec3.zCoord >= this.minZ
+ && par1Vec3.zCoord <= this.maxZ;
+ }
+
+ /**
+ * Checks if a vector is within the X and Y bounds of the block.
+ */
+ private boolean isVecInsideXYBounds(Vec3 par1Vec3) {
+ return par1Vec3 == null ? false
+ : par1Vec3.xCoord >= this.minX && par1Vec3.xCoord <= this.maxX && par1Vec3.yCoord >= this.minY
+ && par1Vec3.yCoord <= this.maxY;
+ }
+
+ /**
+ * Called upon the block being destroyed by an explosion
+ */
+ public void onBlockDestroyedByExplosion(World par1World, int par2, int par3, int par4, Explosion par5Explosion) {
+ }
+
+ public boolean canPlaceBlockOnSide(World par1World, int par2, int par3, int par4, int par5,
+ ItemStack par6ItemStack) {
+ return this.canPlaceBlockOnSide(par1World, par2, par3, par4, par5);
+ }
+
+ /**
+ * checks to see if you can place this block can be placed on that side of a
+ * block: BlockLever overrides
+ */
+ public boolean canPlaceBlockOnSide(World par1World, int par2, int par3, int par4, int par5) {
+ return this.canPlaceBlockAt(par1World, par2, par3, par4);
+ }
+
+ /**
+ * Checks to see if its valid to put this block at the specified coordinates.
+ * Args: world, x, y, z
+ */
+ public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4) {
+ int var5 = par1World.getBlockId(par2, par3, par4);
+ return var5 == 0 || blocksList[var5].blockMaterial.isReplaceable();
+ }
+
+ /**
+ * Called upon block activation (right click on the block.)
+ */
+ public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer,
+ int par6, float par7, float par8, float par9) {
+ return false;
+ }
+
+ /**
+ * Called whenever an entity is walking on top of this block. Args: world, x, y,
+ * z, entity
+ */
+ public void onEntityWalking(World par1World, int par2, int par3, int par4, Entity par5Entity) {
+ }
+
+ /**
+ * Called when a block is placed using its ItemBlock. Args: World, X, Y, Z,
+ * side, hitX, hitY, hitZ, block metadata
+ */
+ public int onBlockPlaced(World par1World, int par2, int par3, int par4, int par5, float par6, float par7,
+ float par8, int par9) {
+ return par9;
+ }
+
+ /**
+ * Called when the block is clicked by a player. Args: x, y, z, entityPlayer
+ */
+ public void onBlockClicked(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer) {
+ }
+
+ /**
+ * Can add to the passed in vector for a movement vector to be applied to the
+ * entity. Args: x, y, z, entity, vec3d
+ */
+ public void velocityToAddToEntity(World par1World, int par2, int par3, int par4, Entity par5Entity, Vec3 par6Vec3) {
+ }
+
+ /**
+ * Updates the blocks bounds based on its current state. Args: world, x, y, z
+ */
+ public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ }
+
+ /**
+ * returns the block bounderies minX value
+ */
+ public final double getMinX() {
+ return this.minX;
+ }
+
+ /**
+ * returns the block bounderies maxX value
+ */
+ public final double getBlockBoundsMaxX() {
+ return this.maxX;
+ }
+
+ /**
+ * returns the block bounderies minY value
+ */
+ public final double getBlockBoundsMinY() {
+ return this.minY;
+ }
+
+ /**
+ * returns the block bounderies maxY value
+ */
+ public final double getBlockBoundsMaxY() {
+ return this.maxY;
+ }
+
+ /**
+ * returns the block bounderies minZ value
+ */
+ public final double getBlockBoundsMinZ() {
+ return this.minZ;
+ }
+
+ /**
+ * returns the block bounderies maxZ value
+ */
+ public final double getBlockBoundsMaxZ() {
+ return this.maxZ;
+ }
+
+ /**
+ * Returns true if the block is emitting indirect/weak redstone power on the
+ * specified side. If isBlockNormalCube returns true, standard redstone
+ * propagation rules will apply instead and this will not be called. Args:
+ * World, X, Y, Z, side. Note that the side is reversed - eg it is 1 (up) when
+ * checking the bottom of the block.
+ */
+ public int isProvidingWeakPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) {
+ return 0;
+ }
+
+ /**
+ * Can this block provide power. Only wire currently seems to have this change
+ * based on its state.
+ */
+ public boolean canProvidePower() {
+ return false;
+ }
+
+ /**
+ * Triggered whenever an entity collides with this block (enters into the
+ * block). Args: world, x, y, z, entity
+ */
+ public void onEntityCollidedWithBlock(World par1World, int par2, int par3, int par4, Entity par5Entity) {
+ }
+
+ /**
+ * Returns true if the block is emitting direct/strong redstone power on the
+ * specified side. Args: World, X, Y, Z, side. Note that the side is reversed -
+ * eg it is 1 (up) when checking the bottom of the block.
+ */
+ public int isProvidingStrongPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) {
+ return 0;
+ }
+
+ /**
+ * Sets the block's bounds for rendering it as an item
+ */
+ public void setBlockBoundsForItemRender() {
+ }
+
+ /**
+ * Called when the player destroys a block with an item that can harvest it. (i,
+ * j, k) are the coordinates of the block and l is the block's subtype/damage.
+ */
+ public void harvestBlock(World par1World, EntityPlayer par2EntityPlayer, int par3, int par4, int par5, int par6) {
+ par2EntityPlayer.addStat(StatList.mineBlockStatArray[this.blockID], 1);
+ par2EntityPlayer.addExhaustion(0.025F);
+
+ if (this.canSilkHarvest() && EnchantmentHelper.getSilkTouchModifier(par2EntityPlayer)) {
+ ItemStack var8 = this.createStackedBlock(par6);
+
+ if (var8 != null) {
+ this.dropBlockAsItem_do(par1World, par3, par4, par5, var8);
+ }
+ } else {
+ int var7 = EnchantmentHelper.getFortuneModifier(par2EntityPlayer);
+ this.dropBlockAsItem(par1World, par3, par4, par5, par6, var7);
+ }
+ }
+
+ /**
+ * Return true if a player with Silk Touch can harvest this block directly, and
+ * not its normal drops.
+ */
+ protected boolean canSilkHarvest() {
+ return this.renderAsNormalBlock() && !this.isBlockContainer;
+ }
+
+ /**
+ * Returns an item stack containing a single instance of the current block type.
+ * 'i' is the block's subtype/damage and is ignored for blocks which do not
+ * support subtypes. Blocks which cannot be harvested should return null.
+ */
+ protected ItemStack createStackedBlock(int par1) {
+ int var2 = 0;
+
+ if (this.blockID >= 0 && this.blockID < Item.itemsList.length
+ && Item.itemsList[this.blockID].getHasSubtypes()) {
+ var2 = par1;
+ }
+
+ return new ItemStack(this.blockID, 1, var2);
+ }
+
+ /**
+ * Returns the usual quantity dropped by the block plus a bonus of 1 to 'i'
+ * (inclusive).
+ */
+ public int quantityDroppedWithBonus(int par1, EaglercraftRandom par2Random) {
+ return this.quantityDropped(par2Random);
+ }
+
+ /**
+ * Can this block stay at this position. Similar to canPlaceBlockAt except gets
+ * checked often with plants.
+ */
+ public boolean canBlockStay(World par1World, int par2, int par3, int par4) {
+ return true;
+ }
+
+ /**
+ * Called when the block is placed in the world.
+ */
+ public void onBlockPlacedBy(World par1World, int par2, int par3, int par4, EntityLiving par5EntityLiving,
+ ItemStack par6ItemStack) {
+ }
+
+ /**
+ * Called after a block is placed
+ */
+ public void onPostBlockPlaced(World par1World, int par2, int par3, int par4, int par5) {
+ }
+
+ public Block setUnlocalizedName(String par1Str) {
+ this.unlocalizedName = par1Str;
+ return this;
+ }
+
+ /**
+ * Gets the localized name of this block. Used for the statistics page.
+ */
+ public String getLocalizedName() {
+ return StatCollector.translateToLocal(this.getUnlocalizedName() + ".name");
+ }
+
+ /**
+ * Returns the unlocalized name of this block.
+ */
+ public String getUnlocalizedName() {
+ return "tile." + this.unlocalizedName;
+ }
+
+ /**
+ * Called when the block receives a BlockEvent - see World.addBlockEvent. By
+ * default, passes it on to the tile entity at this location. Args: world, x, y,
+ * z, blockID, EventID, event parameter
+ */
+ public boolean onBlockEventReceived(World par1World, int par2, int par3, int par4, int par5, int par6) {
+ return false;
+ }
+
+ /**
+ * Return the state of blocks statistics flags - if the block is counted for
+ * mined and placed.
+ */
+ public boolean getEnableStats() {
+ return this.enableStats;
+ }
+
+ /**
+ * Disable statistics for the block, the block will no count for mined or
+ * placed.
+ */
+ protected Block disableStats() {
+ this.enableStats = false;
+ return this;
+ }
+
+ /**
+ * Returns the mobility information of the block, 0 = free, 1 = can't push but
+ * can move over, 2 = total immobility and stop pistons
+ */
+ public int getMobilityFlag() {
+ return this.blockMaterial.getMaterialMobility();
+ }
+
+ /**
+ * Block's chance to react to an entity falling on it.
+ */
+ public void onFallenUpon(World par1World, int par2, int par3, int par4, Entity par5Entity, float par6) {
+ }
+
+ /**
+ * Get the block's damage value (for use with pick block).
+ */
+ public int getDamageValue(World par1World, int par2, int par3, int par4) {
+ return this.damageDropped(par1World.getBlockMetadata(par2, par3, par4));
+ }
+
+ /**
+ * Sets the CreativeTab to display this block on.
+ */
+ public Block setCreativeTab(CreativeTabs par1CreativeTabs) {
+ this.displayOnCreativeTab = par1CreativeTabs;
+ return this;
+ }
+
+ /**
+ * Called when the block is attempted to be harvested
+ */
+ public void onBlockHarvested(World par1World, int par2, int par3, int par4, int par5,
+ EntityPlayer par6EntityPlayer) {
+ }
+
+ /**
+ * Called when this block is set (with meta data).
+ */
+ public void onSetBlockIDWithMetaData(World par1World, int par2, int par3, int par4, int par5) {
+ }
+
+ /**
+ * currently only used by BlockCauldron to incrament meta-data during rain
+ */
+ public void fillWithRain(World par1World, int par2, int par3, int par4) {
+ }
+
+ public boolean func_82506_l() {
+ return true;
+ }
+
+ /**
+ * Return whether this block can drop from an explosion.
+ */
+ public boolean canDropFromExplosion(Explosion par1Explosion) {
+ return true;
+ }
+
+ /**
+ * Returns true if the given block ID is equivalent to this one. Example:
+ * redstoneTorchOn matches itself and redstoneTorchOff, and vice versa. Most
+ * blocks only match themselves.
+ */
+ public boolean isAssociatedBlockID(int par1) {
+ return this.blockID == par1;
+ }
+
+ /**
+ * Static version of isAssociatedBlockID.
+ */
+ public static boolean isAssociatedBlockID(int par0, int par1) {
+ return par0 == par1 ? true
+ : (par0 != 0 && par1 != 0 && blocksList[par0] != null && blocksList[par1] != null
+ ? blocksList[par0].isAssociatedBlockID(par1)
+ : false);
+ }
+
+ /**
+ * If this returns true, then comparators facing away from this block will use
+ * the value from getComparatorInputOverride instead of the actual redstone
+ * signal strength.
+ */
+ public boolean hasComparatorInputOverride() {
+ return false;
+ }
+
+ /**
+ * If hasComparatorInputOverride returns true, the return value from this is
+ * used instead of the redstone signal strength when this block inputs to a
+ * comparator.
+ */
+ public int getComparatorInputOverride(World par1World, int par2, int par3, int par4, int par5) {
+ return 0;
+ }
+
+ static {
+ Item.itemsList[cloth.blockID] = (new ItemCloth(cloth.blockID - 256)).setUnlocalizedName("cloth");
+ Item.itemsList[wood.blockID] = (new ItemMultiTextureTile(wood.blockID - 256, wood, BlockLog.woodType))
+ .setUnlocalizedName("log");
+ Item.itemsList[planks.blockID] = (new ItemMultiTextureTile(planks.blockID - 256, planks, BlockWood.woodType))
+ .setUnlocalizedName("wood");
+ Item.itemsList[silverfish.blockID] = (new ItemMultiTextureTile(silverfish.blockID - 256, silverfish,
+ BlockSilverfish.silverfishStoneTypes)).setUnlocalizedName("monsterStoneEgg");
+ Item.itemsList[stoneBrick.blockID] = (new ItemMultiTextureTile(stoneBrick.blockID - 256, stoneBrick,
+ BlockStoneBrick.STONE_BRICK_TYPES)).setUnlocalizedName("stonebricksmooth");
+ Item.itemsList[sandStone.blockID] = (new ItemMultiTextureTile(sandStone.blockID - 256, sandStone,
+ BlockSandStone.SAND_STONE_TYPES)).setUnlocalizedName("sandStone");
+ Item.itemsList[blockNetherQuartz.blockID] = (new ItemMultiTextureTile(blockNetherQuartz.blockID - 256,
+ blockNetherQuartz, BlockQuartz.quartzBlockTypes)).setUnlocalizedName("quartzBlock");
+ Item.itemsList[stoneSingleSlab.blockID] = (new ItemSlab(stoneSingleSlab.blockID - 256, stoneSingleSlab,
+ stoneDoubleSlab, false)).setUnlocalizedName("stoneSlab");
+ Item.itemsList[stoneDoubleSlab.blockID] = (new ItemSlab(stoneDoubleSlab.blockID - 256, stoneSingleSlab,
+ stoneDoubleSlab, true)).setUnlocalizedName("stoneSlab");
+ Item.itemsList[woodSingleSlab.blockID] = (new ItemSlab(woodSingleSlab.blockID - 256, woodSingleSlab,
+ woodDoubleSlab, false)).setUnlocalizedName("woodSlab");
+ Item.itemsList[woodDoubleSlab.blockID] = (new ItemSlab(woodDoubleSlab.blockID - 256, woodSingleSlab,
+ woodDoubleSlab, true)).setUnlocalizedName("woodSlab");
+ Item.itemsList[sapling.blockID] = (new ItemMultiTextureTile(sapling.blockID - 256, sapling,
+ BlockSapling.WOOD_TYPES)).setUnlocalizedName("sapling");
+ Item.itemsList[leaves.blockID] = (new ItemLeaves(leaves.blockID - 256)).setUnlocalizedName("leaves");
+ Item.itemsList[vine.blockID] = new ItemColored(vine.blockID - 256, false);
+ Item.itemsList[tallGrass.blockID] = (new ItemColored(tallGrass.blockID - 256, true))
+ .setBlockNames(new String[] { "shrub", "grass", "fern" });
+ Item.itemsList[snow.blockID] = new ItemSnow(snow.blockID - 256, snow);
+ Item.itemsList[waterlily.blockID] = new ItemLilyPad(waterlily.blockID - 256);
+ Item.itemsList[pistonBase.blockID] = new ItemPiston(pistonBase.blockID - 256);
+ Item.itemsList[pistonStickyBase.blockID] = new ItemPiston(pistonStickyBase.blockID - 256);
+ Item.itemsList[cobblestoneWall.blockID] = (new ItemMultiTextureTile(cobblestoneWall.blockID - 256,
+ cobblestoneWall, BlockWall.types)).setUnlocalizedName("cobbleWall");
+ Item.itemsList[anvil.blockID] = (new ItemAnvilBlock(anvil)).setUnlocalizedName("anvil");
+
+ for (int var0 = 0; var0 < 256; ++var0) {
+ if (blocksList[var0] != null) {
+ if (Item.itemsList[var0] == null) {
+ Item.itemsList[var0] = new ItemBlock(var0 - 256);
+ blocksList[var0].initializeBlock();
+ }
+
+ boolean var1 = false;
+
+ if (var0 > 0 && blocksList[var0].getRenderType() == 10) {
+ var1 = true;
+ }
+
+ if (var0 > 0 && blocksList[var0] instanceof BlockHalfSlab) {
+ var1 = true;
+ }
+
+ if (var0 == tilledField.blockID) {
+ var1 = true;
+ }
+
+ if (canBlockGrass[var0]) {
+ var1 = true;
+ }
+
+ if (lightOpacity[var0] == 0) {
+ var1 = true;
+ }
+
+ useNeighborBrightness[var0] = var1;
+ }
+ }
+
+ canBlockGrass[0] = true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockAnvil.java b/sp-server/src/main/java/net/minecraft/src/BlockAnvil.java
new file mode 100644
index 0000000..6fe2ec2
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockAnvil.java
@@ -0,0 +1,114 @@
+package net.minecraft.src;
+
+public class BlockAnvil extends BlockSand {
+ /** List of types/statues the Anvil can be in. */
+ public static final String[] statuses = new String[] { "intact", "slightlyDamaged", "veryDamaged" };
+ private static final String[] anvilIconNames = new String[] { "anvil_top", "anvil_top_damaged_1",
+ "anvil_top_damaged_2" };
+ public int field_82521_b = 0;
+
+ protected BlockAnvil(int par1) {
+ super(par1, Material.anvil);
+ this.setLightOpacity(0);
+ this.setCreativeTab(CreativeTabs.tabDecorations);
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * Called when the block is placed in the world.
+ */
+ public void onBlockPlacedBy(World par1World, int par2, int par3, int par4, EntityLiving par5EntityLiving,
+ ItemStack par6ItemStack) {
+ int var7 = MathHelper.floor_double((double) (par5EntityLiving.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3;
+ int var8 = par1World.getBlockMetadata(par2, par3, par4) >> 2;
+ ++var7;
+ var7 %= 4;
+
+ if (var7 == 0) {
+ par1World.setBlockMetadata(par2, par3, par4, 2 | var8 << 2, 2);
+ }
+
+ if (var7 == 1) {
+ par1World.setBlockMetadata(par2, par3, par4, 3 | var8 << 2, 2);
+ }
+
+ if (var7 == 2) {
+ par1World.setBlockMetadata(par2, par3, par4, 0 | var8 << 2, 2);
+ }
+
+ if (var7 == 3) {
+ par1World.setBlockMetadata(par2, par3, par4, 1 | var8 << 2, 2);
+ }
+ }
+
+ /**
+ * Called upon block activation (right click on the block.)
+ */
+ public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer,
+ int par6, float par7, float par8, float par9) {
+ if (par1World.isRemote) {
+ return true;
+ } else {
+ par5EntityPlayer.displayGUIAnvil(par2, par3, par4);
+ return true;
+ }
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 35;
+ }
+
+ /**
+ * Determines the damage on the item the block drops. Used in cloth and wood.
+ */
+ public int damageDropped(int par1) {
+ return par1 >> 2;
+ }
+
+ /**
+ * Updates the blocks bounds based on its current state. Args: world, x, y, z
+ */
+ public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ int var5 = par1IBlockAccess.getBlockMetadata(par2, par3, par4) & 3;
+
+ if (var5 != 3 && var5 != 1) {
+ this.setBlockBounds(0.125F, 0.0F, 0.0F, 0.875F, 1.0F, 1.0F);
+ } else {
+ this.setBlockBounds(0.0F, 0.0F, 0.125F, 1.0F, 1.0F, 0.875F);
+ }
+ }
+
+ /**
+ * Called when the falling block entity for this block is created
+ */
+ protected void onStartFalling(EntityFallingSand par1EntityFallingSand) {
+ par1EntityFallingSand.setIsAnvil(true);
+ }
+
+ /**
+ * Called when the falling block entity for this block hits the ground and turns
+ * back into a block
+ */
+ public void onFinishFalling(World par1World, int par2, int par3, int par4, int par5) {
+ par1World.playAuxSFX(1022, par2, par3, par4, 0);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockBasePressurePlate.java b/sp-server/src/main/java/net/minecraft/src/BlockBasePressurePlate.java
new file mode 100644
index 0000000..c1481d2
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockBasePressurePlate.java
@@ -0,0 +1,238 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public abstract class BlockBasePressurePlate extends Block {
+ private String pressurePlateIconName;
+
+ protected BlockBasePressurePlate(int par1, String par2Str, Material par3Material) {
+ super(par1, par3Material);
+ this.pressurePlateIconName = par2Str;
+ this.setCreativeTab(CreativeTabs.tabRedstone);
+ this.setTickRandomly(true);
+ this.func_94353_c_(this.getMetaFromWeight(15));
+ }
+
+ /**
+ * Updates the blocks bounds based on its current state. Args: world, x, y, z
+ */
+ public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ this.func_94353_c_(par1IBlockAccess.getBlockMetadata(par2, par3, par4));
+ }
+
+ protected void func_94353_c_(int par1) {
+ boolean var2 = this.getPowerSupply(par1) > 0;
+ float var3 = 0.0625F;
+
+ if (var2) {
+ this.setBlockBounds(var3, 0.0F, var3, 1.0F - var3, 0.03125F, 1.0F - var3);
+ } else {
+ this.setBlockBounds(var3, 0.0F, var3, 1.0F - var3, 0.0625F, 1.0F - var3);
+ }
+ }
+
+ /**
+ * How many world ticks before ticking
+ */
+ public int tickRate(World par1World) {
+ return 20;
+ }
+
+ /**
+ * Returns a bounding box from the pool of bounding boxes (this means this box
+ * can change after the pool has been cleared to be reused)
+ */
+ public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) {
+ return null;
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ public boolean getBlocksMovement(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ return true;
+ }
+
+ /**
+ * Checks to see if its valid to put this block at the specified coordinates.
+ * Args: world, x, y, z
+ */
+ public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4) {
+ return par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4)
+ || BlockFence.isIdAFence(par1World.getBlockId(par2, par3 - 1, par4));
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ boolean var6 = false;
+
+ if (!par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4)
+ && !BlockFence.isIdAFence(par1World.getBlockId(par2, par3 - 1, par4))) {
+ var6 = true;
+ }
+
+ if (var6) {
+ this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
+ par1World.setBlockToAir(par2, par3, par4);
+ }
+ }
+
+ /**
+ * Ticks the block if it's been scheduled
+ */
+ public void updateTick(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ if (!par1World.isRemote) {
+ int var6 = this.getPowerSupply(par1World.getBlockMetadata(par2, par3, par4));
+
+ if (var6 > 0) {
+ this.setStateIfMobInteractsWithPlate(par1World, par2, par3, par4, var6);
+ }
+ }
+ }
+
+ /**
+ * Triggered whenever an entity collides with this block (enters into the
+ * block). Args: world, x, y, z, entity
+ */
+ public void onEntityCollidedWithBlock(World par1World, int par2, int par3, int par4, Entity par5Entity) {
+ if (!par1World.isRemote) {
+ int var6 = this.getPowerSupply(par1World.getBlockMetadata(par2, par3, par4));
+
+ if (var6 == 0) {
+ this.setStateIfMobInteractsWithPlate(par1World, par2, par3, par4, var6);
+ }
+ }
+ }
+
+ /**
+ * Checks if there are mobs on the plate. If a mob is on the plate and it is
+ * off, it turns it on, and vice versa.
+ */
+ protected void setStateIfMobInteractsWithPlate(World par1World, int par2, int par3, int par4, int par5) {
+ int var6 = this.getPlateState(par1World, par2, par3, par4);
+ boolean var7 = par5 > 0;
+ boolean var8 = var6 > 0;
+
+ if (par5 != var6) {
+ par1World.setBlockMetadata(par2, par3, par4, this.getMetaFromWeight(var6), 2);
+ this.func_94354_b_(par1World, par2, par3, par4);
+ par1World.markBlockRangeForRenderUpdate(par2, par3, par4, par2, par3, par4);
+ }
+
+ if (!var8 && var7) {
+ par1World.playSoundEffect((double) par2 + 0.5D, (double) par3 + 0.1D, (double) par4 + 0.5D, "random.click",
+ 0.3F, 0.5F);
+ } else if (var8 && !var7) {
+ par1World.playSoundEffect((double) par2 + 0.5D, (double) par3 + 0.1D, (double) par4 + 0.5D, "random.click",
+ 0.3F, 0.6F);
+ }
+
+ if (var8) {
+ par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, this.tickRate(par1World));
+ }
+ }
+
+ protected AxisAlignedBB getSensitiveAABB(int par1, int par2, int par3) {
+ float var4 = 0.125F;
+ return AxisAlignedBB.getAABBPool().getAABB((double) ((float) par1 + var4), (double) par2,
+ (double) ((float) par3 + var4), (double) ((float) (par1 + 1) - var4), (double) par2 + 0.25D,
+ (double) ((float) (par3 + 1) - var4));
+ }
+
+ /**
+ * ejects contained items into the world, and notifies neighbours of an update,
+ * as appropriate
+ */
+ public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) {
+ if (this.getPowerSupply(par6) > 0) {
+ this.func_94354_b_(par1World, par2, par3, par4);
+ }
+
+ super.breakBlock(par1World, par2, par3, par4, par5, par6);
+ }
+
+ protected void func_94354_b_(World par1World, int par2, int par3, int par4) {
+ par1World.notifyBlocksOfNeighborChange(par2, par3, par4, this.blockID);
+ par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID);
+ }
+
+ /**
+ * Returns true if the block is emitting indirect/weak redstone power on the
+ * specified side. If isBlockNormalCube returns true, standard redstone
+ * propagation rules will apply instead and this will not be called. Args:
+ * World, X, Y, Z, side. Note that the side is reversed - eg it is 1 (up) when
+ * checking the bottom of the block.
+ */
+ public int isProvidingWeakPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) {
+ return this.getPowerSupply(par1IBlockAccess.getBlockMetadata(par2, par3, par4));
+ }
+
+ /**
+ * Returns true if the block is emitting direct/strong redstone power on the
+ * specified side. Args: World, X, Y, Z, side. Note that the side is reversed -
+ * eg it is 1 (up) when checking the bottom of the block.
+ */
+ public int isProvidingStrongPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) {
+ return par5 == 1 ? this.getPowerSupply(par1IBlockAccess.getBlockMetadata(par2, par3, par4)) : 0;
+ }
+
+ /**
+ * Can this block provide power. Only wire currently seems to have this change
+ * based on its state.
+ */
+ public boolean canProvidePower() {
+ return true;
+ }
+
+ /**
+ * Sets the block's bounds for rendering it as an item
+ */
+ public void setBlockBoundsForItemRender() {
+ float var1 = 0.5F;
+ float var2 = 0.125F;
+ float var3 = 0.5F;
+ this.setBlockBounds(0.5F - var1, 0.5F - var2, 0.5F - var3, 0.5F + var1, 0.5F + var2, 0.5F + var3);
+ }
+
+ /**
+ * Returns the mobility information of the block, 0 = free, 1 = can't push but
+ * can move over, 2 = total immobility and stop pistons
+ */
+ public int getMobilityFlag() {
+ return 1;
+ }
+
+ /**
+ * Returns the current state of the pressure plate. Returns a value between 0
+ * and 15 based on the number of items on it.
+ */
+ protected abstract int getPlateState(World var1, int var2, int var3, int var4);
+
+ /**
+ * Argument is metadata. Returns power level (0-15)
+ */
+ protected abstract int getPowerSupply(int var1);
+
+ /**
+ * Argument is weight (0-15). Return the metadata to be set because of it.
+ */
+ protected abstract int getMetaFromWeight(int var1);
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockBaseRailLogic.java b/sp-server/src/main/java/net/minecraft/src/BlockBaseRailLogic.java
new file mode 100644
index 0000000..005e908
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockBaseRailLogic.java
@@ -0,0 +1,368 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class BlockBaseRailLogic {
+ private World logicWorld;
+ private int railX;
+ private int railY;
+ private int railZ;
+ private final boolean isStraightRail;
+
+ /** The positions of connected rails */
+ private List connectedTracks;
+
+ final BlockRailBase theRail;
+
+ public BlockBaseRailLogic(BlockRailBase par1, World par2, int par3, int par4, int par5) {
+ this.theRail = par1;
+ this.connectedTracks = new ArrayList();
+ this.logicWorld = par2;
+ this.railX = par3;
+ this.railY = par4;
+ this.railZ = par5;
+ int var6 = par2.getBlockId(par3, par4, par5);
+ int var7 = par2.getBlockMetadata(par3, par4, par5);
+
+ if (((BlockRailBase) Block.blocksList[var6]).isPowered) {
+ this.isStraightRail = true;
+ var7 &= -9;
+ } else {
+ this.isStraightRail = false;
+ }
+
+ this.setBasicRail(var7);
+ }
+
+ private void setBasicRail(int par1) {
+ this.connectedTracks.clear();
+
+ if (par1 == 0) {
+ this.connectedTracks.add(new ChunkPosition(this.railX, this.railY, this.railZ - 1));
+ this.connectedTracks.add(new ChunkPosition(this.railX, this.railY, this.railZ + 1));
+ } else if (par1 == 1) {
+ this.connectedTracks.add(new ChunkPosition(this.railX - 1, this.railY, this.railZ));
+ this.connectedTracks.add(new ChunkPosition(this.railX + 1, this.railY, this.railZ));
+ } else if (par1 == 2) {
+ this.connectedTracks.add(new ChunkPosition(this.railX - 1, this.railY, this.railZ));
+ this.connectedTracks.add(new ChunkPosition(this.railX + 1, this.railY + 1, this.railZ));
+ } else if (par1 == 3) {
+ this.connectedTracks.add(new ChunkPosition(this.railX - 1, this.railY + 1, this.railZ));
+ this.connectedTracks.add(new ChunkPosition(this.railX + 1, this.railY, this.railZ));
+ } else if (par1 == 4) {
+ this.connectedTracks.add(new ChunkPosition(this.railX, this.railY + 1, this.railZ - 1));
+ this.connectedTracks.add(new ChunkPosition(this.railX, this.railY, this.railZ + 1));
+ } else if (par1 == 5) {
+ this.connectedTracks.add(new ChunkPosition(this.railX, this.railY, this.railZ - 1));
+ this.connectedTracks.add(new ChunkPosition(this.railX, this.railY + 1, this.railZ + 1));
+ } else if (par1 == 6) {
+ this.connectedTracks.add(new ChunkPosition(this.railX + 1, this.railY, this.railZ));
+ this.connectedTracks.add(new ChunkPosition(this.railX, this.railY, this.railZ + 1));
+ } else if (par1 == 7) {
+ this.connectedTracks.add(new ChunkPosition(this.railX - 1, this.railY, this.railZ));
+ this.connectedTracks.add(new ChunkPosition(this.railX, this.railY, this.railZ + 1));
+ } else if (par1 == 8) {
+ this.connectedTracks.add(new ChunkPosition(this.railX - 1, this.railY, this.railZ));
+ this.connectedTracks.add(new ChunkPosition(this.railX, this.railY, this.railZ - 1));
+ } else if (par1 == 9) {
+ this.connectedTracks.add(new ChunkPosition(this.railX + 1, this.railY, this.railZ));
+ this.connectedTracks.add(new ChunkPosition(this.railX, this.railY, this.railZ - 1));
+ }
+ }
+
+ private void refreshConnectedTracks() {
+ for (int var1 = 0; var1 < this.connectedTracks.size(); ++var1) {
+ BlockBaseRailLogic var2 = this.getRailLogic((ChunkPosition) this.connectedTracks.get(var1));
+
+ if (var2 != null && var2.isRailChunkPositionCorrect(this)) {
+ this.connectedTracks.set(var1, new ChunkPosition(var2.railX, var2.railY, var2.railZ));
+ } else {
+ this.connectedTracks.remove(var1--);
+ }
+ }
+ }
+
+ private boolean isMinecartTrack(int par1, int par2, int par3) {
+ return BlockRailBase.isRailBlockAt(this.logicWorld, par1, par2, par3) ? true
+ : (BlockRailBase.isRailBlockAt(this.logicWorld, par1, par2 + 1, par3) ? true
+ : BlockRailBase.isRailBlockAt(this.logicWorld, par1, par2 - 1, par3));
+ }
+
+ private BlockBaseRailLogic getRailLogic(ChunkPosition par1ChunkPosition) {
+ return BlockRailBase.isRailBlockAt(this.logicWorld, par1ChunkPosition.x, par1ChunkPosition.y,
+ par1ChunkPosition.z)
+ ? new BlockBaseRailLogic(this.theRail, this.logicWorld, par1ChunkPosition.x,
+ par1ChunkPosition.y, par1ChunkPosition.z)
+ : (BlockRailBase.isRailBlockAt(this.logicWorld, par1ChunkPosition.x, par1ChunkPosition.y + 1,
+ par1ChunkPosition.z)
+ ? new BlockBaseRailLogic(this.theRail, this.logicWorld, par1ChunkPosition.x,
+ par1ChunkPosition.y + 1, par1ChunkPosition.z)
+ : (BlockRailBase.isRailBlockAt(this.logicWorld, par1ChunkPosition.x,
+ par1ChunkPosition.y - 1, par1ChunkPosition.z)
+ ? new BlockBaseRailLogic(this.theRail, this.logicWorld,
+ par1ChunkPosition.x, par1ChunkPosition.y - 1,
+ par1ChunkPosition.z)
+ : null));
+ }
+
+ /**
+ * Checks if the rail is at the chunk position it is expected to be.
+ */
+ private boolean isRailChunkPositionCorrect(BlockBaseRailLogic par1BlockBaseRailLogic) {
+ for (int var2 = 0; var2 < this.connectedTracks.size(); ++var2) {
+ ChunkPosition var3 = (ChunkPosition) this.connectedTracks.get(var2);
+
+ if (var3.x == par1BlockBaseRailLogic.railX && var3.z == par1BlockBaseRailLogic.railZ) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private boolean isPartOfTrack(int par1, int par2, int par3) {
+ for (int var4 = 0; var4 < this.connectedTracks.size(); ++var4) {
+ ChunkPosition var5 = (ChunkPosition) this.connectedTracks.get(var4);
+
+ if (var5.x == par1 && var5.z == par3) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ protected int getNumberOfAdjacentTracks() {
+ int var1 = 0;
+
+ if (this.isMinecartTrack(this.railX, this.railY, this.railZ - 1)) {
+ ++var1;
+ }
+
+ if (this.isMinecartTrack(this.railX, this.railY, this.railZ + 1)) {
+ ++var1;
+ }
+
+ if (this.isMinecartTrack(this.railX - 1, this.railY, this.railZ)) {
+ ++var1;
+ }
+
+ if (this.isMinecartTrack(this.railX + 1, this.railY, this.railZ)) {
+ ++var1;
+ }
+
+ return var1;
+ }
+
+ private boolean canConnectTo(BlockBaseRailLogic par1BlockBaseRailLogic) {
+ return this.isRailChunkPositionCorrect(par1BlockBaseRailLogic) ? true
+ : (this.connectedTracks.size() == 2 ? false : (this.connectedTracks.isEmpty() ? true : true));
+ }
+
+ private void connectToNeighbor(BlockBaseRailLogic par1BlockBaseRailLogic) {
+ this.connectedTracks.add(new ChunkPosition(par1BlockBaseRailLogic.railX, par1BlockBaseRailLogic.railY,
+ par1BlockBaseRailLogic.railZ));
+ boolean var2 = this.isPartOfTrack(this.railX, this.railY, this.railZ - 1);
+ boolean var3 = this.isPartOfTrack(this.railX, this.railY, this.railZ + 1);
+ boolean var4 = this.isPartOfTrack(this.railX - 1, this.railY, this.railZ);
+ boolean var5 = this.isPartOfTrack(this.railX + 1, this.railY, this.railZ);
+ byte var6 = -1;
+
+ if (var2 || var3) {
+ var6 = 0;
+ }
+
+ if (var4 || var5) {
+ var6 = 1;
+ }
+
+ if (!this.isStraightRail) {
+ if (var3 && var5 && !var2 && !var4) {
+ var6 = 6;
+ }
+
+ if (var3 && var4 && !var2 && !var5) {
+ var6 = 7;
+ }
+
+ if (var2 && var4 && !var3 && !var5) {
+ var6 = 8;
+ }
+
+ if (var2 && var5 && !var3 && !var4) {
+ var6 = 9;
+ }
+ }
+
+ if (var6 == 0) {
+ if (BlockRailBase.isRailBlockAt(this.logicWorld, this.railX, this.railY + 1, this.railZ - 1)) {
+ var6 = 4;
+ }
+
+ if (BlockRailBase.isRailBlockAt(this.logicWorld, this.railX, this.railY + 1, this.railZ + 1)) {
+ var6 = 5;
+ }
+ }
+
+ if (var6 == 1) {
+ if (BlockRailBase.isRailBlockAt(this.logicWorld, this.railX + 1, this.railY + 1, this.railZ)) {
+ var6 = 2;
+ }
+
+ if (BlockRailBase.isRailBlockAt(this.logicWorld, this.railX - 1, this.railY + 1, this.railZ)) {
+ var6 = 3;
+ }
+ }
+
+ if (var6 < 0) {
+ var6 = 0;
+ }
+
+ int var7 = var6;
+
+ if (this.isStraightRail) {
+ var7 = this.logicWorld.getBlockMetadata(this.railX, this.railY, this.railZ) & 8 | var6;
+ }
+
+ this.logicWorld.setBlockMetadata(this.railX, this.railY, this.railZ, var7, 3);
+ }
+
+ private boolean canConnectFrom(int par1, int par2, int par3) {
+ BlockBaseRailLogic var4 = this.getRailLogic(new ChunkPosition(par1, par2, par3));
+
+ if (var4 == null) {
+ return false;
+ } else {
+ var4.refreshConnectedTracks();
+ return var4.canConnectTo(this);
+ }
+ }
+
+ public void func_94511_a(boolean par1, boolean par2) {
+ boolean var3 = this.canConnectFrom(this.railX, this.railY, this.railZ - 1);
+ boolean var4 = this.canConnectFrom(this.railX, this.railY, this.railZ + 1);
+ boolean var5 = this.canConnectFrom(this.railX - 1, this.railY, this.railZ);
+ boolean var6 = this.canConnectFrom(this.railX + 1, this.railY, this.railZ);
+ byte var7 = -1;
+
+ if ((var3 || var4) && !var5 && !var6) {
+ var7 = 0;
+ }
+
+ if ((var5 || var6) && !var3 && !var4) {
+ var7 = 1;
+ }
+
+ if (!this.isStraightRail) {
+ if (var4 && var6 && !var3 && !var5) {
+ var7 = 6;
+ }
+
+ if (var4 && var5 && !var3 && !var6) {
+ var7 = 7;
+ }
+
+ if (var3 && var5 && !var4 && !var6) {
+ var7 = 8;
+ }
+
+ if (var3 && var6 && !var4 && !var5) {
+ var7 = 9;
+ }
+ }
+
+ if (var7 == -1) {
+ if (var3 || var4) {
+ var7 = 0;
+ }
+
+ if (var5 || var6) {
+ var7 = 1;
+ }
+
+ if (!this.isStraightRail) {
+ if (par1) {
+ if (var4 && var6) {
+ var7 = 6;
+ }
+
+ if (var5 && var4) {
+ var7 = 7;
+ }
+
+ if (var6 && var3) {
+ var7 = 9;
+ }
+
+ if (var3 && var5) {
+ var7 = 8;
+ }
+ } else {
+ if (var3 && var5) {
+ var7 = 8;
+ }
+
+ if (var6 && var3) {
+ var7 = 9;
+ }
+
+ if (var5 && var4) {
+ var7 = 7;
+ }
+
+ if (var4 && var6) {
+ var7 = 6;
+ }
+ }
+ }
+ }
+
+ if (var7 == 0) {
+ if (BlockRailBase.isRailBlockAt(this.logicWorld, this.railX, this.railY + 1, this.railZ - 1)) {
+ var7 = 4;
+ }
+
+ if (BlockRailBase.isRailBlockAt(this.logicWorld, this.railX, this.railY + 1, this.railZ + 1)) {
+ var7 = 5;
+ }
+ }
+
+ if (var7 == 1) {
+ if (BlockRailBase.isRailBlockAt(this.logicWorld, this.railX + 1, this.railY + 1, this.railZ)) {
+ var7 = 2;
+ }
+
+ if (BlockRailBase.isRailBlockAt(this.logicWorld, this.railX - 1, this.railY + 1, this.railZ)) {
+ var7 = 3;
+ }
+ }
+
+ if (var7 < 0) {
+ var7 = 0;
+ }
+
+ this.setBasicRail(var7);
+ int var8 = var7;
+
+ if (this.isStraightRail) {
+ var8 = this.logicWorld.getBlockMetadata(this.railX, this.railY, this.railZ) & 8 | var7;
+ }
+
+ if (par2 || this.logicWorld.getBlockMetadata(this.railX, this.railY, this.railZ) != var8) {
+ this.logicWorld.setBlockMetadata(this.railX, this.railY, this.railZ, var8, 3);
+
+ for (int var9 = 0; var9 < this.connectedTracks.size(); ++var9) {
+ BlockBaseRailLogic var10 = this.getRailLogic((ChunkPosition) this.connectedTracks.get(var9));
+
+ if (var10 != null) {
+ var10.refreshConnectedTracks();
+
+ if (var10.canConnectTo(this)) {
+ var10.connectToNeighbor(this);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockBeacon.java b/sp-server/src/main/java/net/minecraft/src/BlockBeacon.java
new file mode 100644
index 0000000..28c0402
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockBeacon.java
@@ -0,0 +1,72 @@
+package net.minecraft.src;
+
+public class BlockBeacon extends BlockContainer {
+ public BlockBeacon(int par1) {
+ super(par1, Material.glass);
+ this.setHardness(3.0F);
+ this.setCreativeTab(CreativeTabs.tabMisc);
+ }
+
+ /**
+ * Returns a new instance of a block's tile entity class. Called on placing the
+ * block.
+ */
+ public TileEntity createNewTileEntity(World par1World) {
+ return new TileEntityBeacon();
+ }
+
+ /**
+ * Called upon block activation (right click on the block.)
+ */
+ public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer,
+ int par6, float par7, float par8, float par9) {
+ if (par1World.isRemote) {
+ return true;
+ } else {
+ TileEntityBeacon var10 = (TileEntityBeacon) par1World.getBlockTileEntity(par2, par3, par4);
+
+ if (var10 != null) {
+ par5EntityPlayer.displayGUIBeacon(var10);
+ }
+
+ return true;
+ }
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 34;
+ }
+
+ /**
+ * Called when the block is placed in the world.
+ */
+ public void onBlockPlacedBy(World par1World, int par2, int par3, int par4, EntityLiving par5EntityLiving,
+ ItemStack par6ItemStack) {
+ super.onBlockPlacedBy(par1World, par2, par3, par4, par5EntityLiving, par6ItemStack);
+
+ if (par6ItemStack.hasDisplayName()) {
+ ((TileEntityBeacon) par1World.getBlockTileEntity(par2, par3, par4))
+ .func_94047_a(par6ItemStack.getDisplayName());
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockBed.java b/sp-server/src/main/java/net/minecraft/src/BlockBed.java
new file mode 100644
index 0000000..eec28a9
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockBed.java
@@ -0,0 +1,265 @@
+package net.minecraft.src;
+
+import java.util.Iterator;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockBed extends BlockDirectional {
+ /** Maps the foot-of-bed block to the head-of-bed block. */
+ public static final int[][] footBlockToHeadBlockMap = new int[][] { { 0, 1 }, { -1, 0 }, { 0, -1 }, { 1, 0 } };
+
+ public BlockBed(int par1) {
+ super(par1, Material.cloth);
+ this.setBounds();
+ }
+
+ /**
+ * Called upon block activation (right click on the block.)
+ */
+ public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer,
+ int par6, float par7, float par8, float par9) {
+ if (par1World.isRemote) {
+ return true;
+ } else {
+ int var10 = par1World.getBlockMetadata(par2, par3, par4);
+
+ if (!isBlockHeadOfBed(var10)) {
+ int var11 = getDirection(var10);
+ par2 += footBlockToHeadBlockMap[var11][0];
+ par4 += footBlockToHeadBlockMap[var11][1];
+
+ if (par1World.getBlockId(par2, par3, par4) != this.blockID) {
+ return true;
+ }
+
+ var10 = par1World.getBlockMetadata(par2, par3, par4);
+ }
+
+ if (par1World.provider.canRespawnHere()
+ && par1World.getBiomeGenForCoords(par2, par4) != BiomeGenBase.hell) {
+ if (isBedOccupied(var10)) {
+ EntityPlayer var19 = null;
+ Iterator var12 = par1World.playerEntities.iterator();
+
+ while (var12.hasNext()) {
+ EntityPlayer var21 = (EntityPlayer) var12.next();
+
+ if (var21.isPlayerSleeping()) {
+ ChunkCoordinates var14 = var21.playerLocation;
+
+ if (var14.posX == par2 && var14.posY == par3 && var14.posZ == par4) {
+ var19 = var21;
+ }
+ }
+ }
+
+ if (var19 != null) {
+ par5EntityPlayer.addChatMessage("tile.bed.occupied");
+ return true;
+ }
+
+ setBedOccupied(par1World, par2, par3, par4, false);
+ }
+
+ EnumStatus var20 = par5EntityPlayer.sleepInBedAt(par2, par3, par4);
+
+ if (var20 == EnumStatus.OK) {
+ setBedOccupied(par1World, par2, par3, par4, true);
+ return true;
+ } else {
+ if (var20 == EnumStatus.NOT_POSSIBLE_NOW) {
+ par5EntityPlayer.addChatMessage("tile.bed.noSleep");
+ } else if (var20 == EnumStatus.NOT_SAFE) {
+ par5EntityPlayer.addChatMessage("tile.bed.notSafe");
+ }
+
+ return true;
+ }
+ } else {
+ double var18 = (double) par2 + 0.5D;
+ double var13 = (double) par3 + 0.5D;
+ double var15 = (double) par4 + 0.5D;
+ par1World.setBlockToAir(par2, par3, par4);
+ int var17 = getDirection(var10);
+ par2 += footBlockToHeadBlockMap[var17][0];
+ par4 += footBlockToHeadBlockMap[var17][1];
+
+ if (par1World.getBlockId(par2, par3, par4) == this.blockID) {
+ par1World.setBlockToAir(par2, par3, par4);
+ var18 = (var18 + (double) par2 + 0.5D) / 2.0D;
+ var13 = (var13 + (double) par3 + 0.5D) / 2.0D;
+ var15 = (var15 + (double) par4 + 0.5D) / 2.0D;
+ }
+
+ par1World.newExplosion((Entity) null, (double) ((float) par2 + 0.5F), (double) ((float) par3 + 0.5F),
+ (double) ((float) par4 + 0.5F), 5.0F, true, true);
+ return true;
+ }
+ }
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 14;
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * Updates the blocks bounds based on its current state. Args: world, x, y, z
+ */
+ public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ this.setBounds();
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ int var6 = par1World.getBlockMetadata(par2, par3, par4);
+ int var7 = getDirection(var6);
+
+ if (isBlockHeadOfBed(var6)) {
+ if (par1World.getBlockId(par2 - footBlockToHeadBlockMap[var7][0], par3,
+ par4 - footBlockToHeadBlockMap[var7][1]) != this.blockID) {
+ par1World.setBlockToAir(par2, par3, par4);
+ }
+ } else if (par1World.getBlockId(par2 + footBlockToHeadBlockMap[var7][0], par3,
+ par4 + footBlockToHeadBlockMap[var7][1]) != this.blockID) {
+ par1World.setBlockToAir(par2, par3, par4);
+
+ if (!par1World.isRemote) {
+ this.dropBlockAsItem(par1World, par2, par3, par4, var6, 0);
+ }
+ }
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return isBlockHeadOfBed(par1) ? 0 : Item.bed.itemID;
+ }
+
+ /**
+ * Set the bounds of the bed block.
+ */
+ private void setBounds() {
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.5625F, 1.0F);
+ }
+
+ /**
+ * Returns whether or not this bed block is the head of the bed.
+ */
+ public static boolean isBlockHeadOfBed(int par0) {
+ return (par0 & 8) != 0;
+ }
+
+ /**
+ * Return whether or not the bed is occupied.
+ */
+ public static boolean isBedOccupied(int par0) {
+ return (par0 & 4) != 0;
+ }
+
+ /**
+ * Sets whether or not the bed is occupied.
+ */
+ public static void setBedOccupied(World par0World, int par1, int par2, int par3, boolean par4) {
+ int var5 = par0World.getBlockMetadata(par1, par2, par3);
+
+ if (par4) {
+ var5 |= 4;
+ } else {
+ var5 &= -5;
+ }
+
+ par0World.setBlockMetadata(par1, par2, par3, var5, 4);
+ }
+
+ /**
+ * Gets the nearest empty chunk coordinates for the player to wake up from a bed
+ * into.
+ */
+ public static ChunkCoordinates getNearestEmptyChunkCoordinates(World par0World, int par1, int par2, int par3,
+ int par4) {
+ int var5 = par0World.getBlockMetadata(par1, par2, par3);
+ int var6 = BlockDirectional.getDirection(var5);
+
+ for (int var7 = 0; var7 <= 1; ++var7) {
+ int var8 = par1 - footBlockToHeadBlockMap[var6][0] * var7 - 1;
+ int var9 = par3 - footBlockToHeadBlockMap[var6][1] * var7 - 1;
+ int var10 = var8 + 2;
+ int var11 = var9 + 2;
+
+ for (int var12 = var8; var12 <= var10; ++var12) {
+ for (int var13 = var9; var13 <= var11; ++var13) {
+ if (par0World.doesBlockHaveSolidTopSurface(var12, par2 - 1, var13)
+ && par0World.isAirBlock(var12, par2, var13)
+ && par0World.isAirBlock(var12, par2 + 1, var13)) {
+ if (par4 <= 0) {
+ return new ChunkCoordinates(var12, par2, var13);
+ }
+
+ --par4;
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Drops the block items with a specified chance of dropping the specified items
+ */
+ public void dropBlockAsItemWithChance(World par1World, int par2, int par3, int par4, int par5, float par6,
+ int par7) {
+ if (!isBlockHeadOfBed(par5)) {
+ super.dropBlockAsItemWithChance(par1World, par2, par3, par4, par5, par6, 0);
+ }
+ }
+
+ /**
+ * Returns the mobility information of the block, 0 = free, 1 = can't push but
+ * can move over, 2 = total immobility and stop pistons
+ */
+ public int getMobilityFlag() {
+ return 1;
+ }
+
+ /**
+ * Called when the block is attempted to be harvested
+ */
+ public void onBlockHarvested(World par1World, int par2, int par3, int par4, int par5,
+ EntityPlayer par6EntityPlayer) {
+ if (par6EntityPlayer.capabilities.isCreativeMode && isBlockHeadOfBed(par5)) {
+ int var7 = getDirection(par5);
+ par2 -= footBlockToHeadBlockMap[var7][0];
+ par4 -= footBlockToHeadBlockMap[var7][1];
+
+ if (par1World.getBlockId(par2, par3, par4) == this.blockID) {
+ par1World.setBlockToAir(par2, par3, par4);
+ }
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockBookshelf.java b/sp-server/src/main/java/net/minecraft/src/BlockBookshelf.java
new file mode 100644
index 0000000..730705a
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockBookshelf.java
@@ -0,0 +1,24 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockBookshelf extends Block {
+ public BlockBookshelf(int par1) {
+ super(par1, Material.wood);
+ this.setCreativeTab(CreativeTabs.tabBlock);
+ }
+
+ /**
+ * Returns the quantity of items to drop on block destruction.
+ */
+ public int quantityDropped(EaglercraftRandom par1Random) {
+ return 3;
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return Item.book.itemID;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockBreakable.java b/sp-server/src/main/java/net/minecraft/src/BlockBreakable.java
new file mode 100644
index 0000000..a125733
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockBreakable.java
@@ -0,0 +1,21 @@
+package net.minecraft.src;
+
+public class BlockBreakable extends Block {
+ private boolean localFlag;
+ private String breakableBlockIcon;
+
+ protected BlockBreakable(int par1, String par2Str, Material par3Material, boolean par4) {
+ super(par1, par3Material);
+ this.localFlag = par4;
+ this.breakableBlockIcon = par2Str;
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockBrewingStand.java b/sp-server/src/main/java/net/minecraft/src/BlockBrewingStand.java
new file mode 100644
index 0000000..4dba507
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockBrewingStand.java
@@ -0,0 +1,161 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockBrewingStand extends BlockContainer {
+ private EaglercraftRandom rand = new EaglercraftRandom();
+
+ public BlockBrewingStand(int par1) {
+ super(par1, Material.iron);
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 25;
+ }
+
+ /**
+ * Returns a new instance of a block's tile entity class. Called on placing the
+ * block.
+ */
+ public TileEntity createNewTileEntity(World par1World) {
+ return new TileEntityBrewingStand();
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ /**
+ * Adds all intersecting collision boxes to a list. (Be sure to only add boxes
+ * to the list if they intersect the mask.) Parameters: World, X, Y, Z, mask,
+ * list, colliding entity
+ */
+ public void addCollisionBoxesToList(World par1World, int par2, int par3, int par4, AxisAlignedBB par5AxisAlignedBB,
+ List par6List, Entity par7Entity) {
+ this.setBlockBounds(0.4375F, 0.0F, 0.4375F, 0.5625F, 0.875F, 0.5625F);
+ super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
+ this.setBlockBoundsForItemRender();
+ super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
+ }
+
+ /**
+ * Sets the block's bounds for rendering it as an item
+ */
+ public void setBlockBoundsForItemRender() {
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.125F, 1.0F);
+ }
+
+ /**
+ * Called upon block activation (right click on the block.)
+ */
+ public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer,
+ int par6, float par7, float par8, float par9) {
+ if (par1World.isRemote) {
+ return true;
+ } else {
+ TileEntityBrewingStand var10 = (TileEntityBrewingStand) par1World.getBlockTileEntity(par2, par3, par4);
+
+ if (var10 != null) {
+ par5EntityPlayer.displayGUIBrewingStand(var10);
+ }
+
+ return true;
+ }
+ }
+
+ /**
+ * Called when the block is placed in the world.
+ */
+ public void onBlockPlacedBy(World par1World, int par2, int par3, int par4, EntityLiving par5EntityLiving,
+ ItemStack par6ItemStack) {
+ if (par6ItemStack.hasDisplayName()) {
+ ((TileEntityBrewingStand) par1World.getBlockTileEntity(par2, par3, par4))
+ .func_94131_a(par6ItemStack.getDisplayName());
+ }
+ }
+
+ /**
+ * ejects contained items into the world, and notifies neighbours of an update,
+ * as appropriate
+ */
+ public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) {
+ TileEntity var7 = par1World.getBlockTileEntity(par2, par3, par4);
+
+ if (var7 instanceof TileEntityBrewingStand) {
+ TileEntityBrewingStand var8 = (TileEntityBrewingStand) var7;
+
+ for (int var9 = 0; var9 < var8.getSizeInventory(); ++var9) {
+ ItemStack var10 = var8.getStackInSlot(var9);
+
+ if (var10 != null) {
+ float var11 = this.rand.nextFloat() * 0.8F + 0.1F;
+ float var12 = this.rand.nextFloat() * 0.8F + 0.1F;
+ float var13 = this.rand.nextFloat() * 0.8F + 0.1F;
+
+ while (var10.stackSize > 0) {
+ int var14 = this.rand.nextInt(21) + 10;
+
+ if (var14 > var10.stackSize) {
+ var14 = var10.stackSize;
+ }
+
+ var10.stackSize -= var14;
+ EntityItem var15 = new EntityItem(par1World, (double) ((float) par2 + var11),
+ (double) ((float) par3 + var12), (double) ((float) par4 + var13),
+ new ItemStack(var10.itemID, var14, var10.getItemDamage()));
+ float var16 = 0.05F;
+ var15.motionX = (double) ((float) this.rand.nextGaussian() * var16);
+ var15.motionY = (double) ((float) this.rand.nextGaussian() * var16 + 0.2F);
+ var15.motionZ = (double) ((float) this.rand.nextGaussian() * var16);
+ par1World.spawnEntityInWorld(var15);
+ }
+ }
+ }
+ }
+
+ super.breakBlock(par1World, par2, par3, par4, par5, par6);
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return Item.brewingStand.itemID;
+ }
+
+ /**
+ * If this returns true, then comparators facing away from this block will use
+ * the value from getComparatorInputOverride instead of the actual redstone
+ * signal strength.
+ */
+ public boolean hasComparatorInputOverride() {
+ return true;
+ }
+
+ /**
+ * If hasComparatorInputOverride returns true, the return value from this is
+ * used instead of the redstone signal strength when this block inputs to a
+ * comparator.
+ */
+ public int getComparatorInputOverride(World par1World, int par2, int par3, int par4, int par5) {
+ return Container.calcRedstoneFromInventory((IInventory) par1World.getBlockTileEntity(par2, par3, par4));
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockButton.java b/sp-server/src/main/java/net/minecraft/src/BlockButton.java
new file mode 100644
index 0000000..c4b95a1
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockButton.java
@@ -0,0 +1,356 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public abstract class BlockButton extends Block {
+ /** Whether this button is sensible to arrows, used by wooden buttons. */
+ private final boolean sensible;
+
+ protected BlockButton(int par1, boolean par2) {
+ super(par1, Material.circuits);
+ this.setTickRandomly(true);
+ this.setCreativeTab(CreativeTabs.tabRedstone);
+ this.sensible = par2;
+ }
+
+ /**
+ * Returns a bounding box from the pool of bounding boxes (this means this box
+ * can change after the pool has been cleared to be reused)
+ */
+ public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) {
+ return null;
+ }
+
+ /**
+ * How many world ticks before ticking
+ */
+ public int tickRate(World par1World) {
+ return this.sensible ? 30 : 20;
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ /**
+ * checks to see if you can place this block can be placed on that side of a
+ * block: BlockLever overrides
+ */
+ public boolean canPlaceBlockOnSide(World par1World, int par2, int par3, int par4, int par5) {
+ return par5 == 2 && par1World.isBlockNormalCube(par2, par3, par4 + 1) ? true
+ : (par5 == 3 && par1World.isBlockNormalCube(par2, par3, par4 - 1) ? true
+ : (par5 == 4 && par1World.isBlockNormalCube(par2 + 1, par3, par4) ? true
+ : par5 == 5 && par1World.isBlockNormalCube(par2 - 1, par3, par4)));
+ }
+
+ /**
+ * Checks to see if its valid to put this block at the specified coordinates.
+ * Args: world, x, y, z
+ */
+ public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4) {
+ return par1World.isBlockNormalCube(par2 - 1, par3, par4) ? true
+ : (par1World.isBlockNormalCube(par2 + 1, par3, par4) ? true
+ : (par1World.isBlockNormalCube(par2, par3, par4 - 1) ? true
+ : par1World.isBlockNormalCube(par2, par3, par4 + 1)));
+ }
+
+ /**
+ * Called when a block is placed using its ItemBlock. Args: World, X, Y, Z,
+ * side, hitX, hitY, hitZ, block metadata
+ */
+ public int onBlockPlaced(World par1World, int par2, int par3, int par4, int par5, float par6, float par7,
+ float par8, int par9) {
+ int var10 = par1World.getBlockMetadata(par2, par3, par4);
+ int var11 = var10 & 8;
+ var10 &= 7;
+
+ if (par5 == 2 && par1World.isBlockNormalCube(par2, par3, par4 + 1)) {
+ var10 = 4;
+ } else if (par5 == 3 && par1World.isBlockNormalCube(par2, par3, par4 - 1)) {
+ var10 = 3;
+ } else if (par5 == 4 && par1World.isBlockNormalCube(par2 + 1, par3, par4)) {
+ var10 = 2;
+ } else if (par5 == 5 && par1World.isBlockNormalCube(par2 - 1, par3, par4)) {
+ var10 = 1;
+ } else {
+ var10 = this.getOrientation(par1World, par2, par3, par4);
+ }
+
+ return var10 + var11;
+ }
+
+ /**
+ * Get side which this button is facing.
+ */
+ private int getOrientation(World par1World, int par2, int par3, int par4) {
+ return par1World.isBlockNormalCube(par2 - 1, par3, par4) ? 1
+ : (par1World.isBlockNormalCube(par2 + 1, par3, par4) ? 2
+ : (par1World.isBlockNormalCube(par2, par3, par4 - 1) ? 3
+ : (par1World.isBlockNormalCube(par2, par3, par4 + 1) ? 4 : 1)));
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ if (this.redundantCanPlaceBlockAt(par1World, par2, par3, par4)) {
+ int var6 = par1World.getBlockMetadata(par2, par3, par4) & 7;
+ boolean var7 = false;
+
+ if (!par1World.isBlockNormalCube(par2 - 1, par3, par4) && var6 == 1) {
+ var7 = true;
+ }
+
+ if (!par1World.isBlockNormalCube(par2 + 1, par3, par4) && var6 == 2) {
+ var7 = true;
+ }
+
+ if (!par1World.isBlockNormalCube(par2, par3, par4 - 1) && var6 == 3) {
+ var7 = true;
+ }
+
+ if (!par1World.isBlockNormalCube(par2, par3, par4 + 1) && var6 == 4) {
+ var7 = true;
+ }
+
+ if (var7) {
+ this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
+ par1World.setBlockToAir(par2, par3, par4);
+ }
+ }
+ }
+
+ /**
+ * This method is redundant, check it out...
+ */
+ private boolean redundantCanPlaceBlockAt(World par1World, int par2, int par3, int par4) {
+ if (!this.canPlaceBlockAt(par1World, par2, par3, par4)) {
+ this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
+ par1World.setBlockToAir(par2, par3, par4);
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * Updates the blocks bounds based on its current state. Args: world, x, y, z
+ */
+ public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ int var5 = par1IBlockAccess.getBlockMetadata(par2, par3, par4);
+ this.func_82534_e(var5);
+ }
+
+ private void func_82534_e(int par1) {
+ int var2 = par1 & 7;
+ boolean var3 = (par1 & 8) > 0;
+ float var4 = 0.375F;
+ float var5 = 0.625F;
+ float var6 = 0.1875F;
+ float var7 = 0.125F;
+
+ if (var3) {
+ var7 = 0.0625F;
+ }
+
+ if (var2 == 1) {
+ this.setBlockBounds(0.0F, var4, 0.5F - var6, var7, var5, 0.5F + var6);
+ } else if (var2 == 2) {
+ this.setBlockBounds(1.0F - var7, var4, 0.5F - var6, 1.0F, var5, 0.5F + var6);
+ } else if (var2 == 3) {
+ this.setBlockBounds(0.5F - var6, var4, 0.0F, 0.5F + var6, var5, var7);
+ } else if (var2 == 4) {
+ this.setBlockBounds(0.5F - var6, var4, 1.0F - var7, 0.5F + var6, var5, 1.0F);
+ }
+ }
+
+ /**
+ * Called when the block is clicked by a player. Args: x, y, z, entityPlayer
+ */
+ public void onBlockClicked(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer) {
+ }
+
+ /**
+ * Called upon block activation (right click on the block.)
+ */
+ public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer,
+ int par6, float par7, float par8, float par9) {
+ int var10 = par1World.getBlockMetadata(par2, par3, par4);
+ int var11 = var10 & 7;
+ int var12 = 8 - (var10 & 8);
+
+ if (var12 == 0) {
+ return true;
+ } else {
+ par1World.setBlockMetadata(par2, par3, par4, var11 + var12, 3);
+ par1World.markBlockRangeForRenderUpdate(par2, par3, par4, par2, par3, par4);
+ par1World.playSoundEffect((double) par2 + 0.5D, (double) par3 + 0.5D, (double) par4 + 0.5D, "random.click",
+ 0.3F, 0.6F);
+ this.func_82536_d(par1World, par2, par3, par4, var11);
+ par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, this.tickRate(par1World));
+ return true;
+ }
+ }
+
+ /**
+ * ejects contained items into the world, and notifies neighbours of an update,
+ * as appropriate
+ */
+ public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) {
+ if ((par6 & 8) > 0) {
+ int var7 = par6 & 7;
+ this.func_82536_d(par1World, par2, par3, par4, var7);
+ }
+
+ super.breakBlock(par1World, par2, par3, par4, par5, par6);
+ }
+
+ /**
+ * Returns true if the block is emitting indirect/weak redstone power on the
+ * specified side. If isBlockNormalCube returns true, standard redstone
+ * propagation rules will apply instead and this will not be called. Args:
+ * World, X, Y, Z, side. Note that the side is reversed - eg it is 1 (up) when
+ * checking the bottom of the block.
+ */
+ public int isProvidingWeakPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) {
+ return (par1IBlockAccess.getBlockMetadata(par2, par3, par4) & 8) > 0 ? 15 : 0;
+ }
+
+ /**
+ * Returns true if the block is emitting direct/strong redstone power on the
+ * specified side. Args: World, X, Y, Z, side. Note that the side is reversed -
+ * eg it is 1 (up) when checking the bottom of the block.
+ */
+ public int isProvidingStrongPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) {
+ int var6 = par1IBlockAccess.getBlockMetadata(par2, par3, par4);
+
+ if ((var6 & 8) == 0) {
+ return 0;
+ } else {
+ int var7 = var6 & 7;
+ return var7 == 5 && par5 == 1 ? 15
+ : (var7 == 4 && par5 == 2 ? 15
+ : (var7 == 3 && par5 == 3 ? 15
+ : (var7 == 2 && par5 == 4 ? 15 : (var7 == 1 && par5 == 5 ? 15 : 0))));
+ }
+ }
+
+ /**
+ * Can this block provide power. Only wire currently seems to have this change
+ * based on its state.
+ */
+ public boolean canProvidePower() {
+ return true;
+ }
+
+ /**
+ * Ticks the block if it's been scheduled
+ */
+ public void updateTick(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ if (!par1World.isRemote) {
+ int var6 = par1World.getBlockMetadata(par2, par3, par4);
+
+ if ((var6 & 8) != 0) {
+ if (this.sensible) {
+ this.func_82535_o(par1World, par2, par3, par4);
+ } else {
+ par1World.setBlockMetadata(par2, par3, par4, var6 & 7, 3);
+ int var7 = var6 & 7;
+ this.func_82536_d(par1World, par2, par3, par4, var7);
+ par1World.playSoundEffect((double) par2 + 0.5D, (double) par3 + 0.5D, (double) par4 + 0.5D,
+ "random.click", 0.3F, 0.5F);
+ par1World.markBlockRangeForRenderUpdate(par2, par3, par4, par2, par3, par4);
+ }
+ }
+ }
+ }
+
+ /**
+ * Sets the block's bounds for rendering it as an item
+ */
+ public void setBlockBoundsForItemRender() {
+ float var1 = 0.1875F;
+ float var2 = 0.125F;
+ float var3 = 0.125F;
+ this.setBlockBounds(0.5F - var1, 0.5F - var2, 0.5F - var3, 0.5F + var1, 0.5F + var2, 0.5F + var3);
+ }
+
+ /**
+ * Triggered whenever an entity collides with this block (enters into the
+ * block). Args: world, x, y, z, entity
+ */
+ public void onEntityCollidedWithBlock(World par1World, int par2, int par3, int par4, Entity par5Entity) {
+ if (!par1World.isRemote) {
+ if (this.sensible) {
+ if ((par1World.getBlockMetadata(par2, par3, par4) & 8) == 0) {
+ this.func_82535_o(par1World, par2, par3, par4);
+ }
+ }
+ }
+ }
+
+ private void func_82535_o(World par1World, int par2, int par3, int par4) {
+ int var5 = par1World.getBlockMetadata(par2, par3, par4);
+ int var6 = var5 & 7;
+ boolean var7 = (var5 & 8) != 0;
+ this.func_82534_e(var5);
+ List var9 = par1World.getEntitiesWithinAABB(EntityArrow.class,
+ AxisAlignedBB.getAABBPool().getAABB((double) par2 + this.minX, (double) par3 + this.minY,
+ (double) par4 + this.minZ, (double) par2 + this.maxX, (double) par3 + this.maxY,
+ (double) par4 + this.maxZ));
+ boolean var8 = !var9.isEmpty();
+
+ if (var8 && !var7) {
+ par1World.setBlockMetadata(par2, par3, par4, var6 | 8, 3);
+ this.func_82536_d(par1World, par2, par3, par4, var6);
+ par1World.markBlockRangeForRenderUpdate(par2, par3, par4, par2, par3, par4);
+ par1World.playSoundEffect((double) par2 + 0.5D, (double) par3 + 0.5D, (double) par4 + 0.5D, "random.click",
+ 0.3F, 0.6F);
+ }
+
+ if (!var8 && var7) {
+ par1World.setBlockMetadata(par2, par3, par4, var6, 3);
+ this.func_82536_d(par1World, par2, par3, par4, var6);
+ par1World.markBlockRangeForRenderUpdate(par2, par3, par4, par2, par3, par4);
+ par1World.playSoundEffect((double) par2 + 0.5D, (double) par3 + 0.5D, (double) par4 + 0.5D, "random.click",
+ 0.3F, 0.5F);
+ }
+
+ if (var8) {
+ par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, this.tickRate(par1World));
+ }
+ }
+
+ private void func_82536_d(World par1World, int par2, int par3, int par4, int par5) {
+ par1World.notifyBlocksOfNeighborChange(par2, par3, par4, this.blockID);
+
+ if (par5 == 1) {
+ par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID);
+ } else if (par5 == 2) {
+ par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID);
+ } else if (par5 == 3) {
+ par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID);
+ } else if (par5 == 4) {
+ par1World.notifyBlocksOfNeighborChange(par2, par3, par4 + 1, this.blockID);
+ } else {
+ par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockButtonStone.java b/sp-server/src/main/java/net/minecraft/src/BlockButtonStone.java
new file mode 100644
index 0000000..4472d13
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockButtonStone.java
@@ -0,0 +1,7 @@
+package net.minecraft.src;
+
+public class BlockButtonStone extends BlockButton {
+ protected BlockButtonStone(int par1) {
+ super(par1, false);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockButtonWood.java b/sp-server/src/main/java/net/minecraft/src/BlockButtonWood.java
new file mode 100644
index 0000000..071daf5
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockButtonWood.java
@@ -0,0 +1,7 @@
+package net.minecraft.src;
+
+public class BlockButtonWood extends BlockButton {
+ protected BlockButtonWood(int par1) {
+ super(par1, true);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockCactus.java b/sp-server/src/main/java/net/minecraft/src/BlockCactus.java
new file mode 100644
index 0000000..5b55084
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockCactus.java
@@ -0,0 +1,118 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockCactus extends Block {
+ protected BlockCactus(int par1) {
+ super(par1, Material.cactus);
+ this.setTickRandomly(true);
+ this.setCreativeTab(CreativeTabs.tabDecorations);
+ }
+
+ /**
+ * Ticks the block if it's been scheduled
+ */
+ public void updateTick(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ if (par1World.isAirBlock(par2, par3 + 1, par4)) {
+ int var6;
+
+ for (var6 = 1; par1World.getBlockId(par2, par3 - var6, par4) == this.blockID; ++var6) {
+ ;
+ }
+
+ if (var6 < 3) {
+ int var7 = par1World.getBlockMetadata(par2, par3, par4);
+
+ if (var7 == 15) {
+ par1World.setBlock(par2, par3 + 1, par4, this.blockID);
+ par1World.setBlockMetadata(par2, par3, par4, 0, 4);
+ this.onNeighborBlockChange(par1World, par2, par3 + 1, par4, this.blockID);
+ } else {
+ par1World.setBlockMetadata(par2, par3, par4, var7 + 1, 4);
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns a bounding box from the pool of bounding boxes (this means this box
+ * can change after the pool has been cleared to be reused)
+ */
+ public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) {
+ float var5 = 0.0625F;
+ return AxisAlignedBB.getAABBPool().getAABB((double) ((float) par2 + var5), (double) par3,
+ (double) ((float) par4 + var5), (double) ((float) (par2 + 1) - var5),
+ (double) ((float) (par3 + 1) - var5), (double) ((float) (par4 + 1) - var5));
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 13;
+ }
+
+ /**
+ * Checks to see if its valid to put this block at the specified coordinates.
+ * Args: world, x, y, z
+ */
+ public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4) {
+ return !super.canPlaceBlockAt(par1World, par2, par3, par4) ? false
+ : this.canBlockStay(par1World, par2, par3, par4);
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ if (!this.canBlockStay(par1World, par2, par3, par4)) {
+ par1World.destroyBlock(par2, par3, par4, true);
+ }
+ }
+
+ /**
+ * Can this block stay at this position. Similar to canPlaceBlockAt except gets
+ * checked often with plants.
+ */
+ public boolean canBlockStay(World par1World, int par2, int par3, int par4) {
+ if (par1World.getBlockMaterial(par2 - 1, par3, par4).isSolid()) {
+ return false;
+ } else if (par1World.getBlockMaterial(par2 + 1, par3, par4).isSolid()) {
+ return false;
+ } else if (par1World.getBlockMaterial(par2, par3, par4 - 1).isSolid()) {
+ return false;
+ } else if (par1World.getBlockMaterial(par2, par3, par4 + 1).isSolid()) {
+ return false;
+ } else {
+ int var5 = par1World.getBlockId(par2, par3 - 1, par4);
+ return var5 == Block.cactus.blockID || var5 == Block.sand.blockID;
+ }
+ }
+
+ /**
+ * Triggered whenever an entity collides with this block (enters into the
+ * block). Args: world, x, y, z, entity
+ */
+ public void onEntityCollidedWithBlock(World par1World, int par2, int par3, int par4, Entity par5Entity) {
+ par5Entity.attackEntityFrom(DamageSource.cactus, 1);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockCake.java b/sp-server/src/main/java/net/minecraft/src/BlockCake.java
new file mode 100644
index 0000000..b6c21cc
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockCake.java
@@ -0,0 +1,135 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockCake extends Block {
+ protected BlockCake(int par1) {
+ super(par1, Material.cake);
+ this.setTickRandomly(true);
+ }
+
+ /**
+ * Updates the blocks bounds based on its current state. Args: world, x, y, z
+ */
+ public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ int var5 = par1IBlockAccess.getBlockMetadata(par2, par3, par4);
+ float var6 = 0.0625F;
+ float var7 = (float) (1 + var5 * 2) / 16.0F;
+ float var8 = 0.5F;
+ this.setBlockBounds(var7, 0.0F, var6, 1.0F - var6, var8, 1.0F - var6);
+ }
+
+ /**
+ * Sets the block's bounds for rendering it as an item
+ */
+ public void setBlockBoundsForItemRender() {
+ float var1 = 0.0625F;
+ float var2 = 0.5F;
+ this.setBlockBounds(var1, 0.0F, var1, 1.0F - var1, var2, 1.0F - var1);
+ }
+
+ /**
+ * Returns a bounding box from the pool of bounding boxes (this means this box
+ * can change after the pool has been cleared to be reused)
+ */
+ public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) {
+ int var5 = par1World.getBlockMetadata(par2, par3, par4);
+ float var6 = 0.0625F;
+ float var7 = (float) (1 + var5 * 2) / 16.0F;
+ float var8 = 0.5F;
+ return AxisAlignedBB.getAABBPool().getAABB((double) ((float) par2 + var7), (double) par3,
+ (double) ((float) par4 + var6), (double) ((float) (par2 + 1) - var6),
+ (double) ((float) par3 + var8 - var6), (double) ((float) (par4 + 1) - var6));
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * Called upon block activation (right click on the block.)
+ */
+ public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer,
+ int par6, float par7, float par8, float par9) {
+ this.eatCakeSlice(par1World, par2, par3, par4, par5EntityPlayer);
+ return true;
+ }
+
+ /**
+ * Called when the block is clicked by a player. Args: x, y, z, entityPlayer
+ */
+ public void onBlockClicked(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer) {
+ this.eatCakeSlice(par1World, par2, par3, par4, par5EntityPlayer);
+ }
+
+ /**
+ * Heals the player and removes a slice from the cake.
+ */
+ private void eatCakeSlice(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer) {
+ if (par5EntityPlayer.canEat(false)) {
+ par5EntityPlayer.getFoodStats().addStats(2, 0.1F);
+ int var6 = par1World.getBlockMetadata(par2, par3, par4) + 1;
+
+ if (var6 >= 6) {
+ par1World.setBlockToAir(par2, par3, par4);
+ } else {
+ par1World.setBlockMetadata(par2, par3, par4, var6, 2);
+ }
+ }
+ }
+
+ /**
+ * Checks to see if its valid to put this block at the specified coordinates.
+ * Args: world, x, y, z
+ */
+ public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4) {
+ return !super.canPlaceBlockAt(par1World, par2, par3, par4) ? false
+ : this.canBlockStay(par1World, par2, par3, par4);
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ if (!this.canBlockStay(par1World, par2, par3, par4)) {
+ par1World.setBlockToAir(par2, par3, par4);
+ }
+ }
+
+ /**
+ * Can this block stay at this position. Similar to canPlaceBlockAt except gets
+ * checked often with plants.
+ */
+ public boolean canBlockStay(World par1World, int par2, int par3, int par4) {
+ return par1World.getBlockMaterial(par2, par3 - 1, par4).isSolid();
+ }
+
+ /**
+ * Returns the quantity of items to drop on block destruction.
+ */
+ public int quantityDropped(EaglercraftRandom par1Random) {
+ return 0;
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return 0;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockCarrot.java b/sp-server/src/main/java/net/minecraft/src/BlockCarrot.java
new file mode 100644
index 0000000..b93b5b3
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockCarrot.java
@@ -0,0 +1,21 @@
+package net.minecraft.src;
+
+public class BlockCarrot extends BlockCrops {
+ public BlockCarrot(int par1) {
+ super(par1);
+ }
+
+ /**
+ * Generate a seed ItemStack for this crop.
+ */
+ protected int getSeedItem() {
+ return Item.carrot.itemID;
+ }
+
+ /**
+ * Generate a crop produce ItemStack for this crop.
+ */
+ protected int getCropItem() {
+ return Item.carrot.itemID;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockCauldron.java b/sp-server/src/main/java/net/minecraft/src/BlockCauldron.java
new file mode 100644
index 0000000..7bb85a2
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockCauldron.java
@@ -0,0 +1,145 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockCauldron extends Block {
+ public BlockCauldron(int par1) {
+ super(par1, Material.iron);
+ }
+
+ /**
+ * Adds all intersecting collision boxes to a list. (Be sure to only add boxes
+ * to the list if they intersect the mask.) Parameters: World, X, Y, Z, mask,
+ * list, colliding entity
+ */
+ public void addCollisionBoxesToList(World par1World, int par2, int par3, int par4, AxisAlignedBB par5AxisAlignedBB,
+ List par6List, Entity par7Entity) {
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.3125F, 1.0F);
+ super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
+ float var8 = 0.125F;
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, var8, 1.0F, 1.0F);
+ super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, var8);
+ super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
+ this.setBlockBounds(1.0F - var8, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
+ super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
+ this.setBlockBounds(0.0F, 0.0F, 1.0F - var8, 1.0F, 1.0F, 1.0F);
+ super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
+ this.setBlockBoundsForItemRender();
+ }
+
+ /**
+ * Sets the block's bounds for rendering it as an item
+ */
+ public void setBlockBoundsForItemRender() {
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 24;
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ /**
+ * Called upon block activation (right click on the block.)
+ */
+ public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer,
+ int par6, float par7, float par8, float par9) {
+ if (par1World.isRemote) {
+ return true;
+ } else {
+ ItemStack var10 = par5EntityPlayer.inventory.getCurrentItem();
+
+ if (var10 == null) {
+ return true;
+ } else {
+ int var11 = par1World.getBlockMetadata(par2, par3, par4);
+
+ if (var10.itemID == Item.bucketWater.itemID) {
+ if (var11 < 3) {
+ if (!par5EntityPlayer.capabilities.isCreativeMode) {
+ par5EntityPlayer.inventory.setInventorySlotContents(par5EntityPlayer.inventory.currentItem,
+ new ItemStack(Item.bucketEmpty));
+ }
+
+ par1World.setBlockMetadata(par2, par3, par4, 3, 2);
+ }
+
+ return true;
+ } else {
+ if (var10.itemID == Item.glassBottle.itemID) {
+ if (var11 > 0) {
+ ItemStack var12 = new ItemStack(Item.potion, 1, 0);
+
+ if (!par5EntityPlayer.inventory.addItemStackToInventory(var12)) {
+ par1World.spawnEntityInWorld(new EntityItem(par1World, (double) par2 + 0.5D,
+ (double) par3 + 1.5D, (double) par4 + 0.5D, var12));
+ } else if (par5EntityPlayer instanceof EntityPlayerMP) {
+ ((EntityPlayerMP) par5EntityPlayer)
+ .sendContainerToPlayer(par5EntityPlayer.inventoryContainer);
+ }
+
+ --var10.stackSize;
+
+ if (var10.stackSize <= 0) {
+ par5EntityPlayer.inventory.setInventorySlotContents(
+ par5EntityPlayer.inventory.currentItem, (ItemStack) null);
+ }
+
+ par1World.setBlockMetadata(par2, par3, par4, var11 - 1, 2);
+ }
+ } else if (var11 > 0 && var10.getItem() instanceof ItemArmor
+ && ((ItemArmor) var10.getItem()).getArmorMaterial() == EnumArmorMaterial.CLOTH) {
+ ItemArmor var13 = (ItemArmor) var10.getItem();
+ var13.removeColor(var10);
+ par1World.setBlockMetadata(par2, par3, par4, var11 - 1, 2);
+ return true;
+ }
+
+ return true;
+ }
+ }
+ }
+ }
+
+ /**
+ * currently only used by BlockCauldron to incrament meta-data during rain
+ */
+ public void fillWithRain(World par1World, int par2, int par3, int par4) {
+ if (par1World.rand.nextInt(20) == 1) {
+ int var5 = par1World.getBlockMetadata(par2, par3, par4);
+
+ if (var5 < 3) {
+ par1World.setBlockMetadata(par2, par3, par4, var5 + 1, 2);
+ }
+ }
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return Item.cauldron.itemID;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockChest.java b/sp-server/src/main/java/net/minecraft/src/BlockChest.java
new file mode 100644
index 0000000..adc68e6
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockChest.java
@@ -0,0 +1,495 @@
+package net.minecraft.src;
+
+import java.util.Iterator;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockChest extends BlockContainer {
+ private final EaglercraftRandom random = new EaglercraftRandom();
+
+ /** Determines whether of not the chest is trapped. */
+ public final int isTrapped;
+
+ protected BlockChest(int par1, int par2) {
+ super(par1, Material.wood);
+ this.isTrapped = par2;
+ this.setCreativeTab(CreativeTabs.tabDecorations);
+ this.setBlockBounds(0.0625F, 0.0F, 0.0625F, 0.9375F, 0.875F, 0.9375F);
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 22;
+ }
+
+ /**
+ * Updates the blocks bounds based on its current state. Args: world, x, y, z
+ */
+ public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ if (par1IBlockAccess.getBlockId(par2, par3, par4 - 1) == this.blockID) {
+ this.setBlockBounds(0.0625F, 0.0F, 0.0F, 0.9375F, 0.875F, 0.9375F);
+ } else if (par1IBlockAccess.getBlockId(par2, par3, par4 + 1) == this.blockID) {
+ this.setBlockBounds(0.0625F, 0.0F, 0.0625F, 0.9375F, 0.875F, 1.0F);
+ } else if (par1IBlockAccess.getBlockId(par2 - 1, par3, par4) == this.blockID) {
+ this.setBlockBounds(0.0F, 0.0F, 0.0625F, 0.9375F, 0.875F, 0.9375F);
+ } else if (par1IBlockAccess.getBlockId(par2 + 1, par3, par4) == this.blockID) {
+ this.setBlockBounds(0.0625F, 0.0F, 0.0625F, 1.0F, 0.875F, 0.9375F);
+ } else {
+ this.setBlockBounds(0.0625F, 0.0F, 0.0625F, 0.9375F, 0.875F, 0.9375F);
+ }
+ }
+
+ /**
+ * Called whenever the block is added into the world. Args: world, x, y, z
+ */
+ public void onBlockAdded(World par1World, int par2, int par3, int par4) {
+ super.onBlockAdded(par1World, par2, par3, par4);
+ this.unifyAdjacentChests(par1World, par2, par3, par4);
+ int var5 = par1World.getBlockId(par2, par3, par4 - 1);
+ int var6 = par1World.getBlockId(par2, par3, par4 + 1);
+ int var7 = par1World.getBlockId(par2 - 1, par3, par4);
+ int var8 = par1World.getBlockId(par2 + 1, par3, par4);
+
+ if (var5 == this.blockID) {
+ this.unifyAdjacentChests(par1World, par2, par3, par4 - 1);
+ }
+
+ if (var6 == this.blockID) {
+ this.unifyAdjacentChests(par1World, par2, par3, par4 + 1);
+ }
+
+ if (var7 == this.blockID) {
+ this.unifyAdjacentChests(par1World, par2 - 1, par3, par4);
+ }
+
+ if (var8 == this.blockID) {
+ this.unifyAdjacentChests(par1World, par2 + 1, par3, par4);
+ }
+ }
+
+ /**
+ * Called when the block is placed in the world.
+ */
+ public void onBlockPlacedBy(World par1World, int par2, int par3, int par4, EntityLiving par5EntityLiving,
+ ItemStack par6ItemStack) {
+ int var7 = par1World.getBlockId(par2, par3, par4 - 1);
+ int var8 = par1World.getBlockId(par2, par3, par4 + 1);
+ int var9 = par1World.getBlockId(par2 - 1, par3, par4);
+ int var10 = par1World.getBlockId(par2 + 1, par3, par4);
+ byte var11 = 0;
+ int var12 = MathHelper.floor_double((double) (par5EntityLiving.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3;
+
+ if (var12 == 0) {
+ var11 = 2;
+ }
+
+ if (var12 == 1) {
+ var11 = 5;
+ }
+
+ if (var12 == 2) {
+ var11 = 3;
+ }
+
+ if (var12 == 3) {
+ var11 = 4;
+ }
+
+ if (var7 != this.blockID && var8 != this.blockID && var9 != this.blockID && var10 != this.blockID) {
+ par1World.setBlockMetadata(par2, par3, par4, var11, 3);
+ } else {
+ if ((var7 == this.blockID || var8 == this.blockID) && (var11 == 4 || var11 == 5)) {
+ if (var7 == this.blockID) {
+ par1World.setBlockMetadata(par2, par3, par4 - 1, var11, 3);
+ } else {
+ par1World.setBlockMetadata(par2, par3, par4 + 1, var11, 3);
+ }
+
+ par1World.setBlockMetadata(par2, par3, par4, var11, 3);
+ }
+
+ if ((var9 == this.blockID || var10 == this.blockID) && (var11 == 2 || var11 == 3)) {
+ if (var9 == this.blockID) {
+ par1World.setBlockMetadata(par2 - 1, par3, par4, var11, 3);
+ } else {
+ par1World.setBlockMetadata(par2 + 1, par3, par4, var11, 3);
+ }
+
+ par1World.setBlockMetadata(par2, par3, par4, var11, 3);
+ }
+ }
+
+ if (par6ItemStack.hasDisplayName()) {
+ ((TileEntityChest) par1World.getBlockTileEntity(par2, par3, par4))
+ .func_94043_a(par6ItemStack.getDisplayName());
+ }
+ }
+
+ /**
+ * Turns the adjacent chests to a double chest.
+ */
+ public void unifyAdjacentChests(World par1World, int par2, int par3, int par4) {
+ if (!par1World.isRemote) {
+ int var5 = par1World.getBlockId(par2, par3, par4 - 1);
+ int var6 = par1World.getBlockId(par2, par3, par4 + 1);
+ int var7 = par1World.getBlockId(par2 - 1, par3, par4);
+ int var8 = par1World.getBlockId(par2 + 1, par3, par4);
+ boolean var9 = true;
+ int var10;
+ int var11;
+ boolean var12;
+ byte var13;
+ int var14;
+
+ if (var5 != this.blockID && var6 != this.blockID) {
+ if (var7 != this.blockID && var8 != this.blockID) {
+ var13 = 3;
+
+ if (Block.opaqueCubeLookup[var5] && !Block.opaqueCubeLookup[var6]) {
+ var13 = 3;
+ }
+
+ if (Block.opaqueCubeLookup[var6] && !Block.opaqueCubeLookup[var5]) {
+ var13 = 2;
+ }
+
+ if (Block.opaqueCubeLookup[var7] && !Block.opaqueCubeLookup[var8]) {
+ var13 = 5;
+ }
+
+ if (Block.opaqueCubeLookup[var8] && !Block.opaqueCubeLookup[var7]) {
+ var13 = 4;
+ }
+ } else {
+ var10 = par1World.getBlockId(var7 == this.blockID ? par2 - 1 : par2 + 1, par3, par4 - 1);
+ var11 = par1World.getBlockId(var7 == this.blockID ? par2 - 1 : par2 + 1, par3, par4 + 1);
+ var13 = 3;
+ var12 = true;
+
+ if (var7 == this.blockID) {
+ var14 = par1World.getBlockMetadata(par2 - 1, par3, par4);
+ } else {
+ var14 = par1World.getBlockMetadata(par2 + 1, par3, par4);
+ }
+
+ if (var14 == 2) {
+ var13 = 2;
+ }
+
+ if ((Block.opaqueCubeLookup[var5] || Block.opaqueCubeLookup[var10]) && !Block.opaqueCubeLookup[var6]
+ && !Block.opaqueCubeLookup[var11]) {
+ var13 = 3;
+ }
+
+ if ((Block.opaqueCubeLookup[var6] || Block.opaqueCubeLookup[var11]) && !Block.opaqueCubeLookup[var5]
+ && !Block.opaqueCubeLookup[var10]) {
+ var13 = 2;
+ }
+ }
+ } else {
+ var10 = par1World.getBlockId(par2 - 1, par3, var5 == this.blockID ? par4 - 1 : par4 + 1);
+ var11 = par1World.getBlockId(par2 + 1, par3, var5 == this.blockID ? par4 - 1 : par4 + 1);
+ var13 = 5;
+ var12 = true;
+
+ if (var5 == this.blockID) {
+ var14 = par1World.getBlockMetadata(par2, par3, par4 - 1);
+ } else {
+ var14 = par1World.getBlockMetadata(par2, par3, par4 + 1);
+ }
+
+ if (var14 == 4) {
+ var13 = 4;
+ }
+
+ if ((Block.opaqueCubeLookup[var7] || Block.opaqueCubeLookup[var10]) && !Block.opaqueCubeLookup[var8]
+ && !Block.opaqueCubeLookup[var11]) {
+ var13 = 5;
+ }
+
+ if ((Block.opaqueCubeLookup[var8] || Block.opaqueCubeLookup[var11]) && !Block.opaqueCubeLookup[var7]
+ && !Block.opaqueCubeLookup[var10]) {
+ var13 = 4;
+ }
+ }
+
+ par1World.setBlockMetadata(par2, par3, par4, var13, 3);
+ }
+ }
+
+ /**
+ * Checks to see if its valid to put this block at the specified coordinates.
+ * Args: world, x, y, z
+ */
+ public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4) {
+ int var5 = 0;
+
+ if (par1World.getBlockId(par2 - 1, par3, par4) == this.blockID) {
+ ++var5;
+ }
+
+ if (par1World.getBlockId(par2 + 1, par3, par4) == this.blockID) {
+ ++var5;
+ }
+
+ if (par1World.getBlockId(par2, par3, par4 - 1) == this.blockID) {
+ ++var5;
+ }
+
+ if (par1World.getBlockId(par2, par3, par4 + 1) == this.blockID) {
+ ++var5;
+ }
+
+ return var5 > 1 ? false
+ : (this.isThereANeighborChest(par1World, par2 - 1, par3, par4) ? false
+ : (this.isThereANeighborChest(par1World, par2 + 1, par3, par4) ? false
+ : (this.isThereANeighborChest(par1World, par2, par3, par4 - 1) ? false
+ : !this.isThereANeighborChest(par1World, par2, par3, par4 + 1))));
+ }
+
+ /**
+ * Checks the neighbor blocks to see if there is a chest there. Args: world, x,
+ * y, z
+ */
+ private boolean isThereANeighborChest(World par1World, int par2, int par3, int par4) {
+ return par1World.getBlockId(par2, par3, par4) != this.blockID ? false
+ : (par1World.getBlockId(par2 - 1, par3, par4) == this.blockID ? true
+ : (par1World.getBlockId(par2 + 1, par3, par4) == this.blockID ? true
+ : (par1World.getBlockId(par2, par3, par4 - 1) == this.blockID ? true
+ : par1World.getBlockId(par2, par3, par4 + 1) == this.blockID)));
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ super.onNeighborBlockChange(par1World, par2, par3, par4, par5);
+ TileEntityChest var6 = (TileEntityChest) par1World.getBlockTileEntity(par2, par3, par4);
+
+ if (var6 != null) {
+ var6.updateContainingBlockInfo();
+ }
+ }
+
+ /**
+ * ejects contained items into the world, and notifies neighbours of an update,
+ * as appropriate
+ */
+ public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) {
+ TileEntityChest var7 = (TileEntityChest) par1World.getBlockTileEntity(par2, par3, par4);
+
+ if (var7 != null) {
+ for (int var8 = 0; var8 < var7.getSizeInventory(); ++var8) {
+ ItemStack var9 = var7.getStackInSlot(var8);
+
+ if (var9 != null) {
+ float var10 = this.random.nextFloat() * 0.8F + 0.1F;
+ float var11 = this.random.nextFloat() * 0.8F + 0.1F;
+ EntityItem var14;
+
+ for (float var12 = this.random.nextFloat() * 0.8F + 0.1F; var9.stackSize > 0; par1World
+ .spawnEntityInWorld(var14)) {
+ int var13 = this.random.nextInt(21) + 10;
+
+ if (var13 > var9.stackSize) {
+ var13 = var9.stackSize;
+ }
+
+ var9.stackSize -= var13;
+ var14 = new EntityItem(par1World, (double) ((float) par2 + var10),
+ (double) ((float) par3 + var11), (double) ((float) par4 + var12),
+ new ItemStack(var9.itemID, var13, var9.getItemDamage()));
+ float var15 = 0.05F;
+ var14.motionX = (double) ((float) this.random.nextGaussian() * var15);
+ var14.motionY = (double) ((float) this.random.nextGaussian() * var15 + 0.2F);
+ var14.motionZ = (double) ((float) this.random.nextGaussian() * var15);
+
+ if (var9.hasTagCompound()) {
+ var14.getEntityItem().setTagCompound((NBTTagCompound) var9.getTagCompound().copy());
+ }
+ }
+ }
+ }
+
+ par1World.func_96440_m(par2, par3, par4, par5);
+ }
+
+ super.breakBlock(par1World, par2, par3, par4, par5, par6);
+ }
+
+ /**
+ * Called upon block activation (right click on the block.)
+ */
+ public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer,
+ int par6, float par7, float par8, float par9) {
+ if (par1World.isRemote) {
+ return true;
+ } else {
+ IInventory var10 = this.getInventory(par1World, par2, par3, par4);
+
+ if (var10 != null) {
+ par5EntityPlayer.displayGUIChest(var10);
+ }
+
+ return true;
+ }
+ }
+
+ /**
+ * Gets the inventory of the chest at the specified coords, accounting for
+ * blocks or ocelots on top of the chest, and double chests.
+ */
+ public IInventory getInventory(World par1World, int par2, int par3, int par4) {
+ Object var5 = (TileEntityChest) par1World.getBlockTileEntity(par2, par3, par4);
+
+ if (var5 == null) {
+ return null;
+ } else if (par1World.isBlockNormalCube(par2, par3 + 1, par4)) {
+ return null;
+ } else if (isOcelotBlockingChest(par1World, par2, par3, par4)) {
+ return null;
+ } else if (par1World.getBlockId(par2 - 1, par3, par4) == this.blockID
+ && (par1World.isBlockNormalCube(par2 - 1, par3 + 1, par4)
+ || isOcelotBlockingChest(par1World, par2 - 1, par3, par4))) {
+ return null;
+ } else if (par1World.getBlockId(par2 + 1, par3, par4) == this.blockID
+ && (par1World.isBlockNormalCube(par2 + 1, par3 + 1, par4)
+ || isOcelotBlockingChest(par1World, par2 + 1, par3, par4))) {
+ return null;
+ } else if (par1World.getBlockId(par2, par3, par4 - 1) == this.blockID
+ && (par1World.isBlockNormalCube(par2, par3 + 1, par4 - 1)
+ || isOcelotBlockingChest(par1World, par2, par3, par4 - 1))) {
+ return null;
+ } else if (par1World.getBlockId(par2, par3, par4 + 1) == this.blockID
+ && (par1World.isBlockNormalCube(par2, par3 + 1, par4 + 1)
+ || isOcelotBlockingChest(par1World, par2, par3, par4 + 1))) {
+ return null;
+ } else {
+ if (par1World.getBlockId(par2 - 1, par3, par4) == this.blockID) {
+ var5 = new InventoryLargeChest("container.chestDouble",
+ (TileEntityChest) par1World.getBlockTileEntity(par2 - 1, par3, par4), (IInventory) var5);
+ }
+
+ if (par1World.getBlockId(par2 + 1, par3, par4) == this.blockID) {
+ var5 = new InventoryLargeChest("container.chestDouble", (IInventory) var5,
+ (TileEntityChest) par1World.getBlockTileEntity(par2 + 1, par3, par4));
+ }
+
+ if (par1World.getBlockId(par2, par3, par4 - 1) == this.blockID) {
+ var5 = new InventoryLargeChest("container.chestDouble",
+ (TileEntityChest) par1World.getBlockTileEntity(par2, par3, par4 - 1), (IInventory) var5);
+ }
+
+ if (par1World.getBlockId(par2, par3, par4 + 1) == this.blockID) {
+ var5 = new InventoryLargeChest("container.chestDouble", (IInventory) var5,
+ (TileEntityChest) par1World.getBlockTileEntity(par2, par3, par4 + 1));
+ }
+
+ return (IInventory) var5;
+ }
+ }
+
+ /**
+ * Returns a new instance of a block's tile entity class. Called on placing the
+ * block.
+ */
+ public TileEntity createNewTileEntity(World par1World) {
+ TileEntityChest var2 = new TileEntityChest();
+ return var2;
+ }
+
+ /**
+ * Can this block provide power. Only wire currently seems to have this change
+ * based on its state.
+ */
+ public boolean canProvidePower() {
+ return this.isTrapped == 1;
+ }
+
+ /**
+ * Returns true if the block is emitting indirect/weak redstone power on the
+ * specified side. If isBlockNormalCube returns true, standard redstone
+ * propagation rules will apply instead and this will not be called. Args:
+ * World, X, Y, Z, side. Note that the side is reversed - eg it is 1 (up) when
+ * checking the bottom of the block.
+ */
+ public int isProvidingWeakPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) {
+ if (!this.canProvidePower()) {
+ return 0;
+ } else {
+ int var6 = ((TileEntityChest) par1IBlockAccess.getBlockTileEntity(par2, par3, par4)).numUsingPlayers;
+ return MathHelper.clamp_int(var6, 0, 15);
+ }
+ }
+
+ /**
+ * Returns true if the block is emitting direct/strong redstone power on the
+ * specified side. Args: World, X, Y, Z, side. Note that the side is reversed -
+ * eg it is 1 (up) when checking the bottom of the block.
+ */
+ public int isProvidingStrongPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) {
+ return par5 == 1 ? this.isProvidingWeakPower(par1IBlockAccess, par2, par3, par4, par5) : 0;
+ }
+
+ /**
+ * Looks for a sitting ocelot within certain bounds. Such an ocelot is
+ * considered to be blocking access to the chest.
+ */
+ private static boolean isOcelotBlockingChest(World par0World, int par1, int par2, int par3) {
+ Iterator var4 = par0World.getEntitiesWithinAABB(EntityOcelot.class,
+ AxisAlignedBB.getAABBPool().getAABB((double) par1, (double) (par2 + 1), (double) par3,
+ (double) (par1 + 1), (double) (par2 + 2), (double) (par3 + 1)))
+ .iterator();
+ EntityOcelot var6;
+
+ do {
+ if (!var4.hasNext()) {
+ return false;
+ }
+
+ EntityOcelot var5 = (EntityOcelot) var4.next();
+ var6 = (EntityOcelot) var5;
+ } while (!var6.isSitting());
+
+ return true;
+ }
+
+ /**
+ * If this returns true, then comparators facing away from this block will use
+ * the value from getComparatorInputOverride instead of the actual redstone
+ * signal strength.
+ */
+ public boolean hasComparatorInputOverride() {
+ return true;
+ }
+
+ /**
+ * If hasComparatorInputOverride returns true, the return value from this is
+ * used instead of the redstone signal strength when this block inputs to a
+ * comparator.
+ */
+ public int getComparatorInputOverride(World par1World, int par2, int par3, int par4, int par5) {
+ return Container.calcRedstoneFromInventory(this.getInventory(par1World, par2, par3, par4));
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockClay.java b/sp-server/src/main/java/net/minecraft/src/BlockClay.java
new file mode 100644
index 0000000..f9f2534
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockClay.java
@@ -0,0 +1,24 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockClay extends Block {
+ public BlockClay(int par1) {
+ super(par1, Material.clay);
+ this.setCreativeTab(CreativeTabs.tabBlock);
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return Item.clay.itemID;
+ }
+
+ /**
+ * Returns the quantity of items to drop on block destruction.
+ */
+ public int quantityDropped(EaglercraftRandom par1Random) {
+ return 4;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockCloth.java b/sp-server/src/main/java/net/minecraft/src/BlockCloth.java
new file mode 100644
index 0000000..8ccd498
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockCloth.java
@@ -0,0 +1,29 @@
+package net.minecraft.src;
+
+public class BlockCloth extends Block {
+ public BlockCloth() {
+ super(35, Material.cloth);
+ this.setCreativeTab(CreativeTabs.tabBlock);
+ }
+
+ /**
+ * Determines the damage on the item the block drops. Used in cloth and wood.
+ */
+ public int damageDropped(int par1) {
+ return par1;
+ }
+
+ /**
+ * Takes a dye damage value and returns the block damage value to match
+ */
+ public static int getBlockFromDye(int par0) {
+ return ~par0 & 15;
+ }
+
+ /**
+ * Takes a block damage value and returns the dye damage value to match
+ */
+ public static int getDyeFromBlock(int par0) {
+ return ~par0 & 15;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockCocoa.java b/sp-server/src/main/java/net/minecraft/src/BlockCocoa.java
new file mode 100644
index 0000000..e484f34
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockCocoa.java
@@ -0,0 +1,172 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockCocoa extends BlockDirectional {
+ public static final String[] cocoaIcons = new String[] { "cocoa_0", "cocoa_1", "cocoa_2" };
+
+ public BlockCocoa(int par1) {
+ super(par1, Material.plants);
+ this.setTickRandomly(true);
+ }
+
+ /**
+ * Ticks the block if it's been scheduled
+ */
+ public void updateTick(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ if (!this.canBlockStay(par1World, par2, par3, par4)) {
+ this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
+ par1World.setBlockToAir(par2, par3, par4);
+ } else if (par1World.rand.nextInt(5) == 0) {
+ int var6 = par1World.getBlockMetadata(par2, par3, par4);
+ int var7 = func_72219_c(var6);
+
+ if (var7 < 2) {
+ ++var7;
+ par1World.setBlockMetadata(par2, par3, par4, var7 << 2 | getDirection(var6), 2);
+ }
+ }
+ }
+
+ /**
+ * Can this block stay at this position. Similar to canPlaceBlockAt except gets
+ * checked often with plants.
+ */
+ public boolean canBlockStay(World par1World, int par2, int par3, int par4) {
+ int var5 = getDirection(par1World.getBlockMetadata(par2, par3, par4));
+ par2 += Direction.offsetX[var5];
+ par4 += Direction.offsetZ[var5];
+ int var6 = par1World.getBlockId(par2, par3, par4);
+ return var6 == Block.wood.blockID
+ && BlockLog.limitToValidMetadata(par1World.getBlockMetadata(par2, par3, par4)) == 3;
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 28;
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * Returns a bounding box from the pool of bounding boxes (this means this box
+ * can change after the pool has been cleared to be reused)
+ */
+ public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) {
+ this.setBlockBoundsBasedOnState(par1World, par2, par3, par4);
+ return super.getCollisionBoundingBoxFromPool(par1World, par2, par3, par4);
+ }
+
+ /**
+ * Updates the blocks bounds based on its current state. Args: world, x, y, z
+ */
+ public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ int var5 = par1IBlockAccess.getBlockMetadata(par2, par3, par4);
+ int var6 = getDirection(var5);
+ int var7 = func_72219_c(var5);
+ int var8 = 4 + var7 * 2;
+ int var9 = 5 + var7 * 2;
+ float var10 = (float) var8 / 2.0F;
+
+ switch (var6) {
+ case 0:
+ this.setBlockBounds((8.0F - var10) / 16.0F, (12.0F - (float) var9) / 16.0F, (15.0F - (float) var8) / 16.0F,
+ (8.0F + var10) / 16.0F, 0.75F, 0.9375F);
+ break;
+
+ case 1:
+ this.setBlockBounds(0.0625F, (12.0F - (float) var9) / 16.0F, (8.0F - var10) / 16.0F,
+ (1.0F + (float) var8) / 16.0F, 0.75F, (8.0F + var10) / 16.0F);
+ break;
+
+ case 2:
+ this.setBlockBounds((8.0F - var10) / 16.0F, (12.0F - (float) var9) / 16.0F, 0.0625F, (8.0F + var10) / 16.0F,
+ 0.75F, (1.0F + (float) var8) / 16.0F);
+ break;
+
+ case 3:
+ this.setBlockBounds((15.0F - (float) var8) / 16.0F, (12.0F - (float) var9) / 16.0F, (8.0F - var10) / 16.0F,
+ 0.9375F, 0.75F, (8.0F + var10) / 16.0F);
+ }
+ }
+
+ /**
+ * Called when the block is placed in the world.
+ */
+ public void onBlockPlacedBy(World par1World, int par2, int par3, int par4, EntityLiving par5EntityLiving,
+ ItemStack par6ItemStack) {
+ int var7 = ((MathHelper.floor_double((double) (par5EntityLiving.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3) + 0)
+ % 4;
+ par1World.setBlockMetadata(par2, par3, par4, var7, 2);
+ }
+
+ /**
+ * Called when a block is placed using its ItemBlock. Args: World, X, Y, Z,
+ * side, hitX, hitY, hitZ, block metadata
+ */
+ public int onBlockPlaced(World par1World, int par2, int par3, int par4, int par5, float par6, float par7,
+ float par8, int par9) {
+ if (par5 == 1 || par5 == 0) {
+ par5 = 2;
+ }
+
+ return Direction.footInvisibleFaceRemap[Direction.facingToDirection[par5]];
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ if (!this.canBlockStay(par1World, par2, par3, par4)) {
+ this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
+ par1World.setBlockToAir(par2, par3, par4);
+ }
+ }
+
+ public static int func_72219_c(int par0) {
+ return (par0 & 12) >> 2;
+ }
+
+ /**
+ * Drops the block items with a specified chance of dropping the specified items
+ */
+ public void dropBlockAsItemWithChance(World par1World, int par2, int par3, int par4, int par5, float par6,
+ int par7) {
+ int var8 = func_72219_c(par5);
+ byte var9 = 1;
+
+ if (var8 >= 2) {
+ var9 = 3;
+ }
+
+ for (int var10 = 0; var10 < var9; ++var10) {
+ this.dropBlockAsItem_do(par1World, par2, par3, par4, new ItemStack(Item.dyePowder, 1, 3));
+ }
+ }
+
+ /**
+ * Get the block's damage value (for use with pick block).
+ */
+ public int getDamageValue(World par1World, int par2, int par3, int par4) {
+ return 3;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockCommandBlock.java b/sp-server/src/main/java/net/minecraft/src/BlockCommandBlock.java
new file mode 100644
index 0000000..32caec4
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockCommandBlock.java
@@ -0,0 +1,103 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockCommandBlock extends BlockContainer {
+ public BlockCommandBlock(int par1) {
+ super(par1, Material.iron);
+ }
+
+ /**
+ * Returns a new instance of a block's tile entity class. Called on placing the
+ * block.
+ */
+ public TileEntity createNewTileEntity(World par1World) {
+ return new TileEntityCommandBlock();
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ if (!par1World.isRemote) {
+ boolean var6 = par1World.isBlockIndirectlyGettingPowered(par2, par3, par4);
+ int var7 = par1World.getBlockMetadata(par2, par3, par4);
+ boolean var8 = (var7 & 1) != 0;
+
+ if (var6 && !var8) {
+ par1World.setBlockMetadata(par2, par3, par4, var7 | 1, 4);
+ par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, this.tickRate(par1World));
+ } else if (!var6 && var8) {
+ par1World.setBlockMetadata(par2, par3, par4, var7 & -2, 4);
+ }
+ }
+ }
+
+ /**
+ * Ticks the block if it's been scheduled
+ */
+ public void updateTick(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ TileEntity var6 = par1World.getBlockTileEntity(par2, par3, par4);
+
+ if (var6 != null && var6 instanceof TileEntityCommandBlock) {
+ TileEntityCommandBlock var7 = (TileEntityCommandBlock) var6;
+ var7.func_96102_a(var7.executeCommandOnPowered(par1World));
+ par1World.func_96440_m(par2, par3, par4, this.blockID);
+ }
+ }
+
+ /**
+ * How many world ticks before ticking
+ */
+ public int tickRate(World par1World) {
+ return 1;
+ }
+
+ /**
+ * Called upon block activation (right click on the block.)
+ */
+ public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer,
+ int par6, float par7, float par8, float par9) {
+ TileEntityCommandBlock var10 = (TileEntityCommandBlock) par1World.getBlockTileEntity(par2, par3, par4);
+
+ if (var10 != null) {
+ par5EntityPlayer.displayGUIEditSign(var10);
+ }
+
+ return true;
+ }
+
+ /**
+ * If this returns true, then comparators facing away from this block will use
+ * the value from getComparatorInputOverride instead of the actual redstone
+ * signal strength.
+ */
+ public boolean hasComparatorInputOverride() {
+ return true;
+ }
+
+ /**
+ * If hasComparatorInputOverride returns true, the return value from this is
+ * used instead of the redstone signal strength when this block inputs to a
+ * comparator.
+ */
+ public int getComparatorInputOverride(World par1World, int par2, int par3, int par4, int par5) {
+ TileEntity var6 = par1World.getBlockTileEntity(par2, par3, par4);
+ return var6 != null && var6 instanceof TileEntityCommandBlock ? ((TileEntityCommandBlock) var6).func_96103_d()
+ : 0;
+ }
+
+ /**
+ * Called when the block is placed in the world.
+ */
+ public void onBlockPlacedBy(World par1World, int par2, int par3, int par4, EntityLiving par5EntityLiving,
+ ItemStack par6ItemStack) {
+ TileEntityCommandBlock var7 = (TileEntityCommandBlock) par1World.getBlockTileEntity(par2, par3, par4);
+
+ if (par6ItemStack.hasDisplayName()) {
+ var7.setCommandSenderName(par6ItemStack.getDisplayName());
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockComparator.java b/sp-server/src/main/java/net/minecraft/src/BlockComparator.java
new file mode 100644
index 0000000..49dc736
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockComparator.java
@@ -0,0 +1,206 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockComparator extends BlockRedstoneLogic implements ITileEntityProvider {
+ public BlockComparator(int par1, boolean par2) {
+ super(par1, par2);
+ this.isBlockContainer = true;
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return Item.comparator.itemID;
+ }
+
+ protected int func_94481_j_(int par1) {
+ return 2;
+ }
+
+ protected BlockRedstoneLogic func_94485_e() {
+ return Block.redstoneComparatorActive;
+ }
+
+ protected BlockRedstoneLogic func_94484_i() {
+ return Block.redstoneComparatorIdle;
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 37;
+ }
+
+ protected boolean func_96470_c(int par1) {
+ return this.isRepeaterPowered || (par1 & 8) != 0;
+ }
+
+ protected int func_94480_d(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) {
+ return this.getTileEntityComparator(par1IBlockAccess, par2, par3, par4).func_96100_a();
+ }
+
+ private int func_94491_m(World par1World, int par2, int par3, int par4, int par5) {
+ return !this.func_94490_c(par5) ? this.getInputStrength(par1World, par2, par3, par4, par5)
+ : Math.max(this.getInputStrength(par1World, par2, par3, par4, par5)
+ - this.func_94482_f(par1World, par2, par3, par4, par5), 0);
+ }
+
+ public boolean func_94490_c(int par1) {
+ return (par1 & 4) == 4;
+ }
+
+ protected boolean func_94478_d(World par1World, int par2, int par3, int par4, int par5) {
+ int var6 = this.getInputStrength(par1World, par2, par3, par4, par5);
+
+ if (var6 >= 15) {
+ return true;
+ } else if (var6 == 0) {
+ return false;
+ } else {
+ int var7 = this.func_94482_f(par1World, par2, par3, par4, par5);
+ return var7 == 0 ? true : var6 >= var7;
+ }
+ }
+
+ /**
+ * Returns the signal strength at one input of the block. Args: world, X, Y, Z,
+ * side
+ */
+ protected int getInputStrength(World par1World, int par2, int par3, int par4, int par5) {
+ int var6 = super.getInputStrength(par1World, par2, par3, par4, par5);
+ int var7 = getDirection(par5);
+ int var8 = par2 + Direction.offsetX[var7];
+ int var9 = par4 + Direction.offsetZ[var7];
+ int var10 = par1World.getBlockId(var8, par3, var9);
+
+ if (var10 > 0) {
+ if (Block.blocksList[var10].hasComparatorInputOverride()) {
+ var6 = Block.blocksList[var10].getComparatorInputOverride(par1World, var8, par3, var9,
+ Direction.footInvisibleFaceRemap[var7]);
+ } else if (var6 < 15 && Block.isNormalCube(var10)) {
+ var8 += Direction.offsetX[var7];
+ var9 += Direction.offsetZ[var7];
+ var10 = par1World.getBlockId(var8, par3, var9);
+
+ if (var10 > 0 && Block.blocksList[var10].hasComparatorInputOverride()) {
+ var6 = Block.blocksList[var10].getComparatorInputOverride(par1World, var8, par3, var9,
+ Direction.footInvisibleFaceRemap[var7]);
+ }
+ }
+ }
+
+ return var6;
+ }
+
+ /**
+ * Returns the blockTileEntity at given coordinates.
+ */
+ public TileEntityComparator getTileEntityComparator(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ return (TileEntityComparator) par1IBlockAccess.getBlockTileEntity(par2, par3, par4);
+ }
+
+ /**
+ * Called upon block activation (right click on the block.)
+ */
+ public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer,
+ int par6, float par7, float par8, float par9) {
+ int var10 = par1World.getBlockMetadata(par2, par3, par4);
+ boolean var11 = this.isRepeaterPowered | (var10 & 8) != 0;
+ boolean var12 = !this.func_94490_c(var10);
+ int var13 = var12 ? 4 : 0;
+ var13 |= var11 ? 8 : 0;
+ par1World.playSoundEffect((double) par2 + 0.5D, (double) par3 + 0.5D, (double) par4 + 0.5D, "random.click",
+ 0.3F, var12 ? 0.55F : 0.5F);
+ par1World.setBlockMetadata(par2, par3, par4, var13 | var10 & 3, 2);
+ this.func_96476_c(par1World, par2, par3, par4, par1World.rand);
+ return true;
+ }
+
+ protected void func_94479_f(World par1World, int par2, int par3, int par4, int par5) {
+ if (!par1World.isBlockTickScheduled(par2, par3, par4, this.blockID)) {
+ int var6 = par1World.getBlockMetadata(par2, par3, par4);
+ int var7 = this.func_94491_m(par1World, par2, par3, par4, var6);
+ int var8 = this.getTileEntityComparator(par1World, par2, par3, par4).func_96100_a();
+
+ if (var7 != var8 || this.func_96470_c(var6) != this.func_94478_d(par1World, par2, par3, par4, var6)) {
+ if (this.func_83011_d(par1World, par2, par3, par4, var6)) {
+ par1World.func_82740_a(par2, par3, par4, this.blockID, this.func_94481_j_(0), -1);
+ } else {
+ par1World.func_82740_a(par2, par3, par4, this.blockID, this.func_94481_j_(0), 0);
+ }
+ }
+ }
+ }
+
+ private void func_96476_c(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ int var6 = par1World.getBlockMetadata(par2, par3, par4);
+ int var7 = this.func_94491_m(par1World, par2, par3, par4, var6);
+ int var8 = this.getTileEntityComparator(par1World, par2, par3, par4).func_96100_a();
+ this.getTileEntityComparator(par1World, par2, par3, par4).func_96099_a(var7);
+
+ if (var8 != var7 || !this.func_94490_c(var6)) {
+ boolean var9 = this.func_94478_d(par1World, par2, par3, par4, var6);
+ boolean var10 = this.isRepeaterPowered || (var6 & 8) != 0;
+
+ if (var10 && !var9) {
+ par1World.setBlockMetadata(par2, par3, par4, var6 & -9, 2);
+ } else if (!var10 && var9) {
+ par1World.setBlockMetadata(par2, par3, par4, var6 | 8, 2);
+ }
+
+ this.func_94483_i_(par1World, par2, par3, par4);
+ }
+ }
+
+ /**
+ * Ticks the block if it's been scheduled
+ */
+ public void updateTick(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ if (this.isRepeaterPowered) {
+ int var6 = par1World.getBlockMetadata(par2, par3, par4);
+ par1World.setBlock(par2, par3, par4, this.func_94484_i().blockID, var6 | 8, 4);
+ }
+
+ this.func_96476_c(par1World, par2, par3, par4, par5Random);
+ }
+
+ /**
+ * Called whenever the block is added into the world. Args: world, x, y, z
+ */
+ public void onBlockAdded(World par1World, int par2, int par3, int par4) {
+ super.onBlockAdded(par1World, par2, par3, par4);
+ par1World.setBlockTileEntity(par2, par3, par4, this.createNewTileEntity(par1World));
+ }
+
+ /**
+ * ejects contained items into the world, and notifies neighbours of an update,
+ * as appropriate
+ */
+ public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) {
+ super.breakBlock(par1World, par2, par3, par4, par5, par6);
+ par1World.removeBlockTileEntity(par2, par3, par4);
+ this.func_94483_i_(par1World, par2, par3, par4);
+ }
+
+ /**
+ * Called when the block receives a BlockEvent - see World.addBlockEvent. By
+ * default, passes it on to the tile entity at this location. Args: world, x, y,
+ * z, blockID, EventID, event parameter
+ */
+ public boolean onBlockEventReceived(World par1World, int par2, int par3, int par4, int par5, int par6) {
+ super.onBlockEventReceived(par1World, par2, par3, par4, par5, par6);
+ TileEntity var7 = par1World.getBlockTileEntity(par2, par3, par4);
+ return var7 != null ? var7.receiveClientEvent(par5, par6) : false;
+ }
+
+ /**
+ * Returns a new instance of a block's tile entity class. Called on placing the
+ * block.
+ */
+ public TileEntity createNewTileEntity(World par1World) {
+ return new TileEntityComparator();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockContainer.java b/sp-server/src/main/java/net/minecraft/src/BlockContainer.java
new file mode 100644
index 0000000..2eff4d3
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockContainer.java
@@ -0,0 +1,35 @@
+package net.minecraft.src;
+
+public abstract class BlockContainer extends Block implements ITileEntityProvider {
+ protected BlockContainer(int par1, Material par2Material) {
+ super(par1, par2Material);
+ this.isBlockContainer = true;
+ }
+
+ /**
+ * Called whenever the block is added into the world. Args: world, x, y, z
+ */
+ public void onBlockAdded(World par1World, int par2, int par3, int par4) {
+ super.onBlockAdded(par1World, par2, par3, par4);
+ }
+
+ /**
+ * ejects contained items into the world, and notifies neighbours of an update,
+ * as appropriate
+ */
+ public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) {
+ super.breakBlock(par1World, par2, par3, par4, par5, par6);
+ par1World.removeBlockTileEntity(par2, par3, par4);
+ }
+
+ /**
+ * Called when the block receives a BlockEvent - see World.addBlockEvent. By
+ * default, passes it on to the tile entity at this location. Args: world, x, y,
+ * z, blockID, EventID, event parameter
+ */
+ public boolean onBlockEventReceived(World par1World, int par2, int par3, int par4, int par5, int par6) {
+ super.onBlockEventReceived(par1World, par2, par3, par4, par5, par6);
+ TileEntity var7 = par1World.getBlockTileEntity(par2, par3, par4);
+ return var7 != null ? var7.receiveClientEvent(par5, par6) : false;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockCrops.java b/sp-server/src/main/java/net/minecraft/src/BlockCrops.java
new file mode 100644
index 0000000..59b39f4
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockCrops.java
@@ -0,0 +1,162 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockCrops extends BlockFlower {
+ protected BlockCrops(int par1) {
+ super(par1);
+ this.setTickRandomly(true);
+ float var2 = 0.5F;
+ this.setBlockBounds(0.5F - var2, 0.0F, 0.5F - var2, 0.5F + var2, 0.25F, 0.5F + var2);
+ this.setCreativeTab((CreativeTabs) null);
+ this.setHardness(0.0F);
+ this.setStepSound(soundGrassFootstep);
+ this.disableStats();
+ }
+
+ /**
+ * Gets passed in the blockID of the block below and supposed to return true if
+ * its allowed to grow on the type of blockID passed in. Args: blockID
+ */
+ protected boolean canThisPlantGrowOnThisBlockID(int par1) {
+ return par1 == Block.tilledField.blockID;
+ }
+
+ /**
+ * Ticks the block if it's been scheduled
+ */
+ public void updateTick(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ super.updateTick(par1World, par2, par3, par4, par5Random);
+
+ if (par1World.getBlockLightValue(par2, par3 + 1, par4) >= 9) {
+ int var6 = par1World.getBlockMetadata(par2, par3, par4);
+
+ if (var6 < 7) {
+ float var7 = this.getGrowthRate(par1World, par2, par3, par4);
+
+ if (par5Random.nextInt((int) (25.0F / var7) + 1) == 0) {
+ ++var6;
+ par1World.setBlockMetadata(par2, par3, par4, var6, 2);
+ }
+ }
+ }
+ }
+
+ /**
+ * Apply bonemeal to the crops.
+ */
+ public void fertilize(World par1World, int par2, int par3, int par4) {
+ int var5 = par1World.getBlockMetadata(par2, par3, par4)
+ + MathHelper.getRandomIntegerInRange(par1World.rand, 2, 5);
+
+ if (var5 > 7) {
+ var5 = 7;
+ }
+
+ par1World.setBlockMetadata(par2, par3, par4, var5, 2);
+ }
+
+ /**
+ * Gets the growth rate for the crop. Setup to encourage rows by halving growth
+ * rate if there is diagonals, crops on different sides that aren't opposing,
+ * and by adding growth for every crop next to this one (and for crop below this
+ * one). Args: x, y, z
+ */
+ private float getGrowthRate(World par1World, int par2, int par3, int par4) {
+ float var5 = 1.0F;
+ int var6 = par1World.getBlockId(par2, par3, par4 - 1);
+ int var7 = par1World.getBlockId(par2, par3, par4 + 1);
+ int var8 = par1World.getBlockId(par2 - 1, par3, par4);
+ int var9 = par1World.getBlockId(par2 + 1, par3, par4);
+ int var10 = par1World.getBlockId(par2 - 1, par3, par4 - 1);
+ int var11 = par1World.getBlockId(par2 + 1, par3, par4 - 1);
+ int var12 = par1World.getBlockId(par2 + 1, par3, par4 + 1);
+ int var13 = par1World.getBlockId(par2 - 1, par3, par4 + 1);
+ boolean var14 = var8 == this.blockID || var9 == this.blockID;
+ boolean var15 = var6 == this.blockID || var7 == this.blockID;
+ boolean var16 = var10 == this.blockID || var11 == this.blockID || var12 == this.blockID
+ || var13 == this.blockID;
+
+ for (int var17 = par2 - 1; var17 <= par2 + 1; ++var17) {
+ for (int var18 = par4 - 1; var18 <= par4 + 1; ++var18) {
+ int var19 = par1World.getBlockId(var17, par3 - 1, var18);
+ float var20 = 0.0F;
+
+ if (var19 == Block.tilledField.blockID) {
+ var20 = 1.0F;
+
+ if (par1World.getBlockMetadata(var17, par3 - 1, var18) > 0) {
+ var20 = 3.0F;
+ }
+ }
+
+ if (var17 != par2 || var18 != par4) {
+ var20 /= 4.0F;
+ }
+
+ var5 += var20;
+ }
+ }
+
+ if (var16 || var14 && var15) {
+ var5 /= 2.0F;
+ }
+
+ return var5;
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 6;
+ }
+
+ /**
+ * Generate a seed ItemStack for this crop.
+ */
+ protected int getSeedItem() {
+ return Item.seeds.itemID;
+ }
+
+ /**
+ * Generate a crop produce ItemStack for this crop.
+ */
+ protected int getCropItem() {
+ return Item.wheat.itemID;
+ }
+
+ /**
+ * Drops the block items with a specified chance of dropping the specified items
+ */
+ public void dropBlockAsItemWithChance(World par1World, int par2, int par3, int par4, int par5, float par6,
+ int par7) {
+ super.dropBlockAsItemWithChance(par1World, par2, par3, par4, par5, par6, 0);
+
+ if (!par1World.isRemote) {
+ if (par5 >= 7) {
+ int var8 = 3 + par7;
+
+ for (int var9 = 0; var9 < var8; ++var9) {
+ if (par1World.rand.nextInt(15) <= par5) {
+ this.dropBlockAsItem_do(par1World, par2, par3, par4, new ItemStack(this.getSeedItem(), 1, 0));
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return par1 == 7 ? this.getCropItem() : this.getSeedItem();
+ }
+
+ /**
+ * Returns the quantity of items to drop on block destruction.
+ */
+ public int quantityDropped(EaglercraftRandom par1Random) {
+ return 1;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockDaylightDetector.java b/sp-server/src/main/java/net/minecraft/src/BlockDaylightDetector.java
new file mode 100644
index 0000000..9ee56d9
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockDaylightDetector.java
@@ -0,0 +1,112 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockDaylightDetector extends BlockContainer {
+ private Icon[] iconArray = new Icon[2];
+
+ public BlockDaylightDetector(int par1) {
+ super(par1, Material.wood);
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.375F, 1.0F);
+ this.setCreativeTab(CreativeTabs.tabRedstone);
+ }
+
+ /**
+ * Updates the blocks bounds based on its current state. Args: world, x, y, z
+ */
+ public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.375F, 1.0F);
+ }
+
+ /**
+ * Returns true if the block is emitting indirect/weak redstone power on the
+ * specified side. If isBlockNormalCube returns true, standard redstone
+ * propagation rules will apply instead and this will not be called. Args:
+ * World, X, Y, Z, side. Note that the side is reversed - eg it is 1 (up) when
+ * checking the bottom of the block.
+ */
+ public int isProvidingWeakPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) {
+ return par1IBlockAccess.getBlockMetadata(par2, par3, par4);
+ }
+
+ /**
+ * Ticks the block if it's been scheduled
+ */
+ public void updateTick(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ }
+
+ /**
+ * Called whenever the block is added into the world. Args: world, x, y, z
+ */
+ public void onBlockAdded(World par1World, int par2, int par3, int par4) {
+ }
+
+ public void updateLightLevel(World par1World, int par2, int par3, int par4) {
+ if (!par1World.provider.hasNoSky) {
+ int var5 = par1World.getBlockMetadata(par2, par3, par4);
+ int var6 = par1World.getSavedLightValue(EnumSkyBlock.Sky, par2, par3, par4) - par1World.skylightSubtracted;
+ float var7 = par1World.getCelestialAngleRadians(1.0F);
+
+ if (var7 < (float) Math.PI) {
+ var7 += (0.0F - var7) * 0.2F;
+ } else {
+ var7 += (((float) Math.PI * 2F) - var7) * 0.2F;
+ }
+
+ var6 = Math.round((float) var6 * MathHelper.cos(var7));
+
+ if (var6 < 0) {
+ var6 = 0;
+ }
+
+ if (var6 > 15) {
+ var6 = 15;
+ }
+
+ if (var5 != var6) {
+ par1World.setBlockMetadata(par2, par3, par4, var6, 3);
+ }
+ }
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * Can this block provide power. Only wire currently seems to have this change
+ * based on its state.
+ */
+ public boolean canProvidePower() {
+ return true;
+ }
+
+ /**
+ * Returns a new instance of a block's tile entity class. Called on placing the
+ * block.
+ */
+ public TileEntity createNewTileEntity(World par1World) {
+ return new TileEntityDaylightDetector();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockDeadBush.java b/sp-server/src/main/java/net/minecraft/src/BlockDeadBush.java
new file mode 100644
index 0000000..fb9a280
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockDeadBush.java
@@ -0,0 +1,40 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockDeadBush extends BlockFlower {
+ protected BlockDeadBush(int par1) {
+ super(par1, Material.vine);
+ float var2 = 0.4F;
+ this.setBlockBounds(0.5F - var2, 0.0F, 0.5F - var2, 0.5F + var2, 0.8F, 0.5F + var2);
+ }
+
+ /**
+ * Gets passed in the blockID of the block below and supposed to return true if
+ * its allowed to grow on the type of blockID passed in. Args: blockID
+ */
+ protected boolean canThisPlantGrowOnThisBlockID(int par1) {
+ return par1 == Block.sand.blockID;
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return -1;
+ }
+
+ /**
+ * Called when the player destroys a block with an item that can harvest it. (i,
+ * j, k) are the coordinates of the block and l is the block's subtype/damage.
+ */
+ public void harvestBlock(World par1World, EntityPlayer par2EntityPlayer, int par3, int par4, int par5, int par6) {
+ if (!par1World.isRemote && par2EntityPlayer.getCurrentEquippedItem() != null
+ && par2EntityPlayer.getCurrentEquippedItem().itemID == Item.shears.itemID) {
+ par2EntityPlayer.addStat(StatList.mineBlockStatArray[this.blockID], 1);
+ this.dropBlockAsItem_do(par1World, par3, par4, par5, new ItemStack(Block.deadBush, 1, par6));
+ } else {
+ super.harvestBlock(par1World, par2EntityPlayer, par3, par4, par5, par6);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockDetectorRail.java b/sp-server/src/main/java/net/minecraft/src/BlockDetectorRail.java
new file mode 100644
index 0000000..76999e2
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockDetectorRail.java
@@ -0,0 +1,152 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockDetectorRail extends BlockRailBase {
+ public BlockDetectorRail(int par1) {
+ super(par1, true);
+ this.setTickRandomly(true);
+ }
+
+ /**
+ * How many world ticks before ticking
+ */
+ public int tickRate(World par1World) {
+ return 20;
+ }
+
+ /**
+ * Can this block provide power. Only wire currently seems to have this change
+ * based on its state.
+ */
+ public boolean canProvidePower() {
+ return true;
+ }
+
+ /**
+ * Triggered whenever an entity collides with this block (enters into the
+ * block). Args: world, x, y, z, entity
+ */
+ public void onEntityCollidedWithBlock(World par1World, int par2, int par3, int par4, Entity par5Entity) {
+ if (!par1World.isRemote) {
+ int var6 = par1World.getBlockMetadata(par2, par3, par4);
+
+ if ((var6 & 8) == 0) {
+ this.setStateIfMinecartInteractsWithRail(par1World, par2, par3, par4, var6);
+ }
+ }
+ }
+
+ /**
+ * Ticks the block if it's been scheduled
+ */
+ public void updateTick(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ if (!par1World.isRemote) {
+ int var6 = par1World.getBlockMetadata(par2, par3, par4);
+
+ if ((var6 & 8) != 0) {
+ this.setStateIfMinecartInteractsWithRail(par1World, par2, par3, par4, var6);
+ }
+ }
+ }
+
+ /**
+ * Returns true if the block is emitting indirect/weak redstone power on the
+ * specified side. If isBlockNormalCube returns true, standard redstone
+ * propagation rules will apply instead and this will not be called. Args:
+ * World, X, Y, Z, side. Note that the side is reversed - eg it is 1 (up) when
+ * checking the bottom of the block.
+ */
+ public int isProvidingWeakPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) {
+ return (par1IBlockAccess.getBlockMetadata(par2, par3, par4) & 8) != 0 ? 15 : 0;
+ }
+
+ /**
+ * Returns true if the block is emitting direct/strong redstone power on the
+ * specified side. Args: World, X, Y, Z, side. Note that the side is reversed -
+ * eg it is 1 (up) when checking the bottom of the block.
+ */
+ public int isProvidingStrongPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) {
+ return (par1IBlockAccess.getBlockMetadata(par2, par3, par4) & 8) == 0 ? 0 : (par5 == 1 ? 15 : 0);
+ }
+
+ /**
+ * Update the detector rail power state if a minecart enter, stays or leave the
+ * block.
+ */
+ private void setStateIfMinecartInteractsWithRail(World par1World, int par2, int par3, int par4, int par5) {
+ boolean var6 = (par5 & 8) != 0;
+ boolean var7 = false;
+ float var8 = 0.125F;
+ List var9 = par1World.getEntitiesWithinAABB(EntityMinecart.class,
+ AxisAlignedBB.getAABBPool().getAABB((double) ((float) par2 + var8), (double) par3,
+ (double) ((float) par4 + var8), (double) ((float) (par2 + 1) - var8),
+ (double) ((float) (par3 + 1) - var8), (double) ((float) (par4 + 1) - var8)));
+
+ if (!var9.isEmpty()) {
+ var7 = true;
+ }
+
+ if (var7 && !var6) {
+ par1World.setBlockMetadata(par2, par3, par4, par5 | 8, 3);
+ par1World.notifyBlocksOfNeighborChange(par2, par3, par4, this.blockID);
+ par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID);
+ par1World.markBlockRangeForRenderUpdate(par2, par3, par4, par2, par3, par4);
+ }
+
+ if (!var7 && var6) {
+ par1World.setBlockMetadata(par2, par3, par4, par5 & 7, 3);
+ par1World.notifyBlocksOfNeighborChange(par2, par3, par4, this.blockID);
+ par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID);
+ par1World.markBlockRangeForRenderUpdate(par2, par3, par4, par2, par3, par4);
+ }
+
+ if (var7) {
+ par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, this.tickRate(par1World));
+ }
+
+ par1World.func_96440_m(par2, par3, par4, this.blockID);
+ }
+
+ /**
+ * Called whenever the block is added into the world. Args: world, x, y, z
+ */
+ public void onBlockAdded(World par1World, int par2, int par3, int par4) {
+ super.onBlockAdded(par1World, par2, par3, par4);
+ this.setStateIfMinecartInteractsWithRail(par1World, par2, par3, par4,
+ par1World.getBlockMetadata(par2, par3, par4));
+ }
+
+ /**
+ * If this returns true, then comparators facing away from this block will use
+ * the value from getComparatorInputOverride instead of the actual redstone
+ * signal strength.
+ */
+ public boolean hasComparatorInputOverride() {
+ return true;
+ }
+
+ /**
+ * If hasComparatorInputOverride returns true, the return value from this is
+ * used instead of the redstone signal strength when this block inputs to a
+ * comparator.
+ */
+ public int getComparatorInputOverride(World par1World, int par2, int par3, int par4, int par5) {
+ if ((par1World.getBlockMetadata(par2, par3, par4) & 8) > 0) {
+ float var6 = 0.125F;
+ List var7 = par1World.selectEntitiesWithinAABB(EntityMinecart.class,
+ AxisAlignedBB.getAABBPool().getAABB((double) ((float) par2 + var6), (double) par3,
+ (double) ((float) par4 + var6), (double) ((float) (par2 + 1) - var6),
+ (double) ((float) (par3 + 1) - var6), (double) ((float) (par4 + 1) - var6)),
+ IEntitySelector.selectInventories);
+
+ if (var7.size() > 0) {
+ return Container.calcRedstoneFromInventory((IInventory) var7.get(0));
+ }
+ }
+
+ return 0;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockDirectional.java b/sp-server/src/main/java/net/minecraft/src/BlockDirectional.java
new file mode 100644
index 0000000..947c9b5
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockDirectional.java
@@ -0,0 +1,14 @@
+package net.minecraft.src;
+
+public abstract class BlockDirectional extends Block {
+ protected BlockDirectional(int par1, Material par2Material) {
+ super(par1, par2Material);
+ }
+
+ /**
+ * Returns the orentation value from the specified metadata
+ */
+ public static int getDirection(int par0) {
+ return par0 & 3;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockDirt.java b/sp-server/src/main/java/net/minecraft/src/BlockDirt.java
new file mode 100644
index 0000000..59e228d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockDirt.java
@@ -0,0 +1,8 @@
+package net.minecraft.src;
+
+public class BlockDirt extends Block {
+ protected BlockDirt(int par1) {
+ super(par1, Material.ground);
+ this.setCreativeTab(CreativeTabs.tabBlock);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockDispenser.java b/sp-server/src/main/java/net/minecraft/src/BlockDispenser.java
new file mode 100644
index 0000000..c0bdd2a
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockDispenser.java
@@ -0,0 +1,234 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockDispenser extends BlockContainer {
+ /** Registry for all dispense behaviors. */
+ public static final IRegistry dispenseBehaviorRegistry = new RegistryDefaulted(new BehaviorDefaultDispenseItem());
+ protected EaglercraftRandom random = new EaglercraftRandom();
+
+ protected BlockDispenser(int par1) {
+ super(par1, Material.rock);
+ this.setCreativeTab(CreativeTabs.tabRedstone);
+ }
+
+ /**
+ * How many world ticks before ticking
+ */
+ public int tickRate(World par1World) {
+ return 4;
+ }
+
+ /**
+ * Called whenever the block is added into the world. Args: world, x, y, z
+ */
+ public void onBlockAdded(World par1World, int par2, int par3, int par4) {
+ super.onBlockAdded(par1World, par2, par3, par4);
+ this.setDispenserDefaultDirection(par1World, par2, par3, par4);
+ }
+
+ /**
+ * sets Dispenser block direction so that the front faces an non-opaque block;
+ * chooses west to be direction if all surrounding blocks are opaque.
+ */
+ private void setDispenserDefaultDirection(World par1World, int par2, int par3, int par4) {
+ if (!par1World.isRemote) {
+ int var5 = par1World.getBlockId(par2, par3, par4 - 1);
+ int var6 = par1World.getBlockId(par2, par3, par4 + 1);
+ int var7 = par1World.getBlockId(par2 - 1, par3, par4);
+ int var8 = par1World.getBlockId(par2 + 1, par3, par4);
+ byte var9 = 3;
+
+ if (Block.opaqueCubeLookup[var5] && !Block.opaqueCubeLookup[var6]) {
+ var9 = 3;
+ }
+
+ if (Block.opaqueCubeLookup[var6] && !Block.opaqueCubeLookup[var5]) {
+ var9 = 2;
+ }
+
+ if (Block.opaqueCubeLookup[var7] && !Block.opaqueCubeLookup[var8]) {
+ var9 = 5;
+ }
+
+ if (Block.opaqueCubeLookup[var8] && !Block.opaqueCubeLookup[var7]) {
+ var9 = 4;
+ }
+
+ par1World.setBlockMetadata(par2, par3, par4, var9, 2);
+ }
+ }
+
+ /**
+ * Called upon block activation (right click on the block.)
+ */
+ public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer,
+ int par6, float par7, float par8, float par9) {
+ if (par1World.isRemote) {
+ return true;
+ } else {
+ TileEntityDispenser var10 = (TileEntityDispenser) par1World.getBlockTileEntity(par2, par3, par4);
+
+ if (var10 != null) {
+ par5EntityPlayer.displayGUIDispenser(var10);
+ }
+
+ return true;
+ }
+ }
+
+ protected void dispense(World par1World, int par2, int par3, int par4) {
+ BlockSourceImpl var5 = new BlockSourceImpl(par1World, par2, par3, par4);
+ TileEntityDispenser var6 = (TileEntityDispenser) var5.getBlockTileEntity();
+
+ if (var6 != null) {
+ int var7 = var6.getRandomStackFromInventory();
+
+ if (var7 < 0) {
+ par1World.playAuxSFX(1001, par2, par3, par4, 0);
+ } else {
+ ItemStack var8 = var6.getStackInSlot(var7);
+ IBehaviorDispenseItem var9 = this.getBehaviorForItemStack(var8);
+
+ if (var9 != IBehaviorDispenseItem.itemDispenseBehaviorProvider) {
+ ItemStack var10 = var9.dispense(var5, var8);
+ var6.setInventorySlotContents(var7, var10.stackSize == 0 ? null : var10);
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the behavior for the given ItemStack.
+ */
+ protected IBehaviorDispenseItem getBehaviorForItemStack(ItemStack par1ItemStack) {
+ return (IBehaviorDispenseItem) dispenseBehaviorRegistry.func_82594_a(par1ItemStack.getItem());
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ boolean var6 = par1World.isBlockIndirectlyGettingPowered(par2, par3, par4)
+ || par1World.isBlockIndirectlyGettingPowered(par2, par3 + 1, par4);
+ int var7 = par1World.getBlockMetadata(par2, par3, par4);
+ boolean var8 = (var7 & 8) != 0;
+
+ if (var6 && !var8) {
+ par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, this.tickRate(par1World));
+ par1World.setBlockMetadata(par2, par3, par4, var7 | 8, 4);
+ } else if (!var6 && var8) {
+ par1World.setBlockMetadata(par2, par3, par4, var7 & -9, 4);
+ }
+ }
+
+ /**
+ * Ticks the block if it's been scheduled
+ */
+ public void updateTick(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ if (!par1World.isRemote) {
+ this.dispense(par1World, par2, par3, par4);
+ }
+ }
+
+ /**
+ * Returns a new instance of a block's tile entity class. Called on placing the
+ * block.
+ */
+ public TileEntity createNewTileEntity(World par1World) {
+ return new TileEntityDispenser();
+ }
+
+ /**
+ * Called when the block is placed in the world.
+ */
+ public void onBlockPlacedBy(World par1World, int par2, int par3, int par4, EntityLiving par5EntityLiving,
+ ItemStack par6ItemStack) {
+ int var7 = BlockPistonBase.determineOrientation(par1World, par2, par3, par4, par5EntityLiving);
+ par1World.setBlockMetadata(par2, par3, par4, var7, 2);
+
+ if (par6ItemStack.hasDisplayName()) {
+ ((TileEntityDispenser) par1World.getBlockTileEntity(par2, par3, par4))
+ .func_94049_a(par6ItemStack.getDisplayName());
+ }
+ }
+
+ /**
+ * ejects contained items into the world, and notifies neighbours of an update,
+ * as appropriate
+ */
+ public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) {
+ TileEntityDispenser var7 = (TileEntityDispenser) par1World.getBlockTileEntity(par2, par3, par4);
+
+ if (var7 != null) {
+ for (int var8 = 0; var8 < var7.getSizeInventory(); ++var8) {
+ ItemStack var9 = var7.getStackInSlot(var8);
+
+ if (var9 != null) {
+ float var10 = this.random.nextFloat() * 0.8F + 0.1F;
+ float var11 = this.random.nextFloat() * 0.8F + 0.1F;
+ float var12 = this.random.nextFloat() * 0.8F + 0.1F;
+
+ while (var9.stackSize > 0) {
+ int var13 = this.random.nextInt(21) + 10;
+
+ if (var13 > var9.stackSize) {
+ var13 = var9.stackSize;
+ }
+
+ var9.stackSize -= var13;
+ EntityItem var14 = new EntityItem(par1World, (double) ((float) par2 + var10),
+ (double) ((float) par3 + var11), (double) ((float) par4 + var12),
+ new ItemStack(var9.itemID, var13, var9.getItemDamage()));
+
+ if (var9.hasTagCompound()) {
+ var14.getEntityItem().setTagCompound((NBTTagCompound) var9.getTagCompound().copy());
+ }
+
+ float var15 = 0.05F;
+ var14.motionX = (double) ((float) this.random.nextGaussian() * var15);
+ var14.motionY = (double) ((float) this.random.nextGaussian() * var15 + 0.2F);
+ var14.motionZ = (double) ((float) this.random.nextGaussian() * var15);
+ par1World.spawnEntityInWorld(var14);
+ }
+ }
+ }
+
+ par1World.func_96440_m(par2, par3, par4, par5);
+ }
+
+ super.breakBlock(par1World, par2, par3, par4, par5, par6);
+ }
+
+ public static IPosition getIPositionFromBlockSource(IBlockSource par0IBlockSource) {
+ EnumFacing var1 = getFacing(par0IBlockSource.getBlockMetadata());
+ double var2 = par0IBlockSource.getX() + 0.7D * (double) var1.getFrontOffsetX();
+ double var4 = par0IBlockSource.getY() + 0.7D * (double) var1.getFrontOffsetY();
+ double var6 = par0IBlockSource.getZ() + 0.7D * (double) var1.getFrontOffsetZ();
+ return new PositionImpl(var2, var4, var6);
+ }
+
+ public static EnumFacing getFacing(int par0) {
+ return EnumFacing.getFront(par0 & 7);
+ }
+
+ /**
+ * If this returns true, then comparators facing away from this block will use
+ * the value from getComparatorInputOverride instead of the actual redstone
+ * signal strength.
+ */
+ public boolean hasComparatorInputOverride() {
+ return true;
+ }
+
+ /**
+ * If hasComparatorInputOverride returns true, the return value from this is
+ * used instead of the redstone signal strength when this block inputs to a
+ * comparator.
+ */
+ public int getComparatorInputOverride(World par1World, int par2, int par3, int par4, int par5) {
+ return Container.calcRedstoneFromInventory((IInventory) par1World.getBlockTileEntity(par2, par3, par4));
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockDoor.java b/sp-server/src/main/java/net/minecraft/src/BlockDoor.java
new file mode 100644
index 0000000..967698d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockDoor.java
@@ -0,0 +1,303 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockDoor extends Block {
+ private static final String[] doorIconNames = new String[] { "doorWood_lower", "doorWood_upper", "doorIron_lower",
+ "doorIron_upper" };
+
+ /** Used for pointing at icon names. */
+ private final int doorTypeForIcon;
+
+ protected BlockDoor(int par1, Material par2Material) {
+ super(par1, par2Material);
+
+ if (par2Material == Material.iron) {
+ this.doorTypeForIcon = 2;
+ } else {
+ this.doorTypeForIcon = 0;
+ }
+
+ float var3 = 0.5F;
+ float var4 = 1.0F;
+ this.setBlockBounds(0.5F - var3, 0.0F, 0.5F - var3, 0.5F + var3, var4, 0.5F + var3);
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ public boolean getBlocksMovement(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ int var5 = this.getFullMetadata(par1IBlockAccess, par2, par3, par4);
+ return (var5 & 4) != 0;
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 7;
+ }
+
+ /**
+ * Returns a bounding box from the pool of bounding boxes (this means this box
+ * can change after the pool has been cleared to be reused)
+ */
+ public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) {
+ this.setBlockBoundsBasedOnState(par1World, par2, par3, par4);
+ return super.getCollisionBoundingBoxFromPool(par1World, par2, par3, par4);
+ }
+
+ /**
+ * Updates the blocks bounds based on its current state. Args: world, x, y, z
+ */
+ public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ this.setDoorRotation(this.getFullMetadata(par1IBlockAccess, par2, par3, par4));
+ }
+
+ /**
+ * Returns 0, 1, 2 or 3 depending on where the hinge is.
+ */
+ public int getDoorOrientation(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ return this.getFullMetadata(par1IBlockAccess, par2, par3, par4) & 3;
+ }
+
+ public boolean isDoorOpen(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ return (this.getFullMetadata(par1IBlockAccess, par2, par3, par4) & 4) != 0;
+ }
+
+ private void setDoorRotation(int par1) {
+ float var2 = 0.1875F;
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 2.0F, 1.0F);
+ int var3 = par1 & 3;
+ boolean var4 = (par1 & 4) != 0;
+ boolean var5 = (par1 & 16) != 0;
+
+ if (var3 == 0) {
+ if (var4) {
+ if (!var5) {
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, var2);
+ } else {
+ this.setBlockBounds(0.0F, 0.0F, 1.0F - var2, 1.0F, 1.0F, 1.0F);
+ }
+ } else {
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, var2, 1.0F, 1.0F);
+ }
+ } else if (var3 == 1) {
+ if (var4) {
+ if (!var5) {
+ this.setBlockBounds(1.0F - var2, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
+ } else {
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, var2, 1.0F, 1.0F);
+ }
+ } else {
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, var2);
+ }
+ } else if (var3 == 2) {
+ if (var4) {
+ if (!var5) {
+ this.setBlockBounds(0.0F, 0.0F, 1.0F - var2, 1.0F, 1.0F, 1.0F);
+ } else {
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, var2);
+ }
+ } else {
+ this.setBlockBounds(1.0F - var2, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
+ }
+ } else if (var3 == 3) {
+ if (var4) {
+ if (!var5) {
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, var2, 1.0F, 1.0F);
+ } else {
+ this.setBlockBounds(1.0F - var2, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
+ }
+ } else {
+ this.setBlockBounds(0.0F, 0.0F, 1.0F - var2, 1.0F, 1.0F, 1.0F);
+ }
+ }
+ }
+
+ /**
+ * Called when the block is clicked by a player. Args: x, y, z, entityPlayer
+ */
+ public void onBlockClicked(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer) {
+ }
+
+ /**
+ * Called upon block activation (right click on the block.)
+ */
+ public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer,
+ int par6, float par7, float par8, float par9) {
+ if (this.blockMaterial == Material.iron) {
+ return true;
+ } else {
+ int var10 = this.getFullMetadata(par1World, par2, par3, par4);
+ int var11 = var10 & 7;
+ var11 ^= 4;
+
+ if ((var10 & 8) == 0) {
+ par1World.setBlockMetadata(par2, par3, par4, var11, 2);
+ par1World.markBlockRangeForRenderUpdate(par2, par3, par4, par2, par3, par4);
+ } else {
+ par1World.setBlockMetadata(par2, par3 - 1, par4, var11, 2);
+ par1World.markBlockRangeForRenderUpdate(par2, par3 - 1, par4, par2, par3, par4);
+ }
+
+ par1World.playAuxSFXAtEntity(par5EntityPlayer, 1003, par2, par3, par4, 0);
+ return true;
+ }
+ }
+
+ /**
+ * A function to open a door.
+ */
+ public void onPoweredBlockChange(World par1World, int par2, int par3, int par4, boolean par5) {
+ int var6 = this.getFullMetadata(par1World, par2, par3, par4);
+ boolean var7 = (var6 & 4) != 0;
+
+ if (var7 != par5) {
+ int var8 = var6 & 7;
+ var8 ^= 4;
+
+ if ((var6 & 8) == 0) {
+ par1World.setBlockMetadata(par2, par3, par4, var8, 2);
+ par1World.markBlockRangeForRenderUpdate(par2, par3, par4, par2, par3, par4);
+ } else {
+ par1World.setBlockMetadata(par2, par3 - 1, par4, var8, 2);
+ par1World.markBlockRangeForRenderUpdate(par2, par3 - 1, par4, par2, par3, par4);
+ }
+
+ par1World.playAuxSFXAtEntity((EntityPlayer) null, 1003, par2, par3, par4, 0);
+ }
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ int var6 = par1World.getBlockMetadata(par2, par3, par4);
+
+ if ((var6 & 8) == 0) {
+ boolean var7 = false;
+
+ if (par1World.getBlockId(par2, par3 + 1, par4) != this.blockID) {
+ par1World.setBlockToAir(par2, par3, par4);
+ var7 = true;
+ }
+
+ if (!par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4)) {
+ par1World.setBlockToAir(par2, par3, par4);
+ var7 = true;
+
+ if (par1World.getBlockId(par2, par3 + 1, par4) == this.blockID) {
+ par1World.setBlockToAir(par2, par3 + 1, par4);
+ }
+ }
+
+ if (var7) {
+ if (!par1World.isRemote) {
+ this.dropBlockAsItem(par1World, par2, par3, par4, var6, 0);
+ }
+ } else {
+ boolean var8 = par1World.isBlockIndirectlyGettingPowered(par2, par3, par4)
+ || par1World.isBlockIndirectlyGettingPowered(par2, par3 + 1, par4);
+
+ if ((var8 || par5 > 0 && Block.blocksList[par5].canProvidePower()) && par5 != this.blockID) {
+ this.onPoweredBlockChange(par1World, par2, par3, par4, var8);
+ }
+ }
+ } else {
+ if (par1World.getBlockId(par2, par3 - 1, par4) != this.blockID) {
+ par1World.setBlockToAir(par2, par3, par4);
+ }
+
+ if (par5 > 0 && par5 != this.blockID) {
+ this.onNeighborBlockChange(par1World, par2, par3 - 1, par4, par5);
+ }
+ }
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return (par1 & 8) != 0 ? 0
+ : (this.blockMaterial == Material.iron ? Item.doorIron.itemID : Item.doorWood.itemID);
+ }
+
+ /**
+ * Ray traces through the blocks collision from start vector to end vector
+ * returning a ray trace hit. Args: world, x, y, z, startVec, endVec
+ */
+ public MovingObjectPosition collisionRayTrace(World par1World, int par2, int par3, int par4, Vec3 par5Vec3,
+ Vec3 par6Vec3) {
+ this.setBlockBoundsBasedOnState(par1World, par2, par3, par4);
+ return super.collisionRayTrace(par1World, par2, par3, par4, par5Vec3, par6Vec3);
+ }
+
+ /**
+ * Checks to see if its valid to put this block at the specified coordinates.
+ * Args: world, x, y, z
+ */
+ public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4) {
+ return par3 >= 255 ? false
+ : par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4)
+ && super.canPlaceBlockAt(par1World, par2, par3, par4)
+ && super.canPlaceBlockAt(par1World, par2, par3 + 1, par4);
+ }
+
+ /**
+ * Returns the mobility information of the block, 0 = free, 1 = can't push but
+ * can move over, 2 = total immobility and stop pistons
+ */
+ public int getMobilityFlag() {
+ return 1;
+ }
+
+ /**
+ * Returns the full metadata value created by combining the metadata of both
+ * blocks the door takes up.
+ */
+ public int getFullMetadata(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ int var5 = par1IBlockAccess.getBlockMetadata(par2, par3, par4);
+ boolean var6 = (var5 & 8) != 0;
+ int var7;
+ int var8;
+
+ if (var6) {
+ var7 = par1IBlockAccess.getBlockMetadata(par2, par3 - 1, par4);
+ var8 = var5;
+ } else {
+ var7 = var5;
+ var8 = par1IBlockAccess.getBlockMetadata(par2, par3 + 1, par4);
+ }
+
+ boolean var9 = (var8 & 1) != 0;
+ return var7 & 7 | (var6 ? 8 : 0) | (var9 ? 16 : 0);
+ }
+
+ /**
+ * Called when the block is attempted to be harvested
+ */
+ public void onBlockHarvested(World par1World, int par2, int par3, int par4, int par5,
+ EntityPlayer par6EntityPlayer) {
+ if (par6EntityPlayer.capabilities.isCreativeMode && (par5 & 8) != 0
+ && par1World.getBlockId(par2, par3 - 1, par4) == this.blockID) {
+ par1World.setBlockToAir(par2, par3 - 1, par4);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockDragonEgg.java b/sp-server/src/main/java/net/minecraft/src/BlockDragonEgg.java
new file mode 100644
index 0000000..1deee5b
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockDragonEgg.java
@@ -0,0 +1,147 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockDragonEgg extends Block {
+ public BlockDragonEgg(int par1) {
+ super(par1, Material.dragonEgg);
+ this.setBlockBounds(0.0625F, 0.0F, 0.0625F, 0.9375F, 1.0F, 0.9375F);
+ }
+
+ /**
+ * Called whenever the block is added into the world. Args: world, x, y, z
+ */
+ public void onBlockAdded(World par1World, int par2, int par3, int par4) {
+ par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, this.tickRate(par1World));
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, this.tickRate(par1World));
+ }
+
+ /**
+ * Ticks the block if it's been scheduled
+ */
+ public void updateTick(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ this.fallIfPossible(par1World, par2, par3, par4);
+ }
+
+ /**
+ * Checks if the dragon egg can fall down, and if so, makes it fall.
+ */
+ private void fallIfPossible(World par1World, int par2, int par3, int par4) {
+ if (BlockSand.canFallBelow(par1World, par2, par3 - 1, par4) && par3 >= 0) {
+ byte var5 = 32;
+
+ if (!BlockSand.fallInstantly && par1World.checkChunksExist(par2 - var5, par3 - var5, par4 - var5,
+ par2 + var5, par3 + var5, par4 + var5)) {
+ EntityFallingSand var6 = new EntityFallingSand(par1World, (double) ((float) par2 + 0.5F),
+ (double) ((float) par3 + 0.5F), (double) ((float) par4 + 0.5F), this.blockID);
+ par1World.spawnEntityInWorld(var6);
+ } else {
+ par1World.setBlockToAir(par2, par3, par4);
+
+ while (BlockSand.canFallBelow(par1World, par2, par3 - 1, par4) && par3 > 0) {
+ --par3;
+ }
+
+ if (par3 > 0) {
+ par1World.setBlock(par2, par3, par4, this.blockID, 0, 2);
+ }
+ }
+ }
+ }
+
+ /**
+ * Called upon block activation (right click on the block.)
+ */
+ public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer,
+ int par6, float par7, float par8, float par9) {
+ this.teleportNearby(par1World, par2, par3, par4);
+ return true;
+ }
+
+ /**
+ * Called when the block is clicked by a player. Args: x, y, z, entityPlayer
+ */
+ public void onBlockClicked(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer) {
+ this.teleportNearby(par1World, par2, par3, par4);
+ }
+
+ /**
+ * Teleports the dragon egg somewhere else in a 31x19x31 area centered on the
+ * egg.
+ */
+ private void teleportNearby(World par1World, int par2, int par3, int par4) {
+ if (par1World.getBlockId(par2, par3, par4) == this.blockID) {
+ for (int var5 = 0; var5 < 1000; ++var5) {
+ int var6 = par2 + par1World.rand.nextInt(16) - par1World.rand.nextInt(16);
+ int var7 = par3 + par1World.rand.nextInt(8) - par1World.rand.nextInt(8);
+ int var8 = par4 + par1World.rand.nextInt(16) - par1World.rand.nextInt(16);
+
+ if (par1World.getBlockId(var6, var7, var8) == 0) {
+ if (!par1World.isRemote) {
+ par1World.setBlock(var6, var7, var8, this.blockID, par1World.getBlockMetadata(par2, par3, par4),
+ 2);
+ par1World.setBlockToAir(par2, par3, par4);
+ } else {
+ short var9 = 128;
+
+ for (int var10 = 0; var10 < var9; ++var10) {
+ double var11 = par1World.rand.nextDouble();
+ float var13 = (par1World.rand.nextFloat() - 0.5F) * 0.2F;
+ float var14 = (par1World.rand.nextFloat() - 0.5F) * 0.2F;
+ float var15 = (par1World.rand.nextFloat() - 0.5F) * 0.2F;
+ double var16 = (double) var6 + (double) (par2 - var6) * var11
+ + (par1World.rand.nextDouble() - 0.5D) * 1.0D + 0.5D;
+ double var18 = (double) var7 + (double) (par3 - var7) * var11
+ + par1World.rand.nextDouble() * 1.0D - 0.5D;
+ double var20 = (double) var8 + (double) (par4 - var8) * var11
+ + (par1World.rand.nextDouble() - 0.5D) * 1.0D + 0.5D;
+ par1World.spawnParticle("portal", var16, var18, var20, (double) var13, (double) var14,
+ (double) var15);
+ }
+ }
+
+ return;
+ }
+ }
+ }
+ }
+
+ /**
+ * How many world ticks before ticking
+ */
+ public int tickRate(World par1World) {
+ return 5;
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 27;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockDropper.java b/sp-server/src/main/java/net/minecraft/src/BlockDropper.java
new file mode 100644
index 0000000..0b96a5c
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockDropper.java
@@ -0,0 +1,66 @@
+package net.minecraft.src;
+
+public class BlockDropper extends BlockDispenser {
+ private final IBehaviorDispenseItem dropperDefaultBehaviour = new BehaviorDefaultDispenseItem();
+
+ protected BlockDropper(int par1) {
+ super(par1);
+ }
+
+ /**
+ * Returns the behavior for the given ItemStack.
+ */
+ protected IBehaviorDispenseItem getBehaviorForItemStack(ItemStack par1ItemStack) {
+ return this.dropperDefaultBehaviour;
+ }
+
+ /**
+ * Returns a new instance of a block's tile entity class. Called on placing the
+ * block.
+ */
+ public TileEntity createNewTileEntity(World par1World) {
+ return new TileEntityDropper();
+ }
+
+ protected void dispense(World par1World, int par2, int par3, int par4) {
+ BlockSourceImpl var5 = new BlockSourceImpl(par1World, par2, par3, par4);
+ TileEntityDispenser var6 = (TileEntityDispenser) var5.getBlockTileEntity();
+
+ if (var6 != null) {
+ int var7 = var6.getRandomStackFromInventory();
+
+ if (var7 < 0) {
+ par1World.playAuxSFX(1001, par2, par3, par4, 0);
+ } else {
+ ItemStack var8 = var6.getStackInSlot(var7);
+ int var9 = par1World.getBlockMetadata(par2, par3, par4) & 7;
+ IInventory var10 = TileEntityHopper.getInventoryAtLocation(par1World,
+ (double) (par2 + Facing.offsetsXForSide[var9]), (double) (par3 + Facing.offsetsYForSide[var9]),
+ (double) (par4 + Facing.offsetsZForSide[var9]));
+ ItemStack var11;
+
+ if (var10 != null) {
+ var11 = TileEntityHopper.insertStack(var10, var8.copy().splitStack(1), Facing.oppositeSide[var9]);
+
+ if (var11 == null) {
+ var11 = var8.copy();
+
+ if (--var11.stackSize == 0) {
+ var11 = null;
+ }
+ } else {
+ var11 = var8.copy();
+ }
+ } else {
+ var11 = this.dropperDefaultBehaviour.dispense(var5, var8);
+
+ if (var11 != null && var11.stackSize == 0) {
+ var11 = null;
+ }
+ }
+
+ var6.setInventorySlotContents(var7, var11);
+ }
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockEnchantmentTable.java b/sp-server/src/main/java/net/minecraft/src/BlockEnchantmentTable.java
new file mode 100644
index 0000000..4ac17dd
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockEnchantmentTable.java
@@ -0,0 +1,64 @@
+package net.minecraft.src;
+
+public class BlockEnchantmentTable extends BlockContainer {
+ protected BlockEnchantmentTable(int par1) {
+ super(par1, Material.rock);
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.75F, 1.0F);
+ this.setLightOpacity(0);
+ this.setCreativeTab(CreativeTabs.tabDecorations);
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * Returns a new instance of a block's tile entity class. Called on placing the
+ * block.
+ */
+ public TileEntity createNewTileEntity(World par1World) {
+ return new TileEntityEnchantmentTable();
+ }
+
+ /**
+ * Called upon block activation (right click on the block.)
+ */
+ public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer,
+ int par6, float par7, float par8, float par9) {
+ if (par1World.isRemote) {
+ return true;
+ } else {
+ TileEntityEnchantmentTable var10 = (TileEntityEnchantmentTable) par1World.getBlockTileEntity(par2, par3,
+ par4);
+ par5EntityPlayer.displayGUIEnchantment(par2, par3, par4,
+ var10.func_94135_b() ? var10.func_94133_a() : null);
+ return true;
+ }
+ }
+
+ /**
+ * Called when the block is placed in the world.
+ */
+ public void onBlockPlacedBy(World par1World, int par2, int par3, int par4, EntityLiving par5EntityLiving,
+ ItemStack par6ItemStack) {
+ super.onBlockPlacedBy(par1World, par2, par3, par4, par5EntityLiving, par6ItemStack);
+
+ if (par6ItemStack.hasDisplayName()) {
+ ((TileEntityEnchantmentTable) par1World.getBlockTileEntity(par2, par3, par4))
+ .func_94134_a(par6ItemStack.getDisplayName());
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockEndPortal.java b/sp-server/src/main/java/net/minecraft/src/BlockEndPortal.java
new file mode 100644
index 0000000..dc976a2
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockEndPortal.java
@@ -0,0 +1,95 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockEndPortal extends BlockContainer {
+ /**
+ * true if the enderdragon has been killed - allows end portal blocks to be
+ * created in the end
+ */
+ public static boolean bossDefeated = false;
+
+ protected BlockEndPortal(int par1, Material par2Material) {
+ super(par1, par2Material);
+ this.setLightValue(1.0F);
+ }
+
+ /**
+ * Returns a new instance of a block's tile entity class. Called on placing the
+ * block.
+ */
+ public TileEntity createNewTileEntity(World par1World) {
+ return new TileEntityEndPortal();
+ }
+
+ /**
+ * Updates the blocks bounds based on its current state. Args: world, x, y, z
+ */
+ public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ float var5 = 0.0625F;
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, var5, 1.0F);
+ }
+
+ /**
+ * Adds all intersecting collision boxes to a list. (Be sure to only add boxes
+ * to the list if they intersect the mask.) Parameters: World, X, Y, Z, mask,
+ * list, colliding entity
+ */
+ public void addCollisionBoxesToList(World par1World, int par2, int par3, int par4, AxisAlignedBB par5AxisAlignedBB,
+ List par6List, Entity par7Entity) {
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ /**
+ * Returns the quantity of items to drop on block destruction.
+ */
+ public int quantityDropped(EaglercraftRandom par1Random) {
+ return 0;
+ }
+
+ /**
+ * Triggered whenever an entity collides with this block (enters into the
+ * block). Args: world, x, y, z, entity
+ */
+ public void onEntityCollidedWithBlock(World par1World, int par2, int par3, int par4, Entity par5Entity) {
+ if (par5Entity.ridingEntity == null && par5Entity.riddenByEntity == null && !par1World.isRemote) {
+ par5Entity.travelToTheEnd(1);
+ }
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return -1;
+ }
+
+ /**
+ * Called whenever the block is added into the world. Args: world, x, y, z
+ */
+ public void onBlockAdded(World par1World, int par2, int par3, int par4) {
+ if (!bossDefeated) {
+ if (par1World.provider.dimensionId != 0) {
+ par1World.setBlockToAir(par2, par3, par4);
+ }
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockEndPortalFrame.java b/sp-server/src/main/java/net/minecraft/src/BlockEndPortalFrame.java
new file mode 100644
index 0000000..9b12424
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockEndPortalFrame.java
@@ -0,0 +1,78 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockEndPortalFrame extends Block {
+ public BlockEndPortalFrame(int par1) {
+ super(par1, Material.rock);
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 26;
+ }
+
+ /**
+ * Sets the block's bounds for rendering it as an item
+ */
+ public void setBlockBoundsForItemRender() {
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.8125F, 1.0F);
+ }
+
+ /**
+ * Adds all intersecting collision boxes to a list. (Be sure to only add boxes
+ * to the list if they intersect the mask.) Parameters: World, X, Y, Z, mask,
+ * list, colliding entity
+ */
+ public void addCollisionBoxesToList(World par1World, int par2, int par3, int par4, AxisAlignedBB par5AxisAlignedBB,
+ List par6List, Entity par7Entity) {
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.8125F, 1.0F);
+ super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
+ int var8 = par1World.getBlockMetadata(par2, par3, par4);
+
+ if (isEnderEyeInserted(var8)) {
+ this.setBlockBounds(0.3125F, 0.8125F, 0.3125F, 0.6875F, 1.0F, 0.6875F);
+ super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
+ }
+
+ this.setBlockBoundsForItemRender();
+ }
+
+ /**
+ * checks if an ender eye has been inserted into the frame block. parameters:
+ * metadata
+ */
+ public static boolean isEnderEyeInserted(int par0) {
+ return (par0 & 4) != 0;
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return 0;
+ }
+
+ /**
+ * Called when the block is placed in the world.
+ */
+ public void onBlockPlacedBy(World par1World, int par2, int par3, int par4, EntityLiving par5EntityLiving,
+ ItemStack par6ItemStack) {
+ int var7 = ((MathHelper.floor_double((double) (par5EntityLiving.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3) + 2)
+ % 4;
+ par1World.setBlockMetadata(par2, par3, par4, var7, 2);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockEnderChest.java b/sp-server/src/main/java/net/minecraft/src/BlockEnderChest.java
new file mode 100644
index 0000000..06ed8a4
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockEnderChest.java
@@ -0,0 +1,115 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockEnderChest extends BlockContainer {
+ protected BlockEnderChest(int par1) {
+ super(par1, Material.rock);
+ this.setCreativeTab(CreativeTabs.tabDecorations);
+ this.setBlockBounds(0.0625F, 0.0F, 0.0625F, 0.9375F, 0.875F, 0.9375F);
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 22;
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return Block.obsidian.blockID;
+ }
+
+ /**
+ * Returns the quantity of items to drop on block destruction.
+ */
+ public int quantityDropped(EaglercraftRandom par1Random) {
+ return 8;
+ }
+
+ /**
+ * Return true if a player with Silk Touch can harvest this block directly, and
+ * not its normal drops.
+ */
+ protected boolean canSilkHarvest() {
+ return true;
+ }
+
+ /**
+ * Called when the block is placed in the world.
+ */
+ public void onBlockPlacedBy(World par1World, int par2, int par3, int par4, EntityLiving par5EntityLiving,
+ ItemStack par6ItemStack) {
+ byte var7 = 0;
+ int var8 = MathHelper.floor_double((double) (par5EntityLiving.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3;
+
+ if (var8 == 0) {
+ var7 = 2;
+ }
+
+ if (var8 == 1) {
+ var7 = 5;
+ }
+
+ if (var8 == 2) {
+ var7 = 3;
+ }
+
+ if (var8 == 3) {
+ var7 = 4;
+ }
+
+ par1World.setBlockMetadata(par2, par3, par4, var7, 2);
+ }
+
+ /**
+ * Called upon block activation (right click on the block.)
+ */
+ public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer,
+ int par6, float par7, float par8, float par9) {
+ InventoryEnderChest var10 = par5EntityPlayer.getInventoryEnderChest();
+ TileEntityEnderChest var11 = (TileEntityEnderChest) par1World.getBlockTileEntity(par2, par3, par4);
+
+ if (var10 != null && var11 != null) {
+ if (par1World.isBlockNormalCube(par2, par3 + 1, par4)) {
+ return true;
+ } else if (par1World.isRemote) {
+ return true;
+ } else {
+ var10.setAssociatedChest(var11);
+ par5EntityPlayer.displayGUIChest(var10);
+ return true;
+ }
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * Returns a new instance of a block's tile entity class. Called on placing the
+ * block.
+ */
+ public TileEntity createNewTileEntity(World par1World) {
+ return new TileEntityEnderChest();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockEventData.java b/sp-server/src/main/java/net/minecraft/src/BlockEventData.java
new file mode 100644
index 0000000..0d27391
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockEventData.java
@@ -0,0 +1,81 @@
+package net.minecraft.src;
+
+public class BlockEventData {
+ private int coordX;
+ private int coordY;
+ private int coordZ;
+ private int blockID;
+
+ /** Different for each blockID */
+ private int eventID;
+
+ /** Different for each blockID, eventID */
+ private int eventParameter;
+
+ public BlockEventData(int par1, int par2, int par3, int par4, int par5, int par6) {
+ this.coordX = par1;
+ this.coordY = par2;
+ this.coordZ = par3;
+ this.eventID = par5;
+ this.eventParameter = par6;
+ this.blockID = par4;
+ }
+
+ /**
+ * Get the X coordinate.
+ */
+ public int getX() {
+ return this.coordX;
+ }
+
+ /**
+ * Get the Y coordinate.
+ */
+ public int getY() {
+ return this.coordY;
+ }
+
+ /**
+ * Get the Z coordinate.
+ */
+ public int getZ() {
+ return this.coordZ;
+ }
+
+ /**
+ * Get the Event ID (different for each BlockID)
+ */
+ public int getEventID() {
+ return this.eventID;
+ }
+
+ /**
+ * Get the Event Parameter (different for each BlockID,EventID)
+ */
+ public int getEventParameter() {
+ return this.eventParameter;
+ }
+
+ /**
+ * Gets the BlockID for this BlockEventData
+ */
+ public int getBlockID() {
+ return this.blockID;
+ }
+
+ public boolean equals(Object par1Obj) {
+ if (!(par1Obj instanceof BlockEventData)) {
+ return false;
+ } else {
+ BlockEventData var2 = (BlockEventData) par1Obj;
+ return this.coordX == var2.coordX && this.coordY == var2.coordY && this.coordZ == var2.coordZ
+ && this.eventID == var2.eventID && this.eventParameter == var2.eventParameter
+ && this.blockID == var2.blockID;
+ }
+ }
+
+ public String toString() {
+ return "TE(" + this.coordX + "," + this.coordY + "," + this.coordZ + ")," + this.eventID + ","
+ + this.eventParameter + "," + this.blockID;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockFarmland.java b/sp-server/src/main/java/net/minecraft/src/BlockFarmland.java
new file mode 100644
index 0000000..d21733d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockFarmland.java
@@ -0,0 +1,128 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockFarmland extends Block {
+ protected BlockFarmland(int par1) {
+ super(par1, Material.ground);
+ this.setTickRandomly(true);
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.9375F, 1.0F);
+ this.setLightOpacity(255);
+ }
+
+ /**
+ * Returns a bounding box from the pool of bounding boxes (this means this box
+ * can change after the pool has been cleared to be reused)
+ */
+ public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) {
+ return AxisAlignedBB.getAABBPool().getAABB((double) (par2 + 0), (double) (par3 + 0), (double) (par4 + 0),
+ (double) (par2 + 1), (double) (par3 + 1), (double) (par4 + 1));
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ /**
+ * Ticks the block if it's been scheduled
+ */
+ public void updateTick(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ if (!this.isWaterNearby(par1World, par2, par3, par4) && !par1World.canLightningStrikeAt(par2, par3 + 1, par4)) {
+ int var6 = par1World.getBlockMetadata(par2, par3, par4);
+
+ if (var6 > 0) {
+ par1World.setBlockMetadata(par2, par3, par4, var6 - 1, 2);
+ } else if (!this.isCropsNearby(par1World, par2, par3, par4)) {
+ par1World.setBlock(par2, par3, par4, Block.dirt.blockID);
+ }
+ } else {
+ par1World.setBlockMetadata(par2, par3, par4, 7, 2);
+ }
+ }
+
+ /**
+ * Block's chance to react to an entity falling on it.
+ */
+ public void onFallenUpon(World par1World, int par2, int par3, int par4, Entity par5Entity, float par6) {
+ if (!par1World.isRemote && par1World.rand.nextFloat() < par6 - 0.5F) {
+ if (!(par5Entity instanceof EntityPlayer)
+ && !par1World.getGameRules().getGameRuleBooleanValue("mobGriefing")) {
+ return;
+ }
+
+ par1World.setBlock(par2, par3, par4, Block.dirt.blockID);
+ }
+ }
+
+ /**
+ * returns true if there is at least one cropblock nearby (x-1 to x+1, y+1, z-1
+ * to z+1)
+ */
+ private boolean isCropsNearby(World par1World, int par2, int par3, int par4) {
+ byte var5 = 0;
+
+ for (int var6 = par2 - var5; var6 <= par2 + var5; ++var6) {
+ for (int var7 = par4 - var5; var7 <= par4 + var5; ++var7) {
+ int var8 = par1World.getBlockId(var6, par3 + 1, var7);
+
+ if (var8 == Block.crops.blockID || var8 == Block.melonStem.blockID || var8 == Block.pumpkinStem.blockID
+ || var8 == Block.potato.blockID || var8 == Block.carrot.blockID) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * returns true if there's water nearby (x-4 to x+4, y to y+1, k-4 to k+4)
+ */
+ private boolean isWaterNearby(World par1World, int par2, int par3, int par4) {
+ for (int var5 = par2 - 4; var5 <= par2 + 4; ++var5) {
+ for (int var6 = par3; var6 <= par3 + 1; ++var6) {
+ for (int var7 = par4 - 4; var7 <= par4 + 4; ++var7) {
+ if (par1World.getBlockMaterial(var5, var6, var7) == Material.water) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ super.onNeighborBlockChange(par1World, par2, par3, par4, par5);
+ Material var6 = par1World.getBlockMaterial(par2, par3 + 1, par4);
+
+ if (var6.isSolid()) {
+ par1World.setBlock(par2, par3, par4, Block.dirt.blockID);
+ }
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return Block.dirt.idDropped(0, par2Random, par3);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockFence.java b/sp-server/src/main/java/net/minecraft/src/BlockFence.java
new file mode 100644
index 0000000..e7271b1
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockFence.java
@@ -0,0 +1,149 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+public class BlockFence extends Block {
+ private final String field_94464_a;
+
+ public BlockFence(int par1, String par2Str, Material par3Material) {
+ super(par1, par3Material);
+ this.field_94464_a = par2Str;
+ this.setCreativeTab(CreativeTabs.tabDecorations);
+ }
+
+ /**
+ * Adds all intersecting collision boxes to a list. (Be sure to only add boxes
+ * to the list if they intersect the mask.) Parameters: World, X, Y, Z, mask,
+ * list, colliding entity
+ */
+ public void addCollisionBoxesToList(World par1World, int par2, int par3, int par4, AxisAlignedBB par5AxisAlignedBB,
+ List par6List, Entity par7Entity) {
+ boolean var8 = this.canConnectFenceTo(par1World, par2, par3, par4 - 1);
+ boolean var9 = this.canConnectFenceTo(par1World, par2, par3, par4 + 1);
+ boolean var10 = this.canConnectFenceTo(par1World, par2 - 1, par3, par4);
+ boolean var11 = this.canConnectFenceTo(par1World, par2 + 1, par3, par4);
+ float var12 = 0.375F;
+ float var13 = 0.625F;
+ float var14 = 0.375F;
+ float var15 = 0.625F;
+
+ if (var8) {
+ var14 = 0.0F;
+ }
+
+ if (var9) {
+ var15 = 1.0F;
+ }
+
+ if (var8 || var9) {
+ this.setBlockBounds(var12, 0.0F, var14, var13, 1.5F, var15);
+ super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
+ }
+
+ var14 = 0.375F;
+ var15 = 0.625F;
+
+ if (var10) {
+ var12 = 0.0F;
+ }
+
+ if (var11) {
+ var13 = 1.0F;
+ }
+
+ if (var10 || var11 || !var8 && !var9) {
+ this.setBlockBounds(var12, 0.0F, var14, var13, 1.5F, var15);
+ super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
+ }
+
+ if (var8) {
+ var14 = 0.0F;
+ }
+
+ if (var9) {
+ var15 = 1.0F;
+ }
+
+ this.setBlockBounds(var12, 0.0F, var14, var13, 1.0F, var15);
+ }
+
+ /**
+ * Updates the blocks bounds based on its current state. Args: world, x, y, z
+ */
+ public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ boolean var5 = this.canConnectFenceTo(par1IBlockAccess, par2, par3, par4 - 1);
+ boolean var6 = this.canConnectFenceTo(par1IBlockAccess, par2, par3, par4 + 1);
+ boolean var7 = this.canConnectFenceTo(par1IBlockAccess, par2 - 1, par3, par4);
+ boolean var8 = this.canConnectFenceTo(par1IBlockAccess, par2 + 1, par3, par4);
+ float var9 = 0.375F;
+ float var10 = 0.625F;
+ float var11 = 0.375F;
+ float var12 = 0.625F;
+
+ if (var5) {
+ var11 = 0.0F;
+ }
+
+ if (var6) {
+ var12 = 1.0F;
+ }
+
+ if (var7) {
+ var9 = 0.0F;
+ }
+
+ if (var8) {
+ var10 = 1.0F;
+ }
+
+ this.setBlockBounds(var9, 0.0F, var11, var10, 1.0F, var12);
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ public boolean getBlocksMovement(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ return false;
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 11;
+ }
+
+ /**
+ * Returns true if the specified block can be connected by a fence
+ */
+ public boolean canConnectFenceTo(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ int var5 = par1IBlockAccess.getBlockId(par2, par3, par4);
+
+ if (var5 != this.blockID && var5 != Block.fenceGate.blockID) {
+ Block var6 = Block.blocksList[var5];
+ return var6 != null && var6.blockMaterial.isOpaque() && var6.renderAsNormalBlock()
+ ? var6.blockMaterial != Material.pumpkin
+ : false;
+ } else {
+ return true;
+ }
+ }
+
+ public static boolean isIdAFence(int par0) {
+ return par0 == Block.fence.blockID || par0 == Block.netherFence.blockID;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockFenceGate.java b/sp-server/src/main/java/net/minecraft/src/BlockFenceGate.java
new file mode 100644
index 0000000..cf4b67b
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockFenceGate.java
@@ -0,0 +1,137 @@
+package net.minecraft.src;
+
+public class BlockFenceGate extends BlockDirectional {
+ public BlockFenceGate(int par1) {
+ super(par1, Material.wood);
+ this.setCreativeTab(CreativeTabs.tabRedstone);
+ }
+
+ /**
+ * Checks to see if its valid to put this block at the specified coordinates.
+ * Args: world, x, y, z
+ */
+ public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4) {
+ return !par1World.getBlockMaterial(par2, par3 - 1, par4).isSolid() ? false
+ : super.canPlaceBlockAt(par1World, par2, par3, par4);
+ }
+
+ /**
+ * Returns a bounding box from the pool of bounding boxes (this means this box
+ * can change after the pool has been cleared to be reused)
+ */
+ public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) {
+ int var5 = par1World.getBlockMetadata(par2, par3, par4);
+ return isFenceGateOpen(var5) ? null
+ : (var5 != 2 && var5 != 0
+ ? AxisAlignedBB.getAABBPool().getAABB((double) ((float) par2 + 0.375F), (double) par3,
+ (double) par4, (double) ((float) par2 + 0.625F), (double) ((float) par3 + 1.5F),
+ (double) (par4 + 1))
+ : AxisAlignedBB.getAABBPool().getAABB((double) par2, (double) par3,
+ (double) ((float) par4 + 0.375F), (double) (par2 + 1), (double) ((float) par3 + 1.5F),
+ (double) ((float) par4 + 0.625F)));
+ }
+
+ /**
+ * Updates the blocks bounds based on its current state. Args: world, x, y, z
+ */
+ public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ int var5 = getDirection(par1IBlockAccess.getBlockMetadata(par2, par3, par4));
+
+ if (var5 != 2 && var5 != 0) {
+ this.setBlockBounds(0.375F, 0.0F, 0.0F, 0.625F, 1.0F, 1.0F);
+ } else {
+ this.setBlockBounds(0.0F, 0.0F, 0.375F, 1.0F, 1.0F, 0.625F);
+ }
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ public boolean getBlocksMovement(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ return isFenceGateOpen(par1IBlockAccess.getBlockMetadata(par2, par3, par4));
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 21;
+ }
+
+ /**
+ * Called when the block is placed in the world.
+ */
+ public void onBlockPlacedBy(World par1World, int par2, int par3, int par4, EntityLiving par5EntityLiving,
+ ItemStack par6ItemStack) {
+ int var7 = (MathHelper.floor_double((double) (par5EntityLiving.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3) % 4;
+ par1World.setBlockMetadata(par2, par3, par4, var7, 2);
+ }
+
+ /**
+ * Called upon block activation (right click on the block.)
+ */
+ public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer,
+ int par6, float par7, float par8, float par9) {
+ int var10 = par1World.getBlockMetadata(par2, par3, par4);
+
+ if (isFenceGateOpen(var10)) {
+ par1World.setBlockMetadata(par2, par3, par4, var10 & -5, 2);
+ } else {
+ int var11 = (MathHelper.floor_double((double) (par5EntityPlayer.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3)
+ % 4;
+ int var12 = getDirection(var10);
+
+ if (var12 == (var11 + 2) % 4) {
+ var10 = var11;
+ }
+
+ par1World.setBlockMetadata(par2, par3, par4, var10 | 4, 2);
+ }
+
+ par1World.playAuxSFXAtEntity(par5EntityPlayer, 1003, par2, par3, par4, 0);
+ return true;
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ if (!par1World.isRemote) {
+ int var6 = par1World.getBlockMetadata(par2, par3, par4);
+ boolean var7 = par1World.isBlockIndirectlyGettingPowered(par2, par3, par4);
+
+ if (var7 || par5 > 0 && Block.blocksList[par5].canProvidePower()) {
+ if (var7 && !isFenceGateOpen(var6)) {
+ par1World.setBlockMetadata(par2, par3, par4, var6 | 4, 2);
+ par1World.playAuxSFXAtEntity((EntityPlayer) null, 1003, par2, par3, par4, 0);
+ } else if (!var7 && isFenceGateOpen(var6)) {
+ par1World.setBlockMetadata(par2, par3, par4, var6 & -5, 2);
+ par1World.playAuxSFXAtEntity((EntityPlayer) null, 1003, par2, par3, par4, 0);
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns if the fence gate is open according to its metadata.
+ */
+ public static boolean isFenceGateOpen(int par0) {
+ return (par0 & 4) != 0;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockFire.java b/sp-server/src/main/java/net/minecraft/src/BlockFire.java
new file mode 100644
index 0000000..c6236be
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockFire.java
@@ -0,0 +1,323 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockFire extends Block {
+ /** The chance this block will encourage nearby blocks to catch on fire */
+ private int[] chanceToEncourageFire = new int[256];
+
+ /**
+ * This is an array indexed by block ID the larger the number in the array the
+ * more likely a block type will catch fires
+ */
+ private int[] abilityToCatchFire = new int[256];
+
+ protected BlockFire(int par1) {
+ super(par1, Material.fire);
+ this.setTickRandomly(true);
+ }
+
+ /**
+ * This method is called on a block after all other blocks gets already created.
+ * You can use it to reference and configure something on the block that needs
+ * the others ones.
+ */
+ public void initializeBlock() {
+ this.setBurnRate(Block.planks.blockID, 5, 20);
+ this.setBurnRate(Block.woodDoubleSlab.blockID, 5, 20);
+ this.setBurnRate(Block.woodSingleSlab.blockID, 5, 20);
+ this.setBurnRate(Block.fence.blockID, 5, 20);
+ this.setBurnRate(Block.stairsWoodOak.blockID, 5, 20);
+ this.setBurnRate(Block.stairsWoodBirch.blockID, 5, 20);
+ this.setBurnRate(Block.stairsWoodSpruce.blockID, 5, 20);
+ this.setBurnRate(Block.stairsWoodJungle.blockID, 5, 20);
+ this.setBurnRate(Block.wood.blockID, 5, 5);
+ this.setBurnRate(Block.leaves.blockID, 30, 60);
+ this.setBurnRate(Block.bookShelf.blockID, 30, 20);
+ this.setBurnRate(Block.tnt.blockID, 15, 100);
+ this.setBurnRate(Block.tallGrass.blockID, 60, 100);
+ this.setBurnRate(Block.cloth.blockID, 30, 60);
+ this.setBurnRate(Block.vine.blockID, 15, 100);
+ }
+
+ /**
+ * Sets the burn rate for a block. The larger abilityToCatchFire the more easily
+ * it will catch. The larger chanceToEncourageFire the faster it will burn and
+ * spread to other blocks. Args: blockID, chanceToEncourageFire,
+ * abilityToCatchFire
+ */
+ private void setBurnRate(int par1, int par2, int par3) {
+ this.chanceToEncourageFire[par1] = par2;
+ this.abilityToCatchFire[par1] = par3;
+ }
+
+ /**
+ * Returns a bounding box from the pool of bounding boxes (this means this box
+ * can change after the pool has been cleared to be reused)
+ */
+ public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) {
+ return null;
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 3;
+ }
+
+ /**
+ * Returns the quantity of items to drop on block destruction.
+ */
+ public int quantityDropped(EaglercraftRandom par1Random) {
+ return 0;
+ }
+
+ /**
+ * How many world ticks before ticking
+ */
+ public int tickRate(World par1World) {
+ return 30;
+ }
+
+ /**
+ * Ticks the block if it's been scheduled
+ */
+ public void updateTick(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ if (par1World.getGameRules().getGameRuleBooleanValue("doFireTick")) {
+ boolean var6 = par1World.getBlockId(par2, par3 - 1, par4) == Block.netherrack.blockID;
+
+ if (par1World.provider instanceof WorldProviderEnd
+ && par1World.getBlockId(par2, par3 - 1, par4) == Block.bedrock.blockID) {
+ var6 = true;
+ }
+
+ if (!this.canPlaceBlockAt(par1World, par2, par3, par4)) {
+ par1World.setBlockToAir(par2, par3, par4);
+ }
+
+ if (!var6 && par1World.isRaining()
+ && (par1World.canLightningStrikeAt(par2, par3, par4)
+ || par1World.canLightningStrikeAt(par2 - 1, par3, par4)
+ || par1World.canLightningStrikeAt(par2 + 1, par3, par4)
+ || par1World.canLightningStrikeAt(par2, par3, par4 - 1)
+ || par1World.canLightningStrikeAt(par2, par3, par4 + 1))) {
+ par1World.setBlockToAir(par2, par3, par4);
+ } else {
+ int var7 = par1World.getBlockMetadata(par2, par3, par4);
+
+ if (var7 < 15) {
+ par1World.setBlockMetadata(par2, par3, par4, var7 + par5Random.nextInt(3) / 2, 4);
+ }
+
+ par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID,
+ this.tickRate(par1World) + par5Random.nextInt(10));
+
+ if (!var6 && !this.canNeighborBurn(par1World, par2, par3, par4)) {
+ if (!par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4) || var7 > 3) {
+ par1World.setBlockToAir(par2, par3, par4);
+ }
+ } else if (!var6 && !this.canBlockCatchFire(par1World, par2, par3 - 1, par4) && var7 == 15
+ && par5Random.nextInt(4) == 0) {
+ par1World.setBlockToAir(par2, par3, par4);
+ } else {
+ boolean var8 = par1World.isBlockHighHumidity(par2, par3, par4);
+ byte var9 = 0;
+
+ if (var8) {
+ var9 = -50;
+ }
+
+ this.tryToCatchBlockOnFire(par1World, par2 + 1, par3, par4, 300 + var9, par5Random, var7);
+ this.tryToCatchBlockOnFire(par1World, par2 - 1, par3, par4, 300 + var9, par5Random, var7);
+ this.tryToCatchBlockOnFire(par1World, par2, par3 - 1, par4, 250 + var9, par5Random, var7);
+ this.tryToCatchBlockOnFire(par1World, par2, par3 + 1, par4, 250 + var9, par5Random, var7);
+ this.tryToCatchBlockOnFire(par1World, par2, par3, par4 - 1, 300 + var9, par5Random, var7);
+ this.tryToCatchBlockOnFire(par1World, par2, par3, par4 + 1, 300 + var9, par5Random, var7);
+
+ for (int var10 = par2 - 1; var10 <= par2 + 1; ++var10) {
+ for (int var11 = par4 - 1; var11 <= par4 + 1; ++var11) {
+ for (int var12 = par3 - 1; var12 <= par3 + 4; ++var12) {
+ if (var10 != par2 || var12 != par3 || var11 != par4) {
+ int var13 = 100;
+
+ if (var12 > par3 + 1) {
+ var13 += (var12 - (par3 + 1)) * 100;
+ }
+
+ int var14 = this.getChanceOfNeighborsEncouragingFire(par1World, var10, var12,
+ var11);
+
+ if (var14 > 0) {
+ int var15 = (var14 + 40 + par1World.difficultySetting * 7) / (var7 + 30);
+
+ if (var8) {
+ var15 /= 2;
+ }
+
+ if (var15 > 0 && par5Random.nextInt(var13) <= var15
+ && (!par1World.isRaining()
+ || !par1World.canLightningStrikeAt(var10, var12, var11))
+ && !par1World.canLightningStrikeAt(var10 - 1, var12, par4)
+ && !par1World.canLightningStrikeAt(var10 + 1, var12, var11)
+ && !par1World.canLightningStrikeAt(var10, var12, var11 - 1)
+ && !par1World.canLightningStrikeAt(var10, var12, var11 + 1)) {
+ int var16 = var7 + par5Random.nextInt(5) / 4;
+
+ if (var16 > 15) {
+ var16 = 15;
+ }
+
+ par1World.setBlock(var10, var12, var11, this.blockID, var16, 3);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public boolean func_82506_l() {
+ return false;
+ }
+
+ private void tryToCatchBlockOnFire(World par1World, int par2, int par3, int par4, int par5, EaglercraftRandom par6Random,
+ int par7) {
+ int var8 = this.abilityToCatchFire[par1World.getBlockId(par2, par3, par4)];
+
+ if (par6Random.nextInt(par5) < var8) {
+ boolean var9 = par1World.getBlockId(par2, par3, par4) == Block.tnt.blockID;
+
+ if (par6Random.nextInt(par7 + 10) < 5 && !par1World.canLightningStrikeAt(par2, par3, par4)) {
+ int var10 = par7 + par6Random.nextInt(5) / 4;
+
+ if (var10 > 15) {
+ var10 = 15;
+ }
+
+ par1World.setBlock(par2, par3, par4, this.blockID, var10, 3);
+ } else {
+ par1World.setBlockToAir(par2, par3, par4);
+ }
+
+ if (var9) {
+ Block.tnt.onBlockDestroyedByPlayer(par1World, par2, par3, par4, 1);
+ }
+ }
+ }
+
+ /**
+ * Returns true if at least one block next to this one can burn.
+ */
+ private boolean canNeighborBurn(World par1World, int par2, int par3, int par4) {
+ return this.canBlockCatchFire(par1World, par2 + 1, par3, par4) ? true
+ : (this.canBlockCatchFire(par1World, par2 - 1, par3, par4) ? true
+ : (this.canBlockCatchFire(par1World, par2, par3 - 1, par4) ? true
+ : (this.canBlockCatchFire(par1World, par2, par3 + 1, par4) ? true
+ : (this.canBlockCatchFire(par1World, par2, par3, par4 - 1) ? true
+ : this.canBlockCatchFire(par1World, par2, par3, par4 + 1)))));
+ }
+
+ /**
+ * Gets the highest chance of a neighbor block encouraging this block to catch
+ * fire
+ */
+ private int getChanceOfNeighborsEncouragingFire(World par1World, int par2, int par3, int par4) {
+ byte var5 = 0;
+
+ if (!par1World.isAirBlock(par2, par3, par4)) {
+ return 0;
+ } else {
+ int var6 = this.getChanceToEncourageFire(par1World, par2 + 1, par3, par4, var5);
+ var6 = this.getChanceToEncourageFire(par1World, par2 - 1, par3, par4, var6);
+ var6 = this.getChanceToEncourageFire(par1World, par2, par3 - 1, par4, var6);
+ var6 = this.getChanceToEncourageFire(par1World, par2, par3 + 1, par4, var6);
+ var6 = this.getChanceToEncourageFire(par1World, par2, par3, par4 - 1, var6);
+ var6 = this.getChanceToEncourageFire(par1World, par2, par3, par4 + 1, var6);
+ return var6;
+ }
+ }
+
+ /**
+ * Returns if this block is collidable (only used by Fire). Args: x, y, z
+ */
+ public boolean isCollidable() {
+ return false;
+ }
+
+ /**
+ * Checks the specified block coordinate to see if it can catch fire. Args:
+ * blockAccess, x, y, z
+ */
+ public boolean canBlockCatchFire(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ return this.chanceToEncourageFire[par1IBlockAccess.getBlockId(par2, par3, par4)] > 0;
+ }
+
+ /**
+ * Retrieves a specified block's chance to encourage their neighbors to burn and
+ * if the number is greater than the current number passed in it will return its
+ * number instead of the passed in one. Args: world, x, y, z,
+ * curChanceToEncourageFire
+ */
+ public int getChanceToEncourageFire(World par1World, int par2, int par3, int par4, int par5) {
+ int var6 = this.chanceToEncourageFire[par1World.getBlockId(par2, par3, par4)];
+ return var6 > par5 ? var6 : par5;
+ }
+
+ /**
+ * Checks to see if its valid to put this block at the specified coordinates.
+ * Args: world, x, y, z
+ */
+ public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4) {
+ return par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4)
+ || this.canNeighborBurn(par1World, par2, par3, par4);
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ if (!par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4)
+ && !this.canNeighborBurn(par1World, par2, par3, par4)) {
+ par1World.setBlockToAir(par2, par3, par4);
+ }
+ }
+
+ /**
+ * Called whenever the block is added into the world. Args: world, x, y, z
+ */
+ public void onBlockAdded(World par1World, int par2, int par3, int par4) {
+ if (par1World.provider.dimensionId > 0 || par1World.getBlockId(par2, par3 - 1, par4) != Block.obsidian.blockID
+ || !Block.portal.tryToCreatePortal(par1World, par2, par3, par4)) {
+ if (!par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4)
+ && !this.canNeighborBurn(par1World, par2, par3, par4)) {
+ par1World.setBlockToAir(par2, par3, par4);
+ } else {
+ par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID,
+ this.tickRate(par1World) + par1World.rand.nextInt(10));
+ }
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockFlower.java b/sp-server/src/main/java/net/minecraft/src/BlockFlower.java
new file mode 100644
index 0000000..ade3c85
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockFlower.java
@@ -0,0 +1,100 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockFlower extends Block {
+ protected BlockFlower(int par1, Material par2Material) {
+ super(par1, par2Material);
+ this.setTickRandomly(true);
+ float var3 = 0.2F;
+ this.setBlockBounds(0.5F - var3, 0.0F, 0.5F - var3, 0.5F + var3, var3 * 3.0F, 0.5F + var3);
+ this.setCreativeTab(CreativeTabs.tabDecorations);
+ }
+
+ protected BlockFlower(int par1) {
+ this(par1, Material.plants);
+ }
+
+ /**
+ * Checks to see if its valid to put this block at the specified coordinates.
+ * Args: world, x, y, z
+ */
+ public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4) {
+ return super.canPlaceBlockAt(par1World, par2, par3, par4)
+ && this.canThisPlantGrowOnThisBlockID(par1World.getBlockId(par2, par3 - 1, par4));
+ }
+
+ /**
+ * Gets passed in the blockID of the block below and supposed to return true if
+ * its allowed to grow on the type of blockID passed in. Args: blockID
+ */
+ protected boolean canThisPlantGrowOnThisBlockID(int par1) {
+ return par1 == Block.grass.blockID || par1 == Block.dirt.blockID || par1 == Block.tilledField.blockID;
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ super.onNeighborBlockChange(par1World, par2, par3, par4, par5);
+ this.checkFlowerChange(par1World, par2, par3, par4);
+ }
+
+ /**
+ * Ticks the block if it's been scheduled
+ */
+ public void updateTick(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ this.checkFlowerChange(par1World, par2, par3, par4);
+ }
+
+ protected final void checkFlowerChange(World par1World, int par2, int par3, int par4) {
+ if (!this.canBlockStay(par1World, par2, par3, par4)) {
+ this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
+ par1World.setBlockToAir(par2, par3, par4);
+ }
+ }
+
+ /**
+ * Can this block stay at this position. Similar to canPlaceBlockAt except gets
+ * checked often with plants.
+ */
+ public boolean canBlockStay(World par1World, int par2, int par3, int par4) {
+ return (par1World.getFullBlockLightValue(par2, par3, par4) >= 8
+ || par1World.canBlockSeeTheSky(par2, par3, par4))
+ && this.canThisPlantGrowOnThisBlockID(par1World.getBlockId(par2, par3 - 1, par4));
+ }
+
+ /**
+ * Returns a bounding box from the pool of bounding boxes (this means this box
+ * can change after the pool has been cleared to be reused)
+ */
+ public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) {
+ return null;
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 1;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockFlowerPot.java b/sp-server/src/main/java/net/minecraft/src/BlockFlowerPot.java
new file mode 100644
index 0000000..b90e9f9
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockFlowerPot.java
@@ -0,0 +1,213 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockFlowerPot extends Block {
+ public BlockFlowerPot(int par1) {
+ super(par1, Material.circuits);
+ this.setBlockBoundsForItemRender();
+ }
+
+ /**
+ * Sets the block's bounds for rendering it as an item
+ */
+ public void setBlockBoundsForItemRender() {
+ float var1 = 0.375F;
+ float var2 = var1 / 2.0F;
+ this.setBlockBounds(0.5F - var2, 0.0F, 0.5F - var2, 0.5F + var2, var1, 0.5F + var2);
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 33;
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ /**
+ * Called upon block activation (right click on the block.)
+ */
+ public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer,
+ int par6, float par7, float par8, float par9) {
+ ItemStack var10 = par5EntityPlayer.inventory.getCurrentItem();
+
+ if (var10 == null) {
+ return false;
+ } else if (par1World.getBlockMetadata(par2, par3, par4) != 0) {
+ return false;
+ } else {
+ int var11 = getMetaForPlant(var10);
+
+ if (var11 > 0) {
+ par1World.setBlockMetadata(par2, par3, par4, var11, 2);
+
+ if (!par5EntityPlayer.capabilities.isCreativeMode && --var10.stackSize <= 0) {
+ par5EntityPlayer.inventory.setInventorySlotContents(par5EntityPlayer.inventory.currentItem,
+ (ItemStack) null);
+ }
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+
+ /**
+ * Get the block's damage value (for use with pick block).
+ */
+ public int getDamageValue(World par1World, int par2, int par3, int par4) {
+ ItemStack var5 = getPlantForMeta(par1World.getBlockMetadata(par2, par3, par4));
+ return var5 == null ? Item.flowerPot.itemID : var5.getItemDamage();
+ }
+
+ /**
+ * Checks to see if its valid to put this block at the specified coordinates.
+ * Args: world, x, y, z
+ */
+ public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4) {
+ return super.canPlaceBlockAt(par1World, par2, par3, par4)
+ && par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4);
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ if (!par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4)) {
+ this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
+ par1World.setBlockToAir(par2, par3, par4);
+ }
+ }
+
+ /**
+ * Drops the block items with a specified chance of dropping the specified items
+ */
+ public void dropBlockAsItemWithChance(World par1World, int par2, int par3, int par4, int par5, float par6,
+ int par7) {
+ super.dropBlockAsItemWithChance(par1World, par2, par3, par4, par5, par6, par7);
+
+ if (par5 > 0) {
+ ItemStack var8 = getPlantForMeta(par5);
+
+ if (var8 != null) {
+ this.dropBlockAsItem_do(par1World, par2, par3, par4, var8);
+ }
+ }
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return Item.flowerPot.itemID;
+ }
+
+ /**
+ * Return the item associated with the specified flower pot metadata value.
+ */
+ public static ItemStack getPlantForMeta(int par0) {
+ switch (par0) {
+ case 1:
+ return new ItemStack(Block.plantRed);
+
+ case 2:
+ return new ItemStack(Block.plantYellow);
+
+ case 3:
+ return new ItemStack(Block.sapling, 1, 0);
+
+ case 4:
+ return new ItemStack(Block.sapling, 1, 1);
+
+ case 5:
+ return new ItemStack(Block.sapling, 1, 2);
+
+ case 6:
+ return new ItemStack(Block.sapling, 1, 3);
+
+ case 7:
+ return new ItemStack(Block.mushroomRed);
+
+ case 8:
+ return new ItemStack(Block.mushroomBrown);
+
+ case 9:
+ return new ItemStack(Block.cactus);
+
+ case 10:
+ return new ItemStack(Block.deadBush);
+
+ case 11:
+ return new ItemStack(Block.tallGrass, 1, 2);
+
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Return the flower pot metadata value associated with the specified item.
+ */
+ public static int getMetaForPlant(ItemStack par0ItemStack) {
+ int var1 = par0ItemStack.getItem().itemID;
+
+ if (var1 == Block.plantRed.blockID) {
+ return 1;
+ } else if (var1 == Block.plantYellow.blockID) {
+ return 2;
+ } else if (var1 == Block.cactus.blockID) {
+ return 9;
+ } else if (var1 == Block.mushroomBrown.blockID) {
+ return 8;
+ } else if (var1 == Block.mushroomRed.blockID) {
+ return 7;
+ } else if (var1 == Block.deadBush.blockID) {
+ return 10;
+ } else {
+ if (var1 == Block.sapling.blockID) {
+ switch (par0ItemStack.getItemDamage()) {
+ case 0:
+ return 3;
+
+ case 1:
+ return 4;
+
+ case 2:
+ return 5;
+
+ case 3:
+ return 6;
+ }
+ }
+
+ if (var1 == Block.tallGrass.blockID) {
+ switch (par0ItemStack.getItemDamage()) {
+ case 2:
+ return 11;
+ }
+ }
+
+ return 0;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockFlowing.java b/sp-server/src/main/java/net/minecraft/src/BlockFlowing.java
new file mode 100644
index 0000000..7fc5688
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockFlowing.java
@@ -0,0 +1,353 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockFlowing extends BlockFluid {
+ /**
+ * Number of horizontally adjacent liquid source blocks. Diagonal doesn't count.
+ * Only source blocks of the same liquid as the block using the field are
+ * counted.
+ */
+ int numAdjacentSources = 0;
+
+ /**
+ * Indicates whether the flow direction is optimal. Each array index corresponds
+ * to one of the four cardinal directions.
+ */
+ boolean[] isOptimalFlowDirection = new boolean[4];
+
+ /**
+ * The estimated cost to flow in a given direction from the current point. Each
+ * array index corresponds to one of the four cardinal directions.
+ */
+ int[] flowCost = new int[4];
+
+ protected BlockFlowing(int par1, Material par2Material) {
+ super(par1, par2Material);
+ }
+
+ /**
+ * Updates the flow for the BlockFlowing object.
+ */
+ private void updateFlow(World par1World, int par2, int par3, int par4) {
+ int var5 = par1World.getBlockMetadata(par2, par3, par4);
+ par1World.setBlock(par2, par3, par4, this.blockID + 1, var5, 2);
+ }
+
+ public boolean getBlocksMovement(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ return this.blockMaterial != Material.lava;
+ }
+
+ /**
+ * Ticks the block if it's been scheduled
+ */
+ public void updateTick(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ int var6 = this.getFlowDecay(par1World, par2, par3, par4);
+ byte var7 = 1;
+
+ if (this.blockMaterial == Material.lava && !par1World.provider.isHellWorld) {
+ var7 = 2;
+ }
+
+ boolean var8 = true;
+ int var10;
+
+ if (var6 > 0) {
+ byte var9 = -100;
+ this.numAdjacentSources = 0;
+ int var12 = this.getSmallestFlowDecay(par1World, par2 - 1, par3, par4, var9);
+ var12 = this.getSmallestFlowDecay(par1World, par2 + 1, par3, par4, var12);
+ var12 = this.getSmallestFlowDecay(par1World, par2, par3, par4 - 1, var12);
+ var12 = this.getSmallestFlowDecay(par1World, par2, par3, par4 + 1, var12);
+ var10 = var12 + var7;
+
+ if (var10 >= 8 || var12 < 0) {
+ var10 = -1;
+ }
+
+ if (this.getFlowDecay(par1World, par2, par3 + 1, par4) >= 0) {
+ int var11 = this.getFlowDecay(par1World, par2, par3 + 1, par4);
+
+ if (var11 >= 8) {
+ var10 = var11;
+ } else {
+ var10 = var11 + 8;
+ }
+ }
+
+ if (this.numAdjacentSources >= 2 && this.blockMaterial == Material.water) {
+ if (par1World.getBlockMaterial(par2, par3 - 1, par4).isSolid()) {
+ var10 = 0;
+ } else if (par1World.getBlockMaterial(par2, par3 - 1, par4) == this.blockMaterial
+ && par1World.getBlockMetadata(par2, par3 - 1, par4) == 0) {
+ var10 = 0;
+ }
+ }
+
+ if (this.blockMaterial == Material.lava && var6 < 8 && var10 < 8 && var10 > var6
+ && par5Random.nextInt(4) != 0) {
+ var10 = var6;
+ var8 = false;
+ }
+
+ if (var10 == var6) {
+ if (var8) {
+ this.updateFlow(par1World, par2, par3, par4);
+ }
+ } else {
+ var6 = var10;
+
+ if (var10 < 0) {
+ par1World.setBlockToAir(par2, par3, par4);
+ } else {
+ par1World.setBlockMetadata(par2, par3, par4, var10, 2);
+ par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, this.tickRate(par1World));
+ par1World.notifyBlocksOfNeighborChange(par2, par3, par4, this.blockID);
+ }
+ }
+ } else {
+ this.updateFlow(par1World, par2, par3, par4);
+ }
+
+ if (this.liquidCanDisplaceBlock(par1World, par2, par3 - 1, par4)) {
+ if (this.blockMaterial == Material.lava
+ && par1World.getBlockMaterial(par2, par3 - 1, par4) == Material.water) {
+ par1World.setBlock(par2, par3 - 1, par4, Block.stone.blockID);
+ this.triggerLavaMixEffects(par1World, par2, par3 - 1, par4);
+ return;
+ }
+
+ if (var6 >= 8) {
+ this.flowIntoBlock(par1World, par2, par3 - 1, par4, var6);
+ } else {
+ this.flowIntoBlock(par1World, par2, par3 - 1, par4, var6 + 8);
+ }
+ } else if (var6 >= 0 && (var6 == 0 || this.blockBlocksFlow(par1World, par2, par3 - 1, par4))) {
+ boolean[] var13 = this.getOptimalFlowDirections(par1World, par2, par3, par4);
+ var10 = var6 + var7;
+
+ if (var6 >= 8) {
+ var10 = 1;
+ }
+
+ if (var10 >= 8) {
+ return;
+ }
+
+ if (var13[0]) {
+ this.flowIntoBlock(par1World, par2 - 1, par3, par4, var10);
+ }
+
+ if (var13[1]) {
+ this.flowIntoBlock(par1World, par2 + 1, par3, par4, var10);
+ }
+
+ if (var13[2]) {
+ this.flowIntoBlock(par1World, par2, par3, par4 - 1, var10);
+ }
+
+ if (var13[3]) {
+ this.flowIntoBlock(par1World, par2, par3, par4 + 1, var10);
+ }
+ }
+ }
+
+ /**
+ * flowIntoBlock(World world, int x, int y, int z, int newFlowDecay) - Flows
+ * into the block at the coordinates and changes the block type to the liquid.
+ */
+ private void flowIntoBlock(World par1World, int par2, int par3, int par4, int par5) {
+ if (this.liquidCanDisplaceBlock(par1World, par2, par3, par4)) {
+ int var6 = par1World.getBlockId(par2, par3, par4);
+
+ if (var6 > 0) {
+ if (this.blockMaterial == Material.lava) {
+ this.triggerLavaMixEffects(par1World, par2, par3, par4);
+ } else {
+ Block.blocksList[var6].dropBlockAsItem(par1World, par2, par3, par4,
+ par1World.getBlockMetadata(par2, par3, par4), 0);
+ }
+ }
+
+ par1World.setBlock(par2, par3, par4, this.blockID, par5, 3);
+ }
+ }
+
+ /**
+ * calculateFlowCost(World world, int x, int y, int z, int accumulatedCost, int
+ * previousDirectionOfFlow) - Used to determine the path of least resistance,
+ * this method returns the lowest possible flow cost for the direction of flow
+ * indicated. Each necessary horizontal flow adds to the flow cost.
+ */
+ private int calculateFlowCost(World par1World, int par2, int par3, int par4, int par5, int par6) {
+ int var7 = 1000;
+
+ for (int var8 = 0; var8 < 4; ++var8) {
+ if ((var8 != 0 || par6 != 1) && (var8 != 1 || par6 != 0) && (var8 != 2 || par6 != 3)
+ && (var8 != 3 || par6 != 2)) {
+ int var9 = par2;
+ int var11 = par4;
+
+ if (var8 == 0) {
+ var9 = par2 - 1;
+ }
+
+ if (var8 == 1) {
+ ++var9;
+ }
+
+ if (var8 == 2) {
+ var11 = par4 - 1;
+ }
+
+ if (var8 == 3) {
+ ++var11;
+ }
+
+ if (!this.blockBlocksFlow(par1World, var9, par3, var11)
+ && (par1World.getBlockMaterial(var9, par3, var11) != this.blockMaterial
+ || par1World.getBlockMetadata(var9, par3, var11) != 0)) {
+ if (!this.blockBlocksFlow(par1World, var9, par3 - 1, var11)) {
+ return par5;
+ }
+
+ if (par5 < 4) {
+ int var12 = this.calculateFlowCost(par1World, var9, par3, var11, par5 + 1, var8);
+
+ if (var12 < var7) {
+ var7 = var12;
+ }
+ }
+ }
+ }
+ }
+
+ return var7;
+ }
+
+ /**
+ * Returns a boolean array indicating which flow directions are optimal based on
+ * each direction's calculated flow cost. Each array index corresponds to one of
+ * the four cardinal directions. A value of true indicates the direction is
+ * optimal.
+ */
+ private boolean[] getOptimalFlowDirections(World par1World, int par2, int par3, int par4) {
+ int var5;
+ int var6;
+
+ for (var5 = 0; var5 < 4; ++var5) {
+ this.flowCost[var5] = 1000;
+ var6 = par2;
+ int var8 = par4;
+
+ if (var5 == 0) {
+ var6 = par2 - 1;
+ }
+
+ if (var5 == 1) {
+ ++var6;
+ }
+
+ if (var5 == 2) {
+ var8 = par4 - 1;
+ }
+
+ if (var5 == 3) {
+ ++var8;
+ }
+
+ if (!this.blockBlocksFlow(par1World, var6, par3, var8)
+ && (par1World.getBlockMaterial(var6, par3, var8) != this.blockMaterial
+ || par1World.getBlockMetadata(var6, par3, var8) != 0)) {
+ if (this.blockBlocksFlow(par1World, var6, par3 - 1, var8)) {
+ this.flowCost[var5] = this.calculateFlowCost(par1World, var6, par3, var8, 1, var5);
+ } else {
+ this.flowCost[var5] = 0;
+ }
+ }
+ }
+
+ var5 = this.flowCost[0];
+
+ for (var6 = 1; var6 < 4; ++var6) {
+ if (this.flowCost[var6] < var5) {
+ var5 = this.flowCost[var6];
+ }
+ }
+
+ for (var6 = 0; var6 < 4; ++var6) {
+ this.isOptimalFlowDirection[var6] = this.flowCost[var6] == var5;
+ }
+
+ return this.isOptimalFlowDirection;
+ }
+
+ /**
+ * Returns true if block at coords blocks fluids
+ */
+ private boolean blockBlocksFlow(World par1World, int par2, int par3, int par4) {
+ int var5 = par1World.getBlockId(par2, par3, par4);
+
+ if (var5 != Block.doorWood.blockID && var5 != Block.doorIron.blockID && var5 != Block.signPost.blockID
+ && var5 != Block.ladder.blockID && var5 != Block.reed.blockID) {
+ if (var5 == 0) {
+ return false;
+ } else {
+ Material var6 = Block.blocksList[var5].blockMaterial;
+ return var6 == Material.portal ? true : var6.blocksMovement();
+ }
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * getSmallestFlowDecay(World world, intx, int y, int z, int
+ * currentSmallestFlowDecay) - Looks up the flow decay at the coordinates given
+ * and returns the smaller of this value or the provided
+ * currentSmallestFlowDecay. If one value is valid and the other isn't, the
+ * valid value will be returned. Valid values are >= 0. Flow decay is the amount
+ * that a liquid has dissipated. 0 indicates a source block.
+ */
+ protected int getSmallestFlowDecay(World par1World, int par2, int par3, int par4, int par5) {
+ int var6 = this.getFlowDecay(par1World, par2, par3, par4);
+
+ if (var6 < 0) {
+ return par5;
+ } else {
+ if (var6 == 0) {
+ ++this.numAdjacentSources;
+ }
+
+ if (var6 >= 8) {
+ var6 = 0;
+ }
+
+ return par5 >= 0 && var6 >= par5 ? par5 : var6;
+ }
+ }
+
+ /**
+ * Returns true if the block at the coordinates can be displaced by the liquid.
+ */
+ private boolean liquidCanDisplaceBlock(World par1World, int par2, int par3, int par4) {
+ Material var5 = par1World.getBlockMaterial(par2, par3, par4);
+ return var5 == this.blockMaterial ? false
+ : (var5 == Material.lava ? false : !this.blockBlocksFlow(par1World, par2, par3, par4));
+ }
+
+ /**
+ * Called whenever the block is added into the world. Args: world, x, y, z
+ */
+ public void onBlockAdded(World par1World, int par2, int par3, int par4) {
+ super.onBlockAdded(par1World, par2, par3, par4);
+
+ if (par1World.getBlockId(par2, par3, par4) == this.blockID) {
+ par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, this.tickRate(par1World));
+ }
+ }
+
+ public boolean func_82506_l() {
+ return false;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockFluid.java b/sp-server/src/main/java/net/minecraft/src/BlockFluid.java
new file mode 100644
index 0000000..dc55aaa
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockFluid.java
@@ -0,0 +1,309 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public abstract class BlockFluid extends Block {
+ protected BlockFluid(int par1, Material par2Material) {
+ super(par1, par2Material);
+ float var3 = 0.0F;
+ float var4 = 0.0F;
+ this.setBlockBounds(0.0F + var4, 0.0F + var3, 0.0F + var4, 1.0F + var4, 1.0F + var3, 1.0F + var4);
+ this.setTickRandomly(true);
+ }
+
+ public boolean getBlocksMovement(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ return this.blockMaterial != Material.lava;
+ }
+
+ /**
+ * Returns the percentage of the fluid block that is air, based on the given
+ * flow decay of the fluid.
+ */
+ public static float getFluidHeightPercent(int par0) {
+ if (par0 >= 8) {
+ par0 = 0;
+ }
+
+ return (float) (par0 + 1) / 9.0F;
+ }
+
+ /**
+ * Returns the amount of fluid decay at the coordinates, or -1 if the block at
+ * the coordinates is not the same material as the fluid.
+ */
+ protected int getFlowDecay(World par1World, int par2, int par3, int par4) {
+ return par1World.getBlockMaterial(par2, par3, par4) == this.blockMaterial
+ ? par1World.getBlockMetadata(par2, par3, par4)
+ : -1;
+ }
+
+ /**
+ * Returns the flow decay but converts values indicating falling liquid (values
+ * >=8) to their effective source block value of zero.
+ */
+ protected int getEffectiveFlowDecay(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ if (par1IBlockAccess.getBlockMaterial(par2, par3, par4) != this.blockMaterial) {
+ return -1;
+ } else {
+ int var5 = par1IBlockAccess.getBlockMetadata(par2, par3, par4);
+
+ if (var5 >= 8) {
+ var5 = 0;
+ }
+
+ return var5;
+ }
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * Returns whether this block is collideable based on the arguments passed in
+ * Args: blockMetaData, unknownFlag
+ */
+ public boolean canCollideCheck(int par1, boolean par2) {
+ return par2 && par1 == 0;
+ }
+
+ /**
+ * Returns Returns true if the given side of this block type should be rendered
+ * (if it's solid or not), if the adjacent block is at the given coordinates.
+ * Args: blockAccess, x, y, z, side
+ */
+ public boolean isBlockSolid(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) {
+ Material var6 = par1IBlockAccess.getBlockMaterial(par2, par3, par4);
+ return var6 == this.blockMaterial ? false
+ : (par5 == 1 ? true
+ : (var6 == Material.ice ? false
+ : super.isBlockSolid(par1IBlockAccess, par2, par3, par4, par5)));
+ }
+
+ /**
+ * Returns a bounding box from the pool of bounding boxes (this means this box
+ * can change after the pool has been cleared to be reused)
+ */
+ public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) {
+ return null;
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 4;
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return 0;
+ }
+
+ /**
+ * Returns the quantity of items to drop on block destruction.
+ */
+ public int quantityDropped(EaglercraftRandom par1Random) {
+ return 0;
+ }
+
+ /**
+ * Returns a vector indicating the direction and intensity of fluid flow.
+ */
+ private Vec3 getFlowVector(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ Vec3 var5 = par1IBlockAccess.getWorldVec3Pool().getVecFromPool(0.0D, 0.0D, 0.0D);
+ int var6 = this.getEffectiveFlowDecay(par1IBlockAccess, par2, par3, par4);
+
+ for (int var7 = 0; var7 < 4; ++var7) {
+ int var8 = par2;
+ int var10 = par4;
+
+ if (var7 == 0) {
+ var8 = par2 - 1;
+ }
+
+ if (var7 == 1) {
+ var10 = par4 - 1;
+ }
+
+ if (var7 == 2) {
+ ++var8;
+ }
+
+ if (var7 == 3) {
+ ++var10;
+ }
+
+ int var11 = this.getEffectiveFlowDecay(par1IBlockAccess, var8, par3, var10);
+ int var12;
+
+ if (var11 < 0) {
+ if (!par1IBlockAccess.getBlockMaterial(var8, par3, var10).blocksMovement()) {
+ var11 = this.getEffectiveFlowDecay(par1IBlockAccess, var8, par3 - 1, var10);
+
+ if (var11 >= 0) {
+ var12 = var11 - (var6 - 8);
+ var5 = var5.addVector((double) ((var8 - par2) * var12), (double) ((par3 - par3) * var12),
+ (double) ((var10 - par4) * var12));
+ }
+ }
+ } else if (var11 >= 0) {
+ var12 = var11 - var6;
+ var5 = var5.addVector((double) ((var8 - par2) * var12), (double) ((par3 - par3) * var12),
+ (double) ((var10 - par4) * var12));
+ }
+ }
+
+ if (par1IBlockAccess.getBlockMetadata(par2, par3, par4) >= 8) {
+ boolean var13 = false;
+
+ if (var13 || this.isBlockSolid(par1IBlockAccess, par2, par3, par4 - 1, 2)) {
+ var13 = true;
+ }
+
+ if (var13 || this.isBlockSolid(par1IBlockAccess, par2, par3, par4 + 1, 3)) {
+ var13 = true;
+ }
+
+ if (var13 || this.isBlockSolid(par1IBlockAccess, par2 - 1, par3, par4, 4)) {
+ var13 = true;
+ }
+
+ if (var13 || this.isBlockSolid(par1IBlockAccess, par2 + 1, par3, par4, 5)) {
+ var13 = true;
+ }
+
+ if (var13 || this.isBlockSolid(par1IBlockAccess, par2, par3 + 1, par4 - 1, 2)) {
+ var13 = true;
+ }
+
+ if (var13 || this.isBlockSolid(par1IBlockAccess, par2, par3 + 1, par4 + 1, 3)) {
+ var13 = true;
+ }
+
+ if (var13 || this.isBlockSolid(par1IBlockAccess, par2 - 1, par3 + 1, par4, 4)) {
+ var13 = true;
+ }
+
+ if (var13 || this.isBlockSolid(par1IBlockAccess, par2 + 1, par3 + 1, par4, 5)) {
+ var13 = true;
+ }
+
+ if (var13) {
+ var5 = var5.normalize().addVector(0.0D, -6.0D, 0.0D);
+ }
+ }
+
+ var5 = var5.normalize();
+ return var5;
+ }
+
+ /**
+ * Can add to the passed in vector for a movement vector to be applied to the
+ * entity. Args: x, y, z, entity, vec3d
+ */
+ public void velocityToAddToEntity(World par1World, int par2, int par3, int par4, Entity par5Entity, Vec3 par6Vec3) {
+ Vec3 var7 = this.getFlowVector(par1World, par2, par3, par4);
+ par6Vec3.xCoord += var7.xCoord;
+ par6Vec3.yCoord += var7.yCoord;
+ par6Vec3.zCoord += var7.zCoord;
+ }
+
+ /**
+ * How many world ticks before ticking
+ */
+ public int tickRate(World par1World) {
+ return this.blockMaterial == Material.water ? 5
+ : (this.blockMaterial == Material.lava ? (par1World.provider.hasNoSky ? 10 : 30) : 0);
+ }
+
+ /**
+ * Called whenever the block is added into the world. Args: world, x, y, z
+ */
+ public void onBlockAdded(World par1World, int par2, int par3, int par4) {
+ this.checkForHarden(par1World, par2, par3, par4);
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ this.checkForHarden(par1World, par2, par3, par4);
+ }
+
+ /**
+ * Forces lava to check to see if it is colliding with water, and then decide
+ * what it should harden to.
+ */
+ private void checkForHarden(World par1World, int par2, int par3, int par4) {
+ if (par1World.getBlockId(par2, par3, par4) == this.blockID) {
+ if (this.blockMaterial == Material.lava) {
+ boolean var5 = false;
+
+ if (var5 || par1World.getBlockMaterial(par2, par3, par4 - 1) == Material.water) {
+ var5 = true;
+ }
+
+ if (var5 || par1World.getBlockMaterial(par2, par3, par4 + 1) == Material.water) {
+ var5 = true;
+ }
+
+ if (var5 || par1World.getBlockMaterial(par2 - 1, par3, par4) == Material.water) {
+ var5 = true;
+ }
+
+ if (var5 || par1World.getBlockMaterial(par2 + 1, par3, par4) == Material.water) {
+ var5 = true;
+ }
+
+ if (var5 || par1World.getBlockMaterial(par2, par3 + 1, par4) == Material.water) {
+ var5 = true;
+ }
+
+ if (var5) {
+ int var6 = par1World.getBlockMetadata(par2, par3, par4);
+
+ if (var6 == 0) {
+ par1World.setBlock(par2, par3, par4, Block.obsidian.blockID);
+ } else if (var6 <= 4) {
+ par1World.setBlock(par2, par3, par4, Block.cobblestone.blockID);
+ }
+
+ this.triggerLavaMixEffects(par1World, par2, par3, par4);
+ }
+ }
+ }
+ }
+
+ /**
+ * Creates fizzing sound and smoke. Used when lava flows over block or mixes
+ * with water.
+ */
+ protected void triggerLavaMixEffects(World par1World, int par2, int par3, int par4) {
+ par1World.playSoundEffect((double) ((float) par2 + 0.5F), (double) ((float) par3 + 0.5F),
+ (double) ((float) par4 + 0.5F), "random.fizz", 0.5F,
+ 2.6F + (par1World.rand.nextFloat() - par1World.rand.nextFloat()) * 0.8F);
+
+ for (int var5 = 0; var5 < 8; ++var5) {
+ par1World.spawnParticle("largesmoke", (double) par2 + Math.random(), (double) par3 + 1.2D,
+ (double) par4 + Math.random(), 0.0D, 0.0D, 0.0D);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockFurnace.java b/sp-server/src/main/java/net/minecraft/src/BlockFurnace.java
new file mode 100644
index 0000000..2651942
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockFurnace.java
@@ -0,0 +1,218 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockFurnace extends BlockContainer {
+ /**
+ * Is the random generator used by furnace to drop the inventory contents in
+ * random directions.
+ */
+ private final EaglercraftRandom furnaceRand = new EaglercraftRandom();
+
+ /** True if this is an active furnace, false if idle */
+ private final boolean isActive;
+
+ /**
+ * This flag is used to prevent the furnace inventory to be dropped upon block
+ * removal, is used internally when the furnace block changes from idle to
+ * active and vice-versa.
+ */
+ private static boolean keepFurnaceInventory = false;
+
+ protected BlockFurnace(int par1, boolean par2) {
+ super(par1, Material.rock);
+ this.isActive = par2;
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return Block.furnaceIdle.blockID;
+ }
+
+ /**
+ * Called whenever the block is added into the world. Args: world, x, y, z
+ */
+ public void onBlockAdded(World par1World, int par2, int par3, int par4) {
+ super.onBlockAdded(par1World, par2, par3, par4);
+ this.setDefaultDirection(par1World, par2, par3, par4);
+ }
+
+ /**
+ * set a blocks direction
+ */
+ private void setDefaultDirection(World par1World, int par2, int par3, int par4) {
+ if (!par1World.isRemote) {
+ int var5 = par1World.getBlockId(par2, par3, par4 - 1);
+ int var6 = par1World.getBlockId(par2, par3, par4 + 1);
+ int var7 = par1World.getBlockId(par2 - 1, par3, par4);
+ int var8 = par1World.getBlockId(par2 + 1, par3, par4);
+ byte var9 = 3;
+
+ if (Block.opaqueCubeLookup[var5] && !Block.opaqueCubeLookup[var6]) {
+ var9 = 3;
+ }
+
+ if (Block.opaqueCubeLookup[var6] && !Block.opaqueCubeLookup[var5]) {
+ var9 = 2;
+ }
+
+ if (Block.opaqueCubeLookup[var7] && !Block.opaqueCubeLookup[var8]) {
+ var9 = 5;
+ }
+
+ if (Block.opaqueCubeLookup[var8] && !Block.opaqueCubeLookup[var7]) {
+ var9 = 4;
+ }
+
+ par1World.setBlockMetadata(par2, par3, par4, var9, 2);
+ }
+ }
+
+ /**
+ * Called upon block activation (right click on the block.)
+ */
+ public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer,
+ int par6, float par7, float par8, float par9) {
+ if (par1World.isRemote) {
+ return true;
+ } else {
+ TileEntityFurnace var10 = (TileEntityFurnace) par1World.getBlockTileEntity(par2, par3, par4);
+
+ if (var10 != null) {
+ par5EntityPlayer.displayGUIFurnace(var10);
+ }
+
+ return true;
+ }
+ }
+
+ /**
+ * Update which block ID the furnace is using depending on whether or not it is
+ * burning
+ */
+ public static void updateFurnaceBlockState(boolean par0, World par1World, int par2, int par3, int par4) {
+ int var5 = par1World.getBlockMetadata(par2, par3, par4);
+ TileEntity var6 = par1World.getBlockTileEntity(par2, par3, par4);
+ keepFurnaceInventory = true;
+
+ if (par0) {
+ par1World.setBlock(par2, par3, par4, Block.furnaceBurning.blockID);
+ } else {
+ par1World.setBlock(par2, par3, par4, Block.furnaceIdle.blockID);
+ }
+
+ keepFurnaceInventory = false;
+ par1World.setBlockMetadata(par2, par3, par4, var5, 2);
+
+ if (var6 != null) {
+ var6.validate();
+ par1World.setBlockTileEntity(par2, par3, par4, var6);
+ }
+ }
+
+ /**
+ * Returns a new instance of a block's tile entity class. Called on placing the
+ * block.
+ */
+ public TileEntity createNewTileEntity(World par1World) {
+ return new TileEntityFurnace();
+ }
+
+ /**
+ * Called when the block is placed in the world.
+ */
+ public void onBlockPlacedBy(World par1World, int par2, int par3, int par4, EntityLiving par5EntityLiving,
+ ItemStack par6ItemStack) {
+ int var7 = MathHelper.floor_double((double) (par5EntityLiving.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3;
+
+ if (var7 == 0) {
+ par1World.setBlockMetadata(par2, par3, par4, 2, 2);
+ }
+
+ if (var7 == 1) {
+ par1World.setBlockMetadata(par2, par3, par4, 5, 2);
+ }
+
+ if (var7 == 2) {
+ par1World.setBlockMetadata(par2, par3, par4, 3, 2);
+ }
+
+ if (var7 == 3) {
+ par1World.setBlockMetadata(par2, par3, par4, 4, 2);
+ }
+
+ if (par6ItemStack.hasDisplayName()) {
+ ((TileEntityFurnace) par1World.getBlockTileEntity(par2, par3, par4))
+ .func_94129_a(par6ItemStack.getDisplayName());
+ }
+ }
+
+ /**
+ * ejects contained items into the world, and notifies neighbours of an update,
+ * as appropriate
+ */
+ public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) {
+ if (!keepFurnaceInventory) {
+ TileEntityFurnace var7 = (TileEntityFurnace) par1World.getBlockTileEntity(par2, par3, par4);
+
+ if (var7 != null) {
+ for (int var8 = 0; var8 < var7.getSizeInventory(); ++var8) {
+ ItemStack var9 = var7.getStackInSlot(var8);
+
+ if (var9 != null) {
+ float var10 = this.furnaceRand.nextFloat() * 0.8F + 0.1F;
+ float var11 = this.furnaceRand.nextFloat() * 0.8F + 0.1F;
+ float var12 = this.furnaceRand.nextFloat() * 0.8F + 0.1F;
+
+ while (var9.stackSize > 0) {
+ int var13 = this.furnaceRand.nextInt(21) + 10;
+
+ if (var13 > var9.stackSize) {
+ var13 = var9.stackSize;
+ }
+
+ var9.stackSize -= var13;
+ EntityItem var14 = new EntityItem(par1World, (double) ((float) par2 + var10),
+ (double) ((float) par3 + var11), (double) ((float) par4 + var12),
+ new ItemStack(var9.itemID, var13, var9.getItemDamage()));
+
+ if (var9.hasTagCompound()) {
+ var14.getEntityItem().setTagCompound((NBTTagCompound) var9.getTagCompound().copy());
+ }
+
+ float var15 = 0.05F;
+ var14.motionX = (double) ((float) this.furnaceRand.nextGaussian() * var15);
+ var14.motionY = (double) ((float) this.furnaceRand.nextGaussian() * var15 + 0.2F);
+ var14.motionZ = (double) ((float) this.furnaceRand.nextGaussian() * var15);
+ par1World.spawnEntityInWorld(var14);
+ }
+ }
+ }
+
+ par1World.func_96440_m(par2, par3, par4, par5);
+ }
+ }
+
+ super.breakBlock(par1World, par2, par3, par4, par5, par6);
+ }
+
+ /**
+ * If this returns true, then comparators facing away from this block will use
+ * the value from getComparatorInputOverride instead of the actual redstone
+ * signal strength.
+ */
+ public boolean hasComparatorInputOverride() {
+ return true;
+ }
+
+ /**
+ * If hasComparatorInputOverride returns true, the return value from this is
+ * used instead of the redstone signal strength when this block inputs to a
+ * comparator.
+ */
+ public int getComparatorInputOverride(World par1World, int par2, int par3, int par4, int par5) {
+ return Container.calcRedstoneFromInventory((IInventory) par1World.getBlockTileEntity(par2, par3, par4));
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockGlass.java b/sp-server/src/main/java/net/minecraft/src/BlockGlass.java
new file mode 100644
index 0000000..920bb9e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockGlass.java
@@ -0,0 +1,42 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockGlass extends BlockBreakable {
+ public BlockGlass(int par1, Material par2Material, boolean par3) {
+ super(par1, "glass", par2Material, par3);
+ this.setCreativeTab(CreativeTabs.tabBlock);
+ }
+
+ /**
+ * Returns the quantity of items to drop on block destruction.
+ */
+ public int quantityDropped(EaglercraftRandom par1Random) {
+ return 0;
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ /**
+ * Return true if a player with Silk Touch can harvest this block directly, and
+ * not its normal drops.
+ */
+ protected boolean canSilkHarvest() {
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockGlowStone.java b/sp-server/src/main/java/net/minecraft/src/BlockGlowStone.java
new file mode 100644
index 0000000..a8691c8
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockGlowStone.java
@@ -0,0 +1,32 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockGlowStone extends Block {
+ public BlockGlowStone(int par1, Material par2Material) {
+ super(par1, par2Material);
+ this.setCreativeTab(CreativeTabs.tabBlock);
+ }
+
+ /**
+ * Returns the usual quantity dropped by the block plus a bonus of 1 to 'i'
+ * (inclusive).
+ */
+ public int quantityDroppedWithBonus(int par1, EaglercraftRandom par2Random) {
+ return MathHelper.clamp_int(this.quantityDropped(par2Random) + par2Random.nextInt(par1 + 1), 1, 4);
+ }
+
+ /**
+ * Returns the quantity of items to drop on block destruction.
+ */
+ public int quantityDropped(EaglercraftRandom par1Random) {
+ return 2 + par1Random.nextInt(3);
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return Item.lightStoneDust.itemID;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockGrass.java b/sp-server/src/main/java/net/minecraft/src/BlockGrass.java
new file mode 100644
index 0000000..bfa1840
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockGrass.java
@@ -0,0 +1,43 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockGrass extends Block {
+ protected BlockGrass(int par1) {
+ super(par1, Material.grass);
+ this.setTickRandomly(true);
+ this.setCreativeTab(CreativeTabs.tabBlock);
+ }
+
+ /**
+ * Ticks the block if it's been scheduled
+ */
+ public void updateTick(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ if (!par1World.isRemote) {
+ if (par1World.getBlockLightValue(par2, par3 + 1, par4) < 4
+ && Block.lightOpacity[par1World.getBlockId(par2, par3 + 1, par4)] > 2) {
+ par1World.setBlock(par2, par3, par4, Block.dirt.blockID);
+ } else if (par1World.getBlockLightValue(par2, par3 + 1, par4) >= 9) {
+ for (int var6 = 0; var6 < 4; ++var6) {
+ int var7 = par2 + par5Random.nextInt(3) - 1;
+ int var8 = par3 + par5Random.nextInt(5) - 3;
+ int var9 = par4 + par5Random.nextInt(3) - 1;
+ int var10 = par1World.getBlockId(var7, var8 + 1, var9);
+
+ if (par1World.getBlockId(var7, var8, var9) == Block.dirt.blockID
+ && par1World.getBlockLightValue(var7, var8 + 1, var9) >= 4
+ && Block.lightOpacity[var10] <= 2) {
+ par1World.setBlock(var7, var8, var9, Block.grass.blockID);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return Block.dirt.idDropped(0, par2Random, par3);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockGravel.java b/sp-server/src/main/java/net/minecraft/src/BlockGravel.java
new file mode 100644
index 0000000..b3c7c1e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockGravel.java
@@ -0,0 +1,20 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockGravel extends BlockSand {
+ public BlockGravel(int par1) {
+ super(par1);
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ if (par3 > 3) {
+ par3 = 3;
+ }
+
+ return par2Random.nextInt(10 - par3 * 3) == 0 ? Item.flint.itemID : this.blockID;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockHalfSlab.java b/sp-server/src/main/java/net/minecraft/src/BlockHalfSlab.java
new file mode 100644
index 0000000..829ed18
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockHalfSlab.java
@@ -0,0 +1,113 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public abstract class BlockHalfSlab extends Block {
+ protected final boolean isDoubleSlab;
+
+ public BlockHalfSlab(int par1, boolean par2, Material par3Material) {
+ super(par1, par3Material);
+ this.isDoubleSlab = par2;
+
+ if (par2) {
+ opaqueCubeLookup[par1] = true;
+ } else {
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.5F, 1.0F);
+ }
+
+ this.setLightOpacity(255);
+ }
+
+ /**
+ * Updates the blocks bounds based on its current state. Args: world, x, y, z
+ */
+ public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ if (this.isDoubleSlab) {
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
+ } else {
+ boolean var5 = (par1IBlockAccess.getBlockMetadata(par2, par3, par4) & 8) != 0;
+
+ if (var5) {
+ this.setBlockBounds(0.0F, 0.5F, 0.0F, 1.0F, 1.0F, 1.0F);
+ } else {
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.5F, 1.0F);
+ }
+ }
+ }
+
+ /**
+ * Sets the block's bounds for rendering it as an item
+ */
+ public void setBlockBoundsForItemRender() {
+ if (this.isDoubleSlab) {
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
+ } else {
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.5F, 1.0F);
+ }
+ }
+
+ /**
+ * Adds all intersecting collision boxes to a list. (Be sure to only add boxes
+ * to the list if they intersect the mask.) Parameters: World, X, Y, Z, mask,
+ * list, colliding entity
+ */
+ public void addCollisionBoxesToList(World par1World, int par2, int par3, int par4, AxisAlignedBB par5AxisAlignedBB,
+ List par6List, Entity par7Entity) {
+ this.setBlockBoundsBasedOnState(par1World, par2, par3, par4);
+ super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return this.isDoubleSlab;
+ }
+
+ /**
+ * Called when a block is placed using its ItemBlock. Args: World, X, Y, Z,
+ * side, hitX, hitY, hitZ, block metadata
+ */
+ public int onBlockPlaced(World par1World, int par2, int par3, int par4, int par5, float par6, float par7,
+ float par8, int par9) {
+ return this.isDoubleSlab ? par9 : (par5 != 0 && (par5 == 1 || (double) par7 <= 0.5D) ? par9 : par9 | 8);
+ }
+
+ /**
+ * Returns the quantity of items to drop on block destruction.
+ */
+ public int quantityDropped(EaglercraftRandom par1Random) {
+ return this.isDoubleSlab ? 2 : 1;
+ }
+
+ /**
+ * Determines the damage on the item the block drops. Used in cloth and wood.
+ */
+ public int damageDropped(int par1) {
+ return par1 & 7;
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return this.isDoubleSlab;
+ }
+
+ /**
+ * Returns the slab block name with step type.
+ */
+ public abstract String getFullSlabName(int var1);
+
+ /**
+ * Get the block's damage value (for use with pick block).
+ */
+ public int getDamageValue(World par1World, int par2, int par3, int par4) {
+ return super.getDamageValue(par1World, par2, par3, par4) & 7;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockHopper.java b/sp-server/src/main/java/net/minecraft/src/BlockHopper.java
new file mode 100644
index 0000000..7a88865
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockHopper.java
@@ -0,0 +1,229 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockHopper extends BlockContainer {
+ private final EaglercraftRandom field_94457_a = new EaglercraftRandom();
+
+ public BlockHopper(int par1) {
+ super(par1, Material.iron);
+ this.setCreativeTab(CreativeTabs.tabRedstone);
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
+ }
+
+ /**
+ * Updates the blocks bounds based on its current state. Args: world, x, y, z
+ */
+ public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
+ }
+
+ /**
+ * Adds all intersecting collision boxes to a list. (Be sure to only add boxes
+ * to the list if they intersect the mask.) Parameters: World, X, Y, Z, mask,
+ * list, colliding entity
+ */
+ public void addCollisionBoxesToList(World par1World, int par2, int par3, int par4, AxisAlignedBB par5AxisAlignedBB,
+ List par6List, Entity par7Entity) {
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.625F, 1.0F);
+ super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
+ float var8 = 0.125F;
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, var8, 1.0F, 1.0F);
+ super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, var8);
+ super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
+ this.setBlockBounds(1.0F - var8, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
+ super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
+ this.setBlockBounds(0.0F, 0.0F, 1.0F - var8, 1.0F, 1.0F, 1.0F);
+ super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
+ }
+
+ /**
+ * Called when a block is placed using its ItemBlock. Args: World, X, Y, Z,
+ * side, hitX, hitY, hitZ, block metadata
+ */
+ public int onBlockPlaced(World par1World, int par2, int par3, int par4, int par5, float par6, float par7,
+ float par8, int par9) {
+ int var10 = Facing.oppositeSide[par5];
+
+ if (var10 == 1) {
+ var10 = 0;
+ }
+
+ return var10;
+ }
+
+ /**
+ * Returns a new instance of a block's tile entity class. Called on placing the
+ * block.
+ */
+ public TileEntity createNewTileEntity(World par1World) {
+ return new TileEntityHopper();
+ }
+
+ /**
+ * Called when the block is placed in the world.
+ */
+ public void onBlockPlacedBy(World par1World, int par2, int par3, int par4, EntityLiving par5EntityLiving,
+ ItemStack par6ItemStack) {
+ super.onBlockPlacedBy(par1World, par2, par3, par4, par5EntityLiving, par6ItemStack);
+
+ if (par6ItemStack.hasDisplayName()) {
+ TileEntityHopper var7 = getHopperTile(par1World, par2, par3, par4);
+ var7.setInventoryName(par6ItemStack.getDisplayName());
+ }
+ }
+
+ /**
+ * Called whenever the block is added into the world. Args: world, x, y, z
+ */
+ public void onBlockAdded(World par1World, int par2, int par3, int par4) {
+ super.onBlockAdded(par1World, par2, par3, par4);
+ this.updateMetadata(par1World, par2, par3, par4);
+ }
+
+ /**
+ * Called upon block activation (right click on the block.)
+ */
+ public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer,
+ int par6, float par7, float par8, float par9) {
+ if (par1World.isRemote) {
+ return true;
+ } else {
+ TileEntityHopper var10 = getHopperTile(par1World, par2, par3, par4);
+
+ if (var10 != null) {
+ par5EntityPlayer.displayGUIHopper(var10);
+ }
+
+ return true;
+ }
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ this.updateMetadata(par1World, par2, par3, par4);
+ }
+
+ /**
+ * Updates the Metadata to include if the Hopper gets powered by Redstone or not
+ */
+ private void updateMetadata(World par1World, int par2, int par3, int par4) {
+ int var5 = par1World.getBlockMetadata(par2, par3, par4);
+ int var6 = getDirectionFromMetadata(var5);
+ boolean var7 = !par1World.isBlockIndirectlyGettingPowered(par2, par3, par4);
+ boolean var8 = getIsBlockNotPoweredFromMetadata(var5);
+
+ if (var7 != var8) {
+ par1World.setBlockMetadata(par2, par3, par4, var6 | (var7 ? 0 : 8), 4);
+ }
+ }
+
+ /**
+ * ejects contained items into the world, and notifies neighbours of an update,
+ * as appropriate
+ */
+ public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) {
+ TileEntityHopper var7 = (TileEntityHopper) par1World.getBlockTileEntity(par2, par3, par4);
+
+ if (var7 != null) {
+ for (int var8 = 0; var8 < var7.getSizeInventory(); ++var8) {
+ ItemStack var9 = var7.getStackInSlot(var8);
+
+ if (var9 != null) {
+ float var10 = this.field_94457_a.nextFloat() * 0.8F + 0.1F;
+ float var11 = this.field_94457_a.nextFloat() * 0.8F + 0.1F;
+ float var12 = this.field_94457_a.nextFloat() * 0.8F + 0.1F;
+
+ while (var9.stackSize > 0) {
+ int var13 = this.field_94457_a.nextInt(21) + 10;
+
+ if (var13 > var9.stackSize) {
+ var13 = var9.stackSize;
+ }
+
+ var9.stackSize -= var13;
+ EntityItem var14 = new EntityItem(par1World, (double) ((float) par2 + var10),
+ (double) ((float) par3 + var11), (double) ((float) par4 + var12),
+ new ItemStack(var9.itemID, var13, var9.getItemDamage()));
+
+ if (var9.hasTagCompound()) {
+ var14.getEntityItem().setTagCompound((NBTTagCompound) var9.getTagCompound().copy());
+ }
+
+ float var15 = 0.05F;
+ var14.motionX = (double) ((float) this.field_94457_a.nextGaussian() * var15);
+ var14.motionY = (double) ((float) this.field_94457_a.nextGaussian() * var15 + 0.2F);
+ var14.motionZ = (double) ((float) this.field_94457_a.nextGaussian() * var15);
+ par1World.spawnEntityInWorld(var14);
+ }
+ }
+ }
+
+ par1World.func_96440_m(par2, par3, par4, par5);
+ }
+
+ super.breakBlock(par1World, par2, par3, par4, par5, par6);
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 38;
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ public static int getDirectionFromMetadata(int par0) {
+ return par0 & 7;
+ }
+
+ public static boolean getIsBlockNotPoweredFromMetadata(int par0) {
+ return (par0 & 8) != 8;
+ }
+
+ /**
+ * If this returns true, then comparators facing away from this block will use
+ * the value from getComparatorInputOverride instead of the actual redstone
+ * signal strength.
+ */
+ public boolean hasComparatorInputOverride() {
+ return true;
+ }
+
+ /**
+ * If hasComparatorInputOverride returns true, the return value from this is
+ * used instead of the redstone signal strength when this block inputs to a
+ * comparator.
+ */
+ public int getComparatorInputOverride(World par1World, int par2, int par3, int par4, int par5) {
+ return Container.calcRedstoneFromInventory(getHopperTile(par1World, par2, par3, par4));
+ }
+
+ public static TileEntityHopper getHopperTile(IBlockAccess par0IBlockAccess, int par1, int par2, int par3) {
+ return (TileEntityHopper) par0IBlockAccess.getBlockTileEntity(par1, par2, par3);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockIce.java b/sp-server/src/main/java/net/minecraft/src/BlockIce.java
new file mode 100644
index 0000000..8b53866
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockIce.java
@@ -0,0 +1,73 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockIce extends BlockBreakable {
+ public BlockIce(int par1) {
+ super(par1, "ice", Material.ice, false);
+ this.slipperiness = 0.98F;
+ this.setTickRandomly(true);
+ this.setCreativeTab(CreativeTabs.tabBlock);
+ }
+
+ /**
+ * Called when the player destroys a block with an item that can harvest it. (i,
+ * j, k) are the coordinates of the block and l is the block's subtype/damage.
+ */
+ public void harvestBlock(World par1World, EntityPlayer par2EntityPlayer, int par3, int par4, int par5, int par6) {
+ par2EntityPlayer.addStat(StatList.mineBlockStatArray[this.blockID], 1);
+ par2EntityPlayer.addExhaustion(0.025F);
+
+ if (this.canSilkHarvest() && EnchantmentHelper.getSilkTouchModifier(par2EntityPlayer)) {
+ ItemStack var9 = this.createStackedBlock(par6);
+
+ if (var9 != null) {
+ this.dropBlockAsItem_do(par1World, par3, par4, par5, var9);
+ }
+ } else {
+ if (par1World.provider.isHellWorld) {
+ par1World.setBlockToAir(par3, par4, par5);
+ return;
+ }
+
+ int var7 = EnchantmentHelper.getFortuneModifier(par2EntityPlayer);
+ this.dropBlockAsItem(par1World, par3, par4, par5, par6, var7);
+ Material var8 = par1World.getBlockMaterial(par3, par4 - 1, par5);
+
+ if (var8.blocksMovement() || var8.isLiquid()) {
+ par1World.setBlock(par3, par4, par5, Block.waterMoving.blockID);
+ }
+ }
+ }
+
+ /**
+ * Returns the quantity of items to drop on block destruction.
+ */
+ public int quantityDropped(EaglercraftRandom par1Random) {
+ return 0;
+ }
+
+ /**
+ * Ticks the block if it's been scheduled
+ */
+ public void updateTick(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ if (par1World.getSavedLightValue(EnumSkyBlock.Block, par2, par3, par4) > 11
+ - Block.lightOpacity[this.blockID]) {
+ if (par1World.provider.isHellWorld) {
+ par1World.setBlockToAir(par2, par3, par4);
+ return;
+ }
+
+ this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
+ par1World.setBlock(par2, par3, par4, Block.waterStill.blockID);
+ }
+ }
+
+ /**
+ * Returns the mobility information of the block, 0 = free, 1 = can't push but
+ * can move over, 2 = total immobility and stop pistons
+ */
+ public int getMobilityFlag() {
+ return 0;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockJukeBox.java b/sp-server/src/main/java/net/minecraft/src/BlockJukeBox.java
new file mode 100644
index 0000000..48e3427
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockJukeBox.java
@@ -0,0 +1,110 @@
+package net.minecraft.src;
+
+public class BlockJukeBox extends BlockContainer {
+ protected BlockJukeBox(int par1) {
+ super(par1, Material.wood);
+ this.setCreativeTab(CreativeTabs.tabDecorations);
+ }
+
+ /**
+ * Called upon block activation (right click on the block.)
+ */
+ public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer,
+ int par6, float par7, float par8, float par9) {
+ if (par1World.getBlockMetadata(par2, par3, par4) == 0) {
+ return false;
+ } else {
+ this.ejectRecord(par1World, par2, par3, par4);
+ return true;
+ }
+ }
+
+ /**
+ * Insert the specified music disc in the jukebox at the given coordinates
+ */
+ public void insertRecord(World par1World, int par2, int par3, int par4, ItemStack par5ItemStack) {
+ if (!par1World.isRemote) {
+ TileEntityRecordPlayer var6 = (TileEntityRecordPlayer) par1World.getBlockTileEntity(par2, par3, par4);
+
+ if (var6 != null) {
+ var6.func_96098_a(par5ItemStack.copy());
+ par1World.setBlockMetadata(par2, par3, par4, 1, 2);
+ }
+ }
+ }
+
+ /**
+ * Ejects the current record inside of the jukebox.
+ */
+ public void ejectRecord(World par1World, int par2, int par3, int par4) {
+ if (!par1World.isRemote) {
+ TileEntityRecordPlayer var5 = (TileEntityRecordPlayer) par1World.getBlockTileEntity(par2, par3, par4);
+
+ if (var5 != null) {
+ ItemStack var6 = var5.func_96097_a();
+
+ if (var6 != null) {
+ par1World.playAuxSFX(1005, par2, par3, par4, 0);
+ par1World.playRecord((String) null, par2, par3, par4);
+ var5.func_96098_a((ItemStack) null);
+ par1World.setBlockMetadata(par2, par3, par4, 0, 2);
+ float var7 = 0.7F;
+ double var8 = (double) (par1World.rand.nextFloat() * var7) + (double) (1.0F - var7) * 0.5D;
+ double var10 = (double) (par1World.rand.nextFloat() * var7) + (double) (1.0F - var7) * 0.2D + 0.6D;
+ double var12 = (double) (par1World.rand.nextFloat() * var7) + (double) (1.0F - var7) * 0.5D;
+ ItemStack var14 = var6.copy();
+ EntityItem var15 = new EntityItem(par1World, (double) par2 + var8, (double) par3 + var10,
+ (double) par4 + var12, var14);
+ var15.delayBeforeCanPickup = 10;
+ par1World.spawnEntityInWorld(var15);
+ }
+ }
+ }
+ }
+
+ /**
+ * ejects contained items into the world, and notifies neighbours of an update,
+ * as appropriate
+ */
+ public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) {
+ this.ejectRecord(par1World, par2, par3, par4);
+ super.breakBlock(par1World, par2, par3, par4, par5, par6);
+ }
+
+ /**
+ * Drops the block items with a specified chance of dropping the specified items
+ */
+ public void dropBlockAsItemWithChance(World par1World, int par2, int par3, int par4, int par5, float par6,
+ int par7) {
+ if (!par1World.isRemote) {
+ super.dropBlockAsItemWithChance(par1World, par2, par3, par4, par5, par6, 0);
+ }
+ }
+
+ /**
+ * Returns a new instance of a block's tile entity class. Called on placing the
+ * block.
+ */
+ public TileEntity createNewTileEntity(World par1World) {
+ return new TileEntityRecordPlayer();
+ }
+
+ /**
+ * If this returns true, then comparators facing away from this block will use
+ * the value from getComparatorInputOverride instead of the actual redstone
+ * signal strength.
+ */
+ public boolean hasComparatorInputOverride() {
+ return true;
+ }
+
+ /**
+ * If hasComparatorInputOverride returns true, the return value from this is
+ * used instead of the redstone signal strength when this block inputs to a
+ * comparator.
+ */
+ public int getComparatorInputOverride(World par1World, int par2, int par3, int par4, int par5) {
+ ItemStack var6 = ((TileEntityRecordPlayer) par1World.getBlockTileEntity(par2, par3, par4)).func_96097_a();
+ return var6 == null ? 0 : var6.itemID + 1 - Item.record13.itemID;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockLadder.java b/sp-server/src/main/java/net/minecraft/src/BlockLadder.java
new file mode 100644
index 0000000..e04819d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockLadder.java
@@ -0,0 +1,151 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockLadder extends Block {
+ protected BlockLadder(int par1) {
+ super(par1, Material.circuits);
+ this.setCreativeTab(CreativeTabs.tabDecorations);
+ }
+
+ /**
+ * Returns a bounding box from the pool of bounding boxes (this means this box
+ * can change after the pool has been cleared to be reused)
+ */
+ public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) {
+ this.setBlockBoundsBasedOnState(par1World, par2, par3, par4);
+ return super.getCollisionBoundingBoxFromPool(par1World, par2, par3, par4);
+ }
+
+ /**
+ * Updates the blocks bounds based on its current state. Args: world, x, y, z
+ */
+ public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ this.updateLadderBounds(par1IBlockAccess.getBlockMetadata(par2, par3, par4));
+ }
+
+ /**
+ * Update the ladder block bounds based on the given metadata value.
+ */
+ public void updateLadderBounds(int par1) {
+ float var3 = 0.125F;
+
+ if (par1 == 2) {
+ this.setBlockBounds(0.0F, 0.0F, 1.0F - var3, 1.0F, 1.0F, 1.0F);
+ }
+
+ if (par1 == 3) {
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, var3);
+ }
+
+ if (par1 == 4) {
+ this.setBlockBounds(1.0F - var3, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
+ }
+
+ if (par1 == 5) {
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, var3, 1.0F, 1.0F);
+ }
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 8;
+ }
+
+ /**
+ * Checks to see if its valid to put this block at the specified coordinates.
+ * Args: world, x, y, z
+ */
+ public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4) {
+ return par1World.isBlockNormalCube(par2 - 1, par3, par4) ? true
+ : (par1World.isBlockNormalCube(par2 + 1, par3, par4) ? true
+ : (par1World.isBlockNormalCube(par2, par3, par4 - 1) ? true
+ : par1World.isBlockNormalCube(par2, par3, par4 + 1)));
+ }
+
+ /**
+ * Called when a block is placed using its ItemBlock. Args: World, X, Y, Z,
+ * side, hitX, hitY, hitZ, block metadata
+ */
+ public int onBlockPlaced(World par1World, int par2, int par3, int par4, int par5, float par6, float par7,
+ float par8, int par9) {
+ int var10 = par9;
+
+ if ((par9 == 0 || par5 == 2) && par1World.isBlockNormalCube(par2, par3, par4 + 1)) {
+ var10 = 2;
+ }
+
+ if ((var10 == 0 || par5 == 3) && par1World.isBlockNormalCube(par2, par3, par4 - 1)) {
+ var10 = 3;
+ }
+
+ if ((var10 == 0 || par5 == 4) && par1World.isBlockNormalCube(par2 + 1, par3, par4)) {
+ var10 = 4;
+ }
+
+ if ((var10 == 0 || par5 == 5) && par1World.isBlockNormalCube(par2 - 1, par3, par4)) {
+ var10 = 5;
+ }
+
+ return var10;
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ int var6 = par1World.getBlockMetadata(par2, par3, par4);
+ boolean var7 = false;
+
+ if (var6 == 2 && par1World.isBlockNormalCube(par2, par3, par4 + 1)) {
+ var7 = true;
+ }
+
+ if (var6 == 3 && par1World.isBlockNormalCube(par2, par3, par4 - 1)) {
+ var7 = true;
+ }
+
+ if (var6 == 4 && par1World.isBlockNormalCube(par2 + 1, par3, par4)) {
+ var7 = true;
+ }
+
+ if (var6 == 5 && par1World.isBlockNormalCube(par2 - 1, par3, par4)) {
+ var7 = true;
+ }
+
+ if (!var7) {
+ this.dropBlockAsItem(par1World, par2, par3, par4, var6, 0);
+ par1World.setBlockToAir(par2, par3, par4);
+ }
+
+ super.onNeighborBlockChange(par1World, par2, par3, par4, par5);
+ }
+
+ /**
+ * Returns the quantity of items to drop on block destruction.
+ */
+ public int quantityDropped(EaglercraftRandom par1Random) {
+ return 1;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockLeaves.java b/sp-server/src/main/java/net/minecraft/src/BlockLeaves.java
new file mode 100644
index 0000000..cf4c98a
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockLeaves.java
@@ -0,0 +1,245 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockLeaves extends BlockLeavesBase {
+ public static final String[] LEAF_TYPES = new String[] { "oak", "spruce", "birch", "jungle" };
+ public static final String[][] field_94396_b = new String[][] {
+ { "leaves", "leaves_spruce", "leaves", "leaves_jungle" },
+ { "leaves_opaque", "leaves_spruce_opaque", "leaves_opaque", "leaves_jungle_opaque" } };
+ private Icon[][] iconArray = new Icon[2][];
+ int[] adjacentTreeBlocks;
+
+ protected BlockLeaves(int par1) {
+ super(par1, Material.leaves, false);
+ this.setTickRandomly(true);
+ this.setCreativeTab(CreativeTabs.tabDecorations);
+ }
+
+ /**
+ * ejects contained items into the world, and notifies neighbours of an update,
+ * as appropriate
+ */
+ public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) {
+ byte var7 = 1;
+ int var8 = var7 + 1;
+
+ if (par1World.checkChunksExist(par2 - var8, par3 - var8, par4 - var8, par2 + var8, par3 + var8, par4 + var8)) {
+ for (int var9 = -var7; var9 <= var7; ++var9) {
+ for (int var10 = -var7; var10 <= var7; ++var10) {
+ for (int var11 = -var7; var11 <= var7; ++var11) {
+ int var12 = par1World.getBlockId(par2 + var9, par3 + var10, par4 + var11);
+
+ if (var12 == Block.leaves.blockID) {
+ int var13 = par1World.getBlockMetadata(par2 + var9, par3 + var10, par4 + var11);
+ par1World.setBlockMetadata(par2 + var9, par3 + var10, par4 + var11, var13 | 8, 4);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Ticks the block if it's been scheduled
+ */
+ public void updateTick(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ if (!par1World.isRemote) {
+ int var6 = par1World.getBlockMetadata(par2, par3, par4);
+
+ if ((var6 & 8) != 0 && (var6 & 4) == 0) {
+ byte var7 = 4;
+ int var8 = var7 + 1;
+ byte var9 = 32;
+ int var10 = var9 * var9;
+ int var11 = var9 / 2;
+
+ if (this.adjacentTreeBlocks == null) {
+ this.adjacentTreeBlocks = new int[var9 * var9 * var9];
+ }
+
+ int var12;
+
+ if (par1World.checkChunksExist(par2 - var8, par3 - var8, par4 - var8, par2 + var8, par3 + var8,
+ par4 + var8)) {
+ int var13;
+ int var14;
+ int var15;
+
+ for (var12 = -var7; var12 <= var7; ++var12) {
+ for (var13 = -var7; var13 <= var7; ++var13) {
+ for (var14 = -var7; var14 <= var7; ++var14) {
+ var15 = par1World.getBlockId(par2 + var12, par3 + var13, par4 + var14);
+
+ if (var15 == Block.wood.blockID) {
+ this.adjacentTreeBlocks[(var12 + var11) * var10 + (var13 + var11) * var9 + var14
+ + var11] = 0;
+ } else if (var15 == Block.leaves.blockID) {
+ this.adjacentTreeBlocks[(var12 + var11) * var10 + (var13 + var11) * var9 + var14
+ + var11] = -2;
+ } else {
+ this.adjacentTreeBlocks[(var12 + var11) * var10 + (var13 + var11) * var9 + var14
+ + var11] = -1;
+ }
+ }
+ }
+ }
+
+ for (var12 = 1; var12 <= 4; ++var12) {
+ for (var13 = -var7; var13 <= var7; ++var13) {
+ for (var14 = -var7; var14 <= var7; ++var14) {
+ for (var15 = -var7; var15 <= var7; ++var15) {
+ if (this.adjacentTreeBlocks[(var13 + var11) * var10 + (var14 + var11) * var9 + var15
+ + var11] == var12 - 1) {
+ if (this.adjacentTreeBlocks[(var13 + var11 - 1) * var10 + (var14 + var11) * var9
+ + var15 + var11] == -2) {
+ this.adjacentTreeBlocks[(var13 + var11 - 1) * var10 + (var14 + var11) * var9
+ + var15 + var11] = var12;
+ }
+
+ if (this.adjacentTreeBlocks[(var13 + var11 + 1) * var10 + (var14 + var11) * var9
+ + var15 + var11] == -2) {
+ this.adjacentTreeBlocks[(var13 + var11 + 1) * var10 + (var14 + var11) * var9
+ + var15 + var11] = var12;
+ }
+
+ if (this.adjacentTreeBlocks[(var13 + var11) * var10 + (var14 + var11 - 1) * var9
+ + var15 + var11] == -2) {
+ this.adjacentTreeBlocks[(var13 + var11) * var10 + (var14 + var11 - 1) * var9
+ + var15 + var11] = var12;
+ }
+
+ if (this.adjacentTreeBlocks[(var13 + var11) * var10 + (var14 + var11 + 1) * var9
+ + var15 + var11] == -2) {
+ this.adjacentTreeBlocks[(var13 + var11) * var10 + (var14 + var11 + 1) * var9
+ + var15 + var11] = var12;
+ }
+
+ if (this.adjacentTreeBlocks[(var13 + var11) * var10 + (var14 + var11) * var9
+ + (var15 + var11 - 1)] == -2) {
+ this.adjacentTreeBlocks[(var13 + var11) * var10 + (var14 + var11) * var9
+ + (var15 + var11 - 1)] = var12;
+ }
+
+ if (this.adjacentTreeBlocks[(var13 + var11) * var10 + (var14 + var11) * var9
+ + var15 + var11 + 1] == -2) {
+ this.adjacentTreeBlocks[(var13 + var11) * var10 + (var14 + var11) * var9
+ + var15 + var11 + 1] = var12;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ var12 = this.adjacentTreeBlocks[var11 * var10 + var11 * var9 + var11];
+
+ if (var12 >= 0) {
+ par1World.setBlockMetadata(par2, par3, par4, var6 & -9, 4);
+ } else {
+ this.removeLeaves(par1World, par2, par3, par4);
+ }
+ }
+ }
+ }
+
+ private void removeLeaves(World par1World, int par2, int par3, int par4) {
+ this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
+ par1World.setBlockToAir(par2, par3, par4);
+ }
+
+ /**
+ * Returns the quantity of items to drop on block destruction.
+ */
+ public int quantityDropped(EaglercraftRandom par1Random) {
+ return par1Random.nextInt(20) == 0 ? 1 : 0;
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return Block.sapling.blockID;
+ }
+
+ /**
+ * Drops the block items with a specified chance of dropping the specified items
+ */
+ public void dropBlockAsItemWithChance(World par1World, int par2, int par3, int par4, int par5, float par6,
+ int par7) {
+ if (!par1World.isRemote) {
+ int var8 = 20;
+
+ if ((par5 & 3) == 3) {
+ var8 = 40;
+ }
+
+ if (par7 > 0) {
+ var8 -= 2 << par7;
+
+ if (var8 < 10) {
+ var8 = 10;
+ }
+ }
+
+ if (par1World.rand.nextInt(var8) == 0) {
+ int var9 = this.idDropped(par5, par1World.rand, par7);
+ this.dropBlockAsItem_do(par1World, par2, par3, par4, new ItemStack(var9, 1, this.damageDropped(par5)));
+ }
+
+ var8 = 200;
+
+ if (par7 > 0) {
+ var8 -= 10 << par7;
+
+ if (var8 < 40) {
+ var8 = 40;
+ }
+ }
+
+ if ((par5 & 3) == 0 && par1World.rand.nextInt(var8) == 0) {
+ this.dropBlockAsItem_do(par1World, par2, par3, par4, new ItemStack(Item.appleRed, 1, 0));
+ }
+ }
+ }
+
+ /**
+ * Called when the player destroys a block with an item that can harvest it. (i,
+ * j, k) are the coordinates of the block and l is the block's subtype/damage.
+ */
+ public void harvestBlock(World par1World, EntityPlayer par2EntityPlayer, int par3, int par4, int par5, int par6) {
+ if (!par1World.isRemote && par2EntityPlayer.getCurrentEquippedItem() != null
+ && par2EntityPlayer.getCurrentEquippedItem().itemID == Item.shears.itemID) {
+ par2EntityPlayer.addStat(StatList.mineBlockStatArray[this.blockID], 1);
+ this.dropBlockAsItem_do(par1World, par3, par4, par5, new ItemStack(Block.leaves.blockID, 1, par6 & 3));
+ } else {
+ super.harvestBlock(par1World, par2EntityPlayer, par3, par4, par5, par6);
+ }
+ }
+
+ /**
+ * Determines the damage on the item the block drops. Used in cloth and wood.
+ */
+ public int damageDropped(int par1) {
+ return par1 & 3;
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return !this.graphicsLevel;
+ }
+
+ /**
+ * Returns an item stack containing a single instance of the current block type.
+ * 'i' is the block's subtype/damage and is ignored for blocks which do not
+ * support subtypes. Blocks which cannot be harvested should return null.
+ */
+ protected ItemStack createStackedBlock(int par1) {
+ return new ItemStack(this.blockID, 1, par1 & 3);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockLeavesBase.java b/sp-server/src/main/java/net/minecraft/src/BlockLeavesBase.java
new file mode 100644
index 0000000..a9af609
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockLeavesBase.java
@@ -0,0 +1,23 @@
+package net.minecraft.src;
+
+public class BlockLeavesBase extends Block {
+ /**
+ * Used to determine how to display leaves based on the graphics level. May also
+ * be used in rendering for transparency, not sure.
+ */
+ protected boolean graphicsLevel;
+
+ protected BlockLeavesBase(int par1, Material par2Material, boolean par3) {
+ super(par1, par2Material);
+ this.graphicsLevel = par3;
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockLever.java b/sp-server/src/main/java/net/minecraft/src/BlockLever.java
new file mode 100644
index 0000000..50a6b7e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockLever.java
@@ -0,0 +1,356 @@
+package net.minecraft.src;
+
+public class BlockLever extends Block {
+ protected BlockLever(int par1) {
+ super(par1, Material.circuits);
+ this.setCreativeTab(CreativeTabs.tabRedstone);
+ }
+
+ /**
+ * Returns a bounding box from the pool of bounding boxes (this means this box
+ * can change after the pool has been cleared to be reused)
+ */
+ public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) {
+ return null;
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 12;
+ }
+
+ /**
+ * checks to see if you can place this block can be placed on that side of a
+ * block: BlockLever overrides
+ */
+ public boolean canPlaceBlockOnSide(World par1World, int par2, int par3, int par4, int par5) {
+ return par5 == 0 && par1World.isBlockNormalCube(par2, par3 + 1, par4) ? true
+ : (par5 == 1 && par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4) ? true
+ : (par5 == 2 && par1World.isBlockNormalCube(par2, par3, par4 + 1) ? true
+ : (par5 == 3 && par1World.isBlockNormalCube(par2, par3, par4 - 1) ? true
+ : (par5 == 4 && par1World.isBlockNormalCube(par2 + 1, par3, par4) ? true
+ : par5 == 5 && par1World.isBlockNormalCube(par2 - 1, par3, par4)))));
+ }
+
+ /**
+ * Checks to see if its valid to put this block at the specified coordinates.
+ * Args: world, x, y, z
+ */
+ public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4) {
+ return par1World
+ .isBlockNormalCube(par2 - 1, par3, par4)
+ ? true
+ : (par1World
+ .isBlockNormalCube(par2 + 1, par3, par4)
+ ? true
+ : (par1World.isBlockNormalCube(par2, par3, par4 - 1) ? true
+ : (par1World.isBlockNormalCube(par2, par3, par4 + 1) ? true
+ : (par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4)
+ ? true
+ : par1World.isBlockNormalCube(par2, par3 + 1, par4)))));
+ }
+
+ /**
+ * Called when a block is placed using its ItemBlock. Args: World, X, Y, Z,
+ * side, hitX, hitY, hitZ, block metadata
+ */
+ public int onBlockPlaced(World par1World, int par2, int par3, int par4, int par5, float par6, float par7,
+ float par8, int par9) {
+ int var11 = par9 & 8;
+ int var10 = par9 & 7;
+ byte var12 = -1;
+
+ if (par5 == 0 && par1World.isBlockNormalCube(par2, par3 + 1, par4)) {
+ var12 = 0;
+ }
+
+ if (par5 == 1 && par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4)) {
+ var12 = 5;
+ }
+
+ if (par5 == 2 && par1World.isBlockNormalCube(par2, par3, par4 + 1)) {
+ var12 = 4;
+ }
+
+ if (par5 == 3 && par1World.isBlockNormalCube(par2, par3, par4 - 1)) {
+ var12 = 3;
+ }
+
+ if (par5 == 4 && par1World.isBlockNormalCube(par2 + 1, par3, par4)) {
+ var12 = 2;
+ }
+
+ if (par5 == 5 && par1World.isBlockNormalCube(par2 - 1, par3, par4)) {
+ var12 = 1;
+ }
+
+ return var12 + var11;
+ }
+
+ /**
+ * Called when the block is placed in the world.
+ */
+ public void onBlockPlacedBy(World par1World, int par2, int par3, int par4, EntityLiving par5EntityLiving,
+ ItemStack par6ItemStack) {
+ int var7 = par1World.getBlockMetadata(par2, par3, par4);
+ int var8 = var7 & 7;
+ int var9 = var7 & 8;
+
+ if (var8 == invertMetadata(1)) {
+ if ((MathHelper.floor_double((double) (par5EntityLiving.rotationYaw * 4.0F / 360.0F) + 0.5D) & 1) == 0) {
+ par1World.setBlockMetadata(par2, par3, par4, 5 | var9, 2);
+ } else {
+ par1World.setBlockMetadata(par2, par3, par4, 6 | var9, 2);
+ }
+ } else if (var8 == invertMetadata(0)) {
+ if ((MathHelper.floor_double((double) (par5EntityLiving.rotationYaw * 4.0F / 360.0F) + 0.5D) & 1) == 0) {
+ par1World.setBlockMetadata(par2, par3, par4, 7 | var9, 2);
+ } else {
+ par1World.setBlockMetadata(par2, par3, par4, 0 | var9, 2);
+ }
+ }
+ }
+
+ /**
+ * only used in ComponentScatteredFeatureJunglePyramid.addComponentParts"
+ */
+ public static int invertMetadata(int par0) {
+ switch (par0) {
+ case 0:
+ return 0;
+
+ case 1:
+ return 5;
+
+ case 2:
+ return 4;
+
+ case 3:
+ return 3;
+
+ case 4:
+ return 2;
+
+ case 5:
+ return 1;
+
+ default:
+ return -1;
+ }
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ if (this.checkIfAttachedToBlock(par1World, par2, par3, par4)) {
+ int var6 = par1World.getBlockMetadata(par2, par3, par4) & 7;
+ boolean var7 = false;
+
+ if (!par1World.isBlockNormalCube(par2 - 1, par3, par4) && var6 == 1) {
+ var7 = true;
+ }
+
+ if (!par1World.isBlockNormalCube(par2 + 1, par3, par4) && var6 == 2) {
+ var7 = true;
+ }
+
+ if (!par1World.isBlockNormalCube(par2, par3, par4 - 1) && var6 == 3) {
+ var7 = true;
+ }
+
+ if (!par1World.isBlockNormalCube(par2, par3, par4 + 1) && var6 == 4) {
+ var7 = true;
+ }
+
+ if (!par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4) && var6 == 5) {
+ var7 = true;
+ }
+
+ if (!par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4) && var6 == 6) {
+ var7 = true;
+ }
+
+ if (!par1World.isBlockNormalCube(par2, par3 + 1, par4) && var6 == 0) {
+ var7 = true;
+ }
+
+ if (!par1World.isBlockNormalCube(par2, par3 + 1, par4) && var6 == 7) {
+ var7 = true;
+ }
+
+ if (var7) {
+ this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
+ par1World.setBlockToAir(par2, par3, par4);
+ }
+ }
+ }
+
+ /**
+ * Checks if the block is attached to another block. If it is not, it returns
+ * false and drops the block as an item. If it is it returns true.
+ */
+ private boolean checkIfAttachedToBlock(World par1World, int par2, int par3, int par4) {
+ if (!this.canPlaceBlockAt(par1World, par2, par3, par4)) {
+ this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
+ par1World.setBlockToAir(par2, par3, par4);
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * Updates the blocks bounds based on its current state. Args: world, x, y, z
+ */
+ public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ int var5 = par1IBlockAccess.getBlockMetadata(par2, par3, par4) & 7;
+ float var6 = 0.1875F;
+
+ if (var5 == 1) {
+ this.setBlockBounds(0.0F, 0.2F, 0.5F - var6, var6 * 2.0F, 0.8F, 0.5F + var6);
+ } else if (var5 == 2) {
+ this.setBlockBounds(1.0F - var6 * 2.0F, 0.2F, 0.5F - var6, 1.0F, 0.8F, 0.5F + var6);
+ } else if (var5 == 3) {
+ this.setBlockBounds(0.5F - var6, 0.2F, 0.0F, 0.5F + var6, 0.8F, var6 * 2.0F);
+ } else if (var5 == 4) {
+ this.setBlockBounds(0.5F - var6, 0.2F, 1.0F - var6 * 2.0F, 0.5F + var6, 0.8F, 1.0F);
+ } else if (var5 != 5 && var5 != 6) {
+ if (var5 == 0 || var5 == 7) {
+ var6 = 0.25F;
+ this.setBlockBounds(0.5F - var6, 0.4F, 0.5F - var6, 0.5F + var6, 1.0F, 0.5F + var6);
+ }
+ } else {
+ var6 = 0.25F;
+ this.setBlockBounds(0.5F - var6, 0.0F, 0.5F - var6, 0.5F + var6, 0.6F, 0.5F + var6);
+ }
+ }
+
+ /**
+ * Called upon block activation (right click on the block.)
+ */
+ public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer,
+ int par6, float par7, float par8, float par9) {
+ if (par1World.isRemote) {
+ return true;
+ } else {
+ int var10 = par1World.getBlockMetadata(par2, par3, par4);
+ int var11 = var10 & 7;
+ int var12 = 8 - (var10 & 8);
+ par1World.setBlockMetadata(par2, par3, par4, var11 + var12, 3);
+ par1World.playSoundEffect((double) par2 + 0.5D, (double) par3 + 0.5D, (double) par4 + 0.5D, "random.click",
+ 0.3F, var12 > 0 ? 0.6F : 0.5F);
+ par1World.notifyBlocksOfNeighborChange(par2, par3, par4, this.blockID);
+
+ if (var11 == 1) {
+ par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID);
+ } else if (var11 == 2) {
+ par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID);
+ } else if (var11 == 3) {
+ par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID);
+ } else if (var11 == 4) {
+ par1World.notifyBlocksOfNeighborChange(par2, par3, par4 + 1, this.blockID);
+ } else if (var11 != 5 && var11 != 6) {
+ if (var11 == 0 || var11 == 7) {
+ par1World.notifyBlocksOfNeighborChange(par2, par3 + 1, par4, this.blockID);
+ }
+ } else {
+ par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID);
+ }
+
+ return true;
+ }
+ }
+
+ /**
+ * ejects contained items into the world, and notifies neighbours of an update,
+ * as appropriate
+ */
+ public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) {
+ if ((par6 & 8) > 0) {
+ par1World.notifyBlocksOfNeighborChange(par2, par3, par4, this.blockID);
+ int var7 = par6 & 7;
+
+ if (var7 == 1) {
+ par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID);
+ } else if (var7 == 2) {
+ par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID);
+ } else if (var7 == 3) {
+ par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID);
+ } else if (var7 == 4) {
+ par1World.notifyBlocksOfNeighborChange(par2, par3, par4 + 1, this.blockID);
+ } else if (var7 != 5 && var7 != 6) {
+ if (var7 == 0 || var7 == 7) {
+ par1World.notifyBlocksOfNeighborChange(par2, par3 + 1, par4, this.blockID);
+ }
+ } else {
+ par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID);
+ }
+ }
+
+ super.breakBlock(par1World, par2, par3, par4, par5, par6);
+ }
+
+ /**
+ * Returns true if the block is emitting indirect/weak redstone power on the
+ * specified side. If isBlockNormalCube returns true, standard redstone
+ * propagation rules will apply instead and this will not be called. Args:
+ * World, X, Y, Z, side. Note that the side is reversed - eg it is 1 (up) when
+ * checking the bottom of the block.
+ */
+ public int isProvidingWeakPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) {
+ return (par1IBlockAccess.getBlockMetadata(par2, par3, par4) & 8) > 0 ? 15 : 0;
+ }
+
+ /**
+ * Returns true if the block is emitting direct/strong redstone power on the
+ * specified side. Args: World, X, Y, Z, side. Note that the side is reversed -
+ * eg it is 1 (up) when checking the bottom of the block.
+ */
+ public int isProvidingStrongPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) {
+ int var6 = par1IBlockAccess.getBlockMetadata(par2, par3, par4);
+
+ if ((var6 & 8) == 0) {
+ return 0;
+ } else {
+ int var7 = var6 & 7;
+ return var7 == 0 && par5 == 0 ? 15
+ : (var7 == 7 && par5 == 0 ? 15
+ : (var7 == 6 && par5 == 1 ? 15
+ : (var7 == 5 && par5 == 1 ? 15
+ : (var7 == 4 && par5 == 2 ? 15
+ : (var7 == 3 && par5 == 3 ? 15
+ : (var7 == 2 && par5 == 4 ? 15
+ : (var7 == 1 && par5 == 5 ? 15 : 0)))))));
+ }
+ }
+
+ /**
+ * Can this block provide power. Only wire currently seems to have this change
+ * based on its state.
+ */
+ public boolean canProvidePower() {
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockLilyPad.java b/sp-server/src/main/java/net/minecraft/src/BlockLilyPad.java
new file mode 100644
index 0000000..020903a
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockLilyPad.java
@@ -0,0 +1,61 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+public class BlockLilyPad extends BlockFlower {
+ protected BlockLilyPad(int par1) {
+ super(par1);
+ float var2 = 0.5F;
+ float var3 = 0.015625F;
+ this.setBlockBounds(0.5F - var2, 0.0F, 0.5F - var2, 0.5F + var2, var3, 0.5F + var2);
+ this.setCreativeTab(CreativeTabs.tabDecorations);
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 23;
+ }
+
+ /**
+ * Adds all intersecting collision boxes to a list. (Be sure to only add boxes
+ * to the list if they intersect the mask.) Parameters: World, X, Y, Z, mask,
+ * list, colliding entity
+ */
+ public void addCollisionBoxesToList(World par1World, int par2, int par3, int par4, AxisAlignedBB par5AxisAlignedBB,
+ List par6List, Entity par7Entity) {
+ if (par7Entity == null || !(par7Entity instanceof EntityBoat)) {
+ super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
+ }
+ }
+
+ /**
+ * Returns a bounding box from the pool of bounding boxes (this means this box
+ * can change after the pool has been cleared to be reused)
+ */
+ public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) {
+ return AxisAlignedBB.getAABBPool().getAABB((double) par2 + this.minX, (double) par3 + this.minY,
+ (double) par4 + this.minZ, (double) par2 + this.maxX, (double) par3 + this.maxY,
+ (double) par4 + this.maxZ);
+ }
+
+ /**
+ * Gets passed in the blockID of the block below and supposed to return true if
+ * its allowed to grow on the type of blockID passed in. Args: blockID
+ */
+ protected boolean canThisPlantGrowOnThisBlockID(int par1) {
+ return par1 == Block.waterStill.blockID;
+ }
+
+ /**
+ * Can this block stay at this position. Similar to canPlaceBlockAt except gets
+ * checked often with plants.
+ */
+ public boolean canBlockStay(World par1World, int par2, int par3, int par4) {
+ return par3 >= 0 && par3 < 256
+ ? par1World.getBlockMaterial(par2, par3 - 1, par4) == Material.water
+ && par1World.getBlockMetadata(par2, par3 - 1, par4) == 0
+ : false;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockLockedChest.java b/sp-server/src/main/java/net/minecraft/src/BlockLockedChest.java
new file mode 100644
index 0000000..7513527
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockLockedChest.java
@@ -0,0 +1,24 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockLockedChest extends Block {
+ protected BlockLockedChest(int par1) {
+ super(par1, Material.wood);
+ }
+
+ /**
+ * Checks to see if its valid to put this block at the specified coordinates.
+ * Args: world, x, y, z
+ */
+ public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4) {
+ return true;
+ }
+
+ /**
+ * Ticks the block if it's been scheduled
+ */
+ public void updateTick(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ par1World.setBlockToAir(par2, par3, par4);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockLog.java b/sp-server/src/main/java/net/minecraft/src/BlockLog.java
new file mode 100644
index 0000000..c8e8b0d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockLog.java
@@ -0,0 +1,114 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockLog extends Block {
+ /** The type of tree this log came from. */
+ public static final String[] woodType = new String[] { "oak", "spruce", "birch", "jungle" };
+ public static final String[] treeTextureTypes = new String[] { "tree_side", "tree_spruce", "tree_birch",
+ "tree_jungle" };
+
+ protected BlockLog(int par1) {
+ super(par1, Material.wood);
+ this.setCreativeTab(CreativeTabs.tabBlock);
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 31;
+ }
+
+ /**
+ * Returns the quantity of items to drop on block destruction.
+ */
+ public int quantityDropped(EaglercraftRandom par1Random) {
+ return 1;
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return Block.wood.blockID;
+ }
+
+ /**
+ * ejects contained items into the world, and notifies neighbours of an update,
+ * as appropriate
+ */
+ public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) {
+ byte var7 = 4;
+ int var8 = var7 + 1;
+
+ if (par1World.checkChunksExist(par2 - var8, par3 - var8, par4 - var8, par2 + var8, par3 + var8, par4 + var8)) {
+ for (int var9 = -var7; var9 <= var7; ++var9) {
+ for (int var10 = -var7; var10 <= var7; ++var10) {
+ for (int var11 = -var7; var11 <= var7; ++var11) {
+ int var12 = par1World.getBlockId(par2 + var9, par3 + var10, par4 + var11);
+
+ if (var12 == Block.leaves.blockID) {
+ int var13 = par1World.getBlockMetadata(par2 + var9, par3 + var10, par4 + var11);
+
+ if ((var13 & 8) == 0) {
+ par1World.setBlockMetadata(par2 + var9, par3 + var10, par4 + var11, var13 | 8, 4);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Called when a block is placed using its ItemBlock. Args: World, X, Y, Z,
+ * side, hitX, hitY, hitZ, block metadata
+ */
+ public int onBlockPlaced(World par1World, int par2, int par3, int par4, int par5, float par6, float par7,
+ float par8, int par9) {
+ int var10 = par9 & 3;
+ byte var11 = 0;
+
+ switch (par5) {
+ case 0:
+ case 1:
+ var11 = 0;
+ break;
+
+ case 2:
+ case 3:
+ var11 = 8;
+ break;
+
+ case 4:
+ case 5:
+ var11 = 4;
+ }
+
+ return var10 | var11;
+ }
+
+ /**
+ * Determines the damage on the item the block drops. Used in cloth and wood.
+ */
+ public int damageDropped(int par1) {
+ return par1 & 3;
+ }
+
+ /**
+ * returns a number between 0 and 3
+ */
+ public static int limitToValidMetadata(int par0) {
+ return par0 & 3;
+ }
+
+ /**
+ * Returns an item stack containing a single instance of the current block type.
+ * 'i' is the block's subtype/damage and is ignored for blocks which do not
+ * support subtypes. Blocks which cannot be harvested should return null.
+ */
+ protected ItemStack createStackedBlock(int par1) {
+ return new ItemStack(this.blockID, 1, limitToValidMetadata(par1));
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockMelon.java b/sp-server/src/main/java/net/minecraft/src/BlockMelon.java
new file mode 100644
index 0000000..2776102
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockMelon.java
@@ -0,0 +1,38 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockMelon extends Block {
+ protected BlockMelon(int par1) {
+ super(par1, Material.pumpkin);
+ this.setCreativeTab(CreativeTabs.tabBlock);
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return Item.melon.itemID;
+ }
+
+ /**
+ * Returns the quantity of items to drop on block destruction.
+ */
+ public int quantityDropped(EaglercraftRandom par1Random) {
+ return 3 + par1Random.nextInt(5);
+ }
+
+ /**
+ * Returns the usual quantity dropped by the block plus a bonus of 1 to 'i'
+ * (inclusive).
+ */
+ public int quantityDroppedWithBonus(int par1, EaglercraftRandom par2Random) {
+ int var3 = this.quantityDropped(par2Random) + par2Random.nextInt(1 + par1);
+
+ if (var3 > 9) {
+ var3 = 9;
+ }
+
+ return var3;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockMobSpawner.java b/sp-server/src/main/java/net/minecraft/src/BlockMobSpawner.java
new file mode 100644
index 0000000..b4e40f5
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockMobSpawner.java
@@ -0,0 +1,50 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockMobSpawner extends BlockContainer {
+ protected BlockMobSpawner(int par1) {
+ super(par1, Material.rock);
+ }
+
+ /**
+ * Returns a new instance of a block's tile entity class. Called on placing the
+ * block.
+ */
+ public TileEntity createNewTileEntity(World par1World) {
+ return new TileEntityMobSpawner();
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return 0;
+ }
+
+ /**
+ * Returns the quantity of items to drop on block destruction.
+ */
+ public int quantityDropped(EaglercraftRandom par1Random) {
+ return 0;
+ }
+
+ /**
+ * Drops the block items with a specified chance of dropping the specified items
+ */
+ public void dropBlockAsItemWithChance(World par1World, int par2, int par3, int par4, int par5, float par6,
+ int par7) {
+ super.dropBlockAsItemWithChance(par1World, par2, par3, par4, par5, par6, par7);
+ int var8 = 15 + par1World.rand.nextInt(15) + par1World.rand.nextInt(15);
+ this.dropXpOnBlockBreak(par1World, par2, par3, par4, var8);
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockMushroom.java b/sp-server/src/main/java/net/minecraft/src/BlockMushroom.java
new file mode 100644
index 0000000..4294cb2
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockMushroom.java
@@ -0,0 +1,114 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockMushroom extends BlockFlower {
+ private final String field_94374_a;
+
+ protected BlockMushroom(int par1, String par2Str) {
+ super(par1);
+ this.field_94374_a = par2Str;
+ float var3 = 0.2F;
+ this.setBlockBounds(0.5F - var3, 0.0F, 0.5F - var3, 0.5F + var3, var3 * 2.0F, 0.5F + var3);
+ this.setTickRandomly(true);
+ }
+
+ /**
+ * Ticks the block if it's been scheduled
+ */
+ public void updateTick(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ if (par5Random.nextInt(25) == 0) {
+ byte var6 = 4;
+ int var7 = 5;
+ int var8;
+ int var9;
+ int var10;
+
+ for (var8 = par2 - var6; var8 <= par2 + var6; ++var8) {
+ for (var9 = par4 - var6; var9 <= par4 + var6; ++var9) {
+ for (var10 = par3 - 1; var10 <= par3 + 1; ++var10) {
+ if (par1World.getBlockId(var8, var10, var9) == this.blockID) {
+ --var7;
+
+ if (var7 <= 0) {
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ var8 = par2 + par5Random.nextInt(3) - 1;
+ var9 = par3 + par5Random.nextInt(2) - par5Random.nextInt(2);
+ var10 = par4 + par5Random.nextInt(3) - 1;
+
+ for (int var11 = 0; var11 < 4; ++var11) {
+ if (par1World.isAirBlock(var8, var9, var10) && this.canBlockStay(par1World, var8, var9, var10)) {
+ par2 = var8;
+ par3 = var9;
+ par4 = var10;
+ }
+
+ var8 = par2 + par5Random.nextInt(3) - 1;
+ var9 = par3 + par5Random.nextInt(2) - par5Random.nextInt(2);
+ var10 = par4 + par5Random.nextInt(3) - 1;
+ }
+
+ if (par1World.isAirBlock(var8, var9, var10) && this.canBlockStay(par1World, var8, var9, var10)) {
+ par1World.setBlock(var8, var9, var10, this.blockID);
+ }
+ }
+ }
+
+ /**
+ * Checks to see if its valid to put this block at the specified coordinates.
+ * Args: world, x, y, z
+ */
+ public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4) {
+ return super.canPlaceBlockAt(par1World, par2, par3, par4) && this.canBlockStay(par1World, par2, par3, par4);
+ }
+
+ /**
+ * Gets passed in the blockID of the block below and supposed to return true if
+ * its allowed to grow on the type of blockID passed in. Args: blockID
+ */
+ protected boolean canThisPlantGrowOnThisBlockID(int par1) {
+ return Block.opaqueCubeLookup[par1];
+ }
+
+ /**
+ * Can this block stay at this position. Similar to canPlaceBlockAt except gets
+ * checked often with plants.
+ */
+ public boolean canBlockStay(World par1World, int par2, int par3, int par4) {
+ if (par3 >= 0 && par3 < 256) {
+ int var5 = par1World.getBlockId(par2, par3 - 1, par4);
+ return var5 == Block.mycelium.blockID || par1World.getFullBlockLightValue(par2, par3, par4) < 13
+ && this.canThisPlantGrowOnThisBlockID(var5);
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Fertilize the mushroom.
+ */
+ public boolean fertilizeMushroom(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ int var6 = par1World.getBlockMetadata(par2, par3, par4);
+ par1World.setBlockToAir(par2, par3, par4);
+ WorldGenBigMushroom var7 = null;
+
+ if (this.blockID == Block.mushroomBrown.blockID) {
+ var7 = new WorldGenBigMushroom(0);
+ } else if (this.blockID == Block.mushroomRed.blockID) {
+ var7 = new WorldGenBigMushroom(1);
+ }
+
+ if (var7 != null && var7.generate(par1World, par5Random, par2, par3, par4)) {
+ return true;
+ } else {
+ par1World.setBlock(par2, par3, par4, this.blockID, var6, 3);
+ return false;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockMushroomCap.java b/sp-server/src/main/java/net/minecraft/src/BlockMushroomCap.java
new file mode 100644
index 0000000..00fd2ca
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockMushroomCap.java
@@ -0,0 +1,35 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockMushroomCap extends Block {
+ private static final String[] field_94429_a = new String[] { "mushroom_skin_brown", "mushroom_skin_red" };
+
+ /** The mushroom type. 0 for brown, 1 for red. */
+ private final int mushroomType;
+
+ public BlockMushroomCap(int par1, Material par2Material, int par3) {
+ super(par1, par2Material);
+ this.mushroomType = par3;
+ }
+
+ /**
+ * Returns the quantity of items to drop on block destruction.
+ */
+ public int quantityDropped(EaglercraftRandom par1Random) {
+ int var2 = par1Random.nextInt(10) - 7;
+
+ if (var2 < 0) {
+ var2 = 0;
+ }
+
+ return var2;
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return Block.mushroomBrown.blockID + this.mushroomType;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockMycelium.java b/sp-server/src/main/java/net/minecraft/src/BlockMycelium.java
new file mode 100644
index 0000000..5fb35f8
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockMycelium.java
@@ -0,0 +1,43 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockMycelium extends Block {
+ protected BlockMycelium(int par1) {
+ super(par1, Material.grass);
+ this.setTickRandomly(true);
+ this.setCreativeTab(CreativeTabs.tabBlock);
+ }
+
+ /**
+ * Ticks the block if it's been scheduled
+ */
+ public void updateTick(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ if (!par1World.isRemote) {
+ if (par1World.getBlockLightValue(par2, par3 + 1, par4) < 4
+ && Block.lightOpacity[par1World.getBlockId(par2, par3 + 1, par4)] > 2) {
+ par1World.setBlock(par2, par3, par4, Block.dirt.blockID);
+ } else if (par1World.getBlockLightValue(par2, par3 + 1, par4) >= 9) {
+ for (int var6 = 0; var6 < 4; ++var6) {
+ int var7 = par2 + par5Random.nextInt(3) - 1;
+ int var8 = par3 + par5Random.nextInt(5) - 3;
+ int var9 = par4 + par5Random.nextInt(3) - 1;
+ int var10 = par1World.getBlockId(var7, var8 + 1, var9);
+
+ if (par1World.getBlockId(var7, var8, var9) == Block.dirt.blockID
+ && par1World.getBlockLightValue(var7, var8 + 1, var9) >= 4
+ && Block.lightOpacity[var10] <= 2) {
+ par1World.setBlock(var7, var8, var9, this.blockID);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return Block.dirt.idDropped(0, par2Random, par3);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockNetherStalk.java b/sp-server/src/main/java/net/minecraft/src/BlockNetherStalk.java
new file mode 100644
index 0000000..a4e506b
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockNetherStalk.java
@@ -0,0 +1,88 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockNetherStalk extends BlockFlower {
+ private static final String[] field_94373_a = new String[] { "netherStalk_0", "netherStalk_1", "netherStalk_2" };
+
+ protected BlockNetherStalk(int par1) {
+ super(par1);
+ this.setTickRandomly(true);
+ float var2 = 0.5F;
+ this.setBlockBounds(0.5F - var2, 0.0F, 0.5F - var2, 0.5F + var2, 0.25F, 0.5F + var2);
+ this.setCreativeTab((CreativeTabs) null);
+ }
+
+ /**
+ * Gets passed in the blockID of the block below and supposed to return true if
+ * its allowed to grow on the type of blockID passed in. Args: blockID
+ */
+ protected boolean canThisPlantGrowOnThisBlockID(int par1) {
+ return par1 == Block.slowSand.blockID;
+ }
+
+ /**
+ * Can this block stay at this position. Similar to canPlaceBlockAt except gets
+ * checked often with plants.
+ */
+ public boolean canBlockStay(World par1World, int par2, int par3, int par4) {
+ return this.canThisPlantGrowOnThisBlockID(par1World.getBlockId(par2, par3 - 1, par4));
+ }
+
+ /**
+ * Ticks the block if it's been scheduled
+ */
+ public void updateTick(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ int var6 = par1World.getBlockMetadata(par2, par3, par4);
+
+ if (var6 < 3 && par5Random.nextInt(10) == 0) {
+ ++var6;
+ par1World.setBlockMetadata(par2, par3, par4, var6, 2);
+ }
+
+ super.updateTick(par1World, par2, par3, par4, par5Random);
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 6;
+ }
+
+ /**
+ * Drops the block items with a specified chance of dropping the specified items
+ */
+ public void dropBlockAsItemWithChance(World par1World, int par2, int par3, int par4, int par5, float par6,
+ int par7) {
+ if (!par1World.isRemote) {
+ int var8 = 1;
+
+ if (par5 >= 3) {
+ var8 = 2 + par1World.rand.nextInt(3);
+
+ if (par7 > 0) {
+ var8 += par1World.rand.nextInt(par7 + 1);
+ }
+ }
+
+ for (int var9 = 0; var9 < var8; ++var9) {
+ this.dropBlockAsItem_do(par1World, par2, par3, par4, new ItemStack(Item.netherStalkSeeds));
+ }
+ }
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return 0;
+ }
+
+ /**
+ * Returns the quantity of items to drop on block destruction.
+ */
+ public int quantityDropped(EaglercraftRandom par1Random) {
+ return 0;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockNetherrack.java b/sp-server/src/main/java/net/minecraft/src/BlockNetherrack.java
new file mode 100644
index 0000000..f4df058
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockNetherrack.java
@@ -0,0 +1,8 @@
+package net.minecraft.src;
+
+public class BlockNetherrack extends Block {
+ public BlockNetherrack(int par1) {
+ super(par1, Material.rock);
+ this.setCreativeTab(CreativeTabs.tabBlock);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockNote.java b/sp-server/src/main/java/net/minecraft/src/BlockNote.java
new file mode 100644
index 0000000..ed38179
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockNote.java
@@ -0,0 +1,98 @@
+package net.minecraft.src;
+
+public class BlockNote extends BlockContainer {
+ public BlockNote(int par1) {
+ super(par1, Material.wood);
+ this.setCreativeTab(CreativeTabs.tabRedstone);
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ boolean var6 = par1World.isBlockIndirectlyGettingPowered(par2, par3, par4);
+ TileEntityNote var7 = (TileEntityNote) par1World.getBlockTileEntity(par2, par3, par4);
+
+ if (var7 != null && var7.previousRedstoneState != var6) {
+ if (var6) {
+ var7.triggerNote(par1World, par2, par3, par4);
+ }
+
+ var7.previousRedstoneState = var6;
+ }
+ }
+
+ /**
+ * Called upon block activation (right click on the block.)
+ */
+ public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer,
+ int par6, float par7, float par8, float par9) {
+ if (par1World.isRemote) {
+ return true;
+ } else {
+ TileEntityNote var10 = (TileEntityNote) par1World.getBlockTileEntity(par2, par3, par4);
+
+ if (var10 != null) {
+ var10.changePitch();
+ var10.triggerNote(par1World, par2, par3, par4);
+ }
+
+ return true;
+ }
+ }
+
+ /**
+ * Called when the block is clicked by a player. Args: x, y, z, entityPlayer
+ */
+ public void onBlockClicked(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer) {
+ if (!par1World.isRemote) {
+ TileEntityNote var6 = (TileEntityNote) par1World.getBlockTileEntity(par2, par3, par4);
+
+ if (var6 != null) {
+ var6.triggerNote(par1World, par2, par3, par4);
+ }
+ }
+ }
+
+ /**
+ * Returns a new instance of a block's tile entity class. Called on placing the
+ * block.
+ */
+ public TileEntity createNewTileEntity(World par1World) {
+ return new TileEntityNote();
+ }
+
+ /**
+ * Called when the block receives a BlockEvent - see World.addBlockEvent. By
+ * default, passes it on to the tile entity at this location. Args: world, x, y,
+ * z, blockID, EventID, event parameter
+ */
+ public boolean onBlockEventReceived(World par1World, int par2, int par3, int par4, int par5, int par6) {
+ float var7 = (float) Math.pow(2.0D, (double) (par6 - 12) / 12.0D);
+ String var8 = "harp";
+
+ if (par5 == 1) {
+ var8 = "bd";
+ }
+
+ if (par5 == 2) {
+ var8 = "snare";
+ }
+
+ if (par5 == 3) {
+ var8 = "hat";
+ }
+
+ if (par5 == 4) {
+ var8 = "bassattack";
+ }
+
+ par1World.playSoundEffect((double) par2 + 0.5D, (double) par3 + 0.5D, (double) par4 + 0.5D, "note." + var8,
+ 3.0F, var7);
+ par1World.spawnParticle("note", (double) par2 + 0.5D, (double) par3 + 1.2D, (double) par4 + 0.5D,
+ (double) par6 / 24.0D, 0.0D, 0.0D);
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockObsidian.java b/sp-server/src/main/java/net/minecraft/src/BlockObsidian.java
new file mode 100644
index 0000000..15aca0c
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockObsidian.java
@@ -0,0 +1,23 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockObsidian extends BlockStone {
+ public BlockObsidian(int par1) {
+ super(par1);
+ }
+
+ /**
+ * Returns the quantity of items to drop on block destruction.
+ */
+ public int quantityDropped(EaglercraftRandom par1Random) {
+ return 1;
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return Block.obsidian.blockID;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockOre.java b/sp-server/src/main/java/net/minecraft/src/BlockOre.java
new file mode 100644
index 0000000..a245b6c
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockOre.java
@@ -0,0 +1,80 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockOre extends Block {
+ public BlockOre(int par1) {
+ super(par1, Material.rock);
+ this.setCreativeTab(CreativeTabs.tabBlock);
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return this.blockID == Block.oreCoal.blockID ? Item.coal.itemID
+ : (this.blockID == Block.oreDiamond.blockID ? Item.diamond.itemID
+ : (this.blockID == Block.oreLapis.blockID ? Item.dyePowder.itemID
+ : (this.blockID == Block.oreEmerald.blockID ? Item.emerald.itemID
+ : (this.blockID == Block.oreNetherQuartz.blockID ? Item.netherQuartz.itemID
+ : this.blockID))));
+ }
+
+ /**
+ * Returns the quantity of items to drop on block destruction.
+ */
+ public int quantityDropped(EaglercraftRandom par1Random) {
+ return this.blockID == Block.oreLapis.blockID ? 4 + par1Random.nextInt(5) : 1;
+ }
+
+ /**
+ * Returns the usual quantity dropped by the block plus a bonus of 1 to 'i'
+ * (inclusive).
+ */
+ public int quantityDroppedWithBonus(int par1, EaglercraftRandom par2Random) {
+ if (par1 > 0 && this.blockID != this.idDropped(0, par2Random, par1)) {
+ int var3 = par2Random.nextInt(par1 + 2) - 1;
+
+ if (var3 < 0) {
+ var3 = 0;
+ }
+
+ return this.quantityDropped(par2Random) * (var3 + 1);
+ } else {
+ return this.quantityDropped(par2Random);
+ }
+ }
+
+ /**
+ * Drops the block items with a specified chance of dropping the specified items
+ */
+ public void dropBlockAsItemWithChance(World par1World, int par2, int par3, int par4, int par5, float par6,
+ int par7) {
+ super.dropBlockAsItemWithChance(par1World, par2, par3, par4, par5, par6, par7);
+
+ if (this.idDropped(par5, par1World.rand, par7) != this.blockID) {
+ int var8 = 0;
+
+ if (this.blockID == Block.oreCoal.blockID) {
+ var8 = MathHelper.getRandomIntegerInRange(par1World.rand, 0, 2);
+ } else if (this.blockID == Block.oreDiamond.blockID) {
+ var8 = MathHelper.getRandomIntegerInRange(par1World.rand, 3, 7);
+ } else if (this.blockID == Block.oreEmerald.blockID) {
+ var8 = MathHelper.getRandomIntegerInRange(par1World.rand, 3, 7);
+ } else if (this.blockID == Block.oreLapis.blockID) {
+ var8 = MathHelper.getRandomIntegerInRange(par1World.rand, 2, 5);
+ } else if (this.blockID == Block.oreNetherQuartz.blockID) {
+ var8 = MathHelper.getRandomIntegerInRange(par1World.rand, 2, 5);
+ }
+
+ this.dropXpOnBlockBreak(par1World, par2, par3, par4, var8);
+ }
+ }
+
+ /**
+ * Determines the damage on the item the block drops. Used in cloth and wood.
+ */
+ public int damageDropped(int par1) {
+ return this.blockID == Block.oreLapis.blockID ? 4 : 0;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockOreStorage.java b/sp-server/src/main/java/net/minecraft/src/BlockOreStorage.java
new file mode 100644
index 0000000..a9d647e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockOreStorage.java
@@ -0,0 +1,8 @@
+package net.minecraft.src;
+
+public class BlockOreStorage extends Block {
+ public BlockOreStorage(int par1) {
+ super(par1, Material.iron);
+ this.setCreativeTab(CreativeTabs.tabBlock);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockPane.java b/sp-server/src/main/java/net/minecraft/src/BlockPane.java
new file mode 100644
index 0000000..79e98a1
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockPane.java
@@ -0,0 +1,167 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockPane extends Block {
+ /**
+ * Holds the texture index of the side of the pane (the thin lateral side)
+ */
+ private final String sideTextureIndex;
+
+ /**
+ * If this field is true, the pane block drops itself when destroyed (like the
+ * iron fences), otherwise, it's just destroyed (like glass panes)
+ */
+ private final boolean canDropItself;
+ private final String field_94402_c;
+
+ protected BlockPane(int par1, String par2Str, String par3Str, Material par4Material, boolean par5) {
+ super(par1, par4Material);
+ this.sideTextureIndex = par3Str;
+ this.canDropItself = par5;
+ this.field_94402_c = par2Str;
+ this.setCreativeTab(CreativeTabs.tabDecorations);
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return !this.canDropItself ? 0 : super.idDropped(par1, par2Random, par3);
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 18;
+ }
+
+ /**
+ * Adds all intersecting collision boxes to a list. (Be sure to only add boxes
+ * to the list if they intersect the mask.) Parameters: World, X, Y, Z, mask,
+ * list, colliding entity
+ */
+ public void addCollisionBoxesToList(World par1World, int par2, int par3, int par4, AxisAlignedBB par5AxisAlignedBB,
+ List par6List, Entity par7Entity) {
+ boolean var8 = this.canThisPaneConnectToThisBlockID(par1World.getBlockId(par2, par3, par4 - 1));
+ boolean var9 = this.canThisPaneConnectToThisBlockID(par1World.getBlockId(par2, par3, par4 + 1));
+ boolean var10 = this.canThisPaneConnectToThisBlockID(par1World.getBlockId(par2 - 1, par3, par4));
+ boolean var11 = this.canThisPaneConnectToThisBlockID(par1World.getBlockId(par2 + 1, par3, par4));
+
+ if ((!var10 || !var11) && (var10 || var11 || var8 || var9)) {
+ if (var10 && !var11) {
+ this.setBlockBounds(0.0F, 0.0F, 0.4375F, 0.5F, 1.0F, 0.5625F);
+ super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
+ } else if (!var10 && var11) {
+ this.setBlockBounds(0.5F, 0.0F, 0.4375F, 1.0F, 1.0F, 0.5625F);
+ super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
+ }
+ } else {
+ this.setBlockBounds(0.0F, 0.0F, 0.4375F, 1.0F, 1.0F, 0.5625F);
+ super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
+ }
+
+ if ((!var8 || !var9) && (var10 || var11 || var8 || var9)) {
+ if (var8 && !var9) {
+ this.setBlockBounds(0.4375F, 0.0F, 0.0F, 0.5625F, 1.0F, 0.5F);
+ super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
+ } else if (!var8 && var9) {
+ this.setBlockBounds(0.4375F, 0.0F, 0.5F, 0.5625F, 1.0F, 1.0F);
+ super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
+ }
+ } else {
+ this.setBlockBounds(0.4375F, 0.0F, 0.0F, 0.5625F, 1.0F, 1.0F);
+ super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
+ }
+ }
+
+ /**
+ * Sets the block's bounds for rendering it as an item
+ */
+ public void setBlockBoundsForItemRender() {
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
+ }
+
+ /**
+ * Updates the blocks bounds based on its current state. Args: world, x, y, z
+ */
+ public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ float var5 = 0.4375F;
+ float var6 = 0.5625F;
+ float var7 = 0.4375F;
+ float var8 = 0.5625F;
+ boolean var9 = this.canThisPaneConnectToThisBlockID(par1IBlockAccess.getBlockId(par2, par3, par4 - 1));
+ boolean var10 = this.canThisPaneConnectToThisBlockID(par1IBlockAccess.getBlockId(par2, par3, par4 + 1));
+ boolean var11 = this.canThisPaneConnectToThisBlockID(par1IBlockAccess.getBlockId(par2 - 1, par3, par4));
+ boolean var12 = this.canThisPaneConnectToThisBlockID(par1IBlockAccess.getBlockId(par2 + 1, par3, par4));
+
+ if ((!var11 || !var12) && (var11 || var12 || var9 || var10)) {
+ if (var11 && !var12) {
+ var5 = 0.0F;
+ } else if (!var11 && var12) {
+ var6 = 1.0F;
+ }
+ } else {
+ var5 = 0.0F;
+ var6 = 1.0F;
+ }
+
+ if ((!var9 || !var10) && (var11 || var12 || var9 || var10)) {
+ if (var9 && !var10) {
+ var7 = 0.0F;
+ } else if (!var9 && var10) {
+ var8 = 1.0F;
+ }
+ } else {
+ var7 = 0.0F;
+ var8 = 1.0F;
+ }
+
+ this.setBlockBounds(var5, 0.0F, var7, var6, 1.0F, var8);
+ }
+
+ /**
+ * Gets passed in the blockID of the block adjacent and supposed to return true
+ * if its allowed to connect to the type of blockID passed in. Args: blockID
+ */
+ public final boolean canThisPaneConnectToThisBlockID(int par1) {
+ return Block.opaqueCubeLookup[par1] || par1 == this.blockID || par1 == Block.glass.blockID;
+ }
+
+ /**
+ * Return true if a player with Silk Touch can harvest this block directly, and
+ * not its normal drops.
+ */
+ protected boolean canSilkHarvest() {
+ return true;
+ }
+
+ /**
+ * Returns an item stack containing a single instance of the current block type.
+ * 'i' is the block's subtype/damage and is ignored for blocks which do not
+ * support subtypes. Blocks which cannot be harvested should return null.
+ */
+ protected ItemStack createStackedBlock(int par1) {
+ return new ItemStack(this.blockID, 1, par1);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockPistonBase.java b/sp-server/src/main/java/net/minecraft/src/BlockPistonBase.java
new file mode 100644
index 0000000..2d1b13d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockPistonBase.java
@@ -0,0 +1,492 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+public class BlockPistonBase extends Block {
+ /** This pistons is the sticky one? */
+ private final boolean isSticky;
+
+ public BlockPistonBase(int par1, boolean par2) {
+ super(par1, Material.piston);
+ this.isSticky = par2;
+ this.setStepSound(soundStoneFootstep);
+ this.setHardness(0.5F);
+ this.setCreativeTab(CreativeTabs.tabRedstone);
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 16;
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * Called upon block activation (right click on the block.)
+ */
+ public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer,
+ int par6, float par7, float par8, float par9) {
+ return false;
+ }
+
+ /**
+ * Called when the block is placed in the world.
+ */
+ public void onBlockPlacedBy(World par1World, int par2, int par3, int par4, EntityLiving par5EntityLiving,
+ ItemStack par6ItemStack) {
+ int var7 = determineOrientation(par1World, par2, par3, par4, par5EntityLiving);
+ par1World.setBlockMetadata(par2, par3, par4, var7, 2);
+
+ if (!par1World.isRemote) {
+ this.updatePistonState(par1World, par2, par3, par4);
+ }
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ if (!par1World.isRemote) {
+ this.updatePistonState(par1World, par2, par3, par4);
+ }
+ }
+
+ /**
+ * Called whenever the block is added into the world. Args: world, x, y, z
+ */
+ public void onBlockAdded(World par1World, int par2, int par3, int par4) {
+ if (!par1World.isRemote && par1World.getBlockTileEntity(par2, par3, par4) == null) {
+ this.updatePistonState(par1World, par2, par3, par4);
+ }
+ }
+
+ /**
+ * handles attempts to extend or retract the piston.
+ */
+ private void updatePistonState(World par1World, int par2, int par3, int par4) {
+ int var5 = par1World.getBlockMetadata(par2, par3, par4);
+ int var6 = getOrientation(var5);
+
+ if (var6 != 7) {
+ boolean var7 = this.isIndirectlyPowered(par1World, par2, par3, par4, var6);
+
+ if (var7 && !isExtended(var5)) {
+ if (canExtend(par1World, par2, par3, par4, var6)) {
+ par1World.addBlockEvent(par2, par3, par4, this.blockID, 0, var6);
+ }
+ } else if (!var7 && isExtended(var5)) {
+ par1World.setBlockMetadata(par2, par3, par4, var6, 2);
+ par1World.addBlockEvent(par2, par3, par4, this.blockID, 1, var6);
+ }
+ }
+ }
+
+ /**
+ * checks the block to that side to see if it is indirectly powered.
+ */
+ private boolean isIndirectlyPowered(World par1World, int par2, int par3, int par4, int par5) {
+ return par5 != 0 && par1World.getIndirectPowerOutput(par2, par3 - 1, par4, 0) ? true
+ : (par5 != 1 && par1World.getIndirectPowerOutput(par2, par3 + 1, par4, 1) ? true
+ : (par5 != 2 && par1World.getIndirectPowerOutput(par2, par3, par4 - 1, 2) ? true
+ : (par5 != 3 && par1World.getIndirectPowerOutput(par2, par3, par4 + 1, 3) ? true
+ : (par5 != 5 && par1World.getIndirectPowerOutput(par2 + 1, par3, par4, 5) ? true
+ : (par5 != 4
+ && par1World.getIndirectPowerOutput(par2 - 1, par3, par4, 4)
+ ? true
+ : (par1World.getIndirectPowerOutput(par2, par3, par4, 0)
+ ? true
+ : (par1World.getIndirectPowerOutput(par2,
+ par3 + 2, par4, 1)
+ ? true
+ : (par1World
+ .getIndirectPowerOutput(
+ par2, par3 + 1,
+ par4 - 1, 2)
+ ? true
+ : (par1World
+ .getIndirectPowerOutput(
+ par2,
+ par3 + 1,
+ par4 + 1,
+ 3) ? true
+ : (par1World
+ .getIndirectPowerOutput(
+ par2 - 1,
+ par3 + 1,
+ par4,
+ 4) ? true
+ : par1World
+ .getIndirectPowerOutput(
+ par2 + 1,
+ par3 + 1,
+ par4,
+ 5)))))))))));
+ }
+
+ /**
+ * Called when the block receives a BlockEvent - see World.addBlockEvent. By
+ * default, passes it on to the tile entity at this location. Args: world, x, y,
+ * z, blockID, EventID, event parameter
+ */
+ public boolean onBlockEventReceived(World par1World, int par2, int par3, int par4, int par5, int par6) {
+ if (!par1World.isRemote) {
+ boolean var7 = this.isIndirectlyPowered(par1World, par2, par3, par4, par6);
+
+ if (var7 && par5 == 1) {
+ par1World.setBlockMetadata(par2, par3, par4, par6 | 8, 2);
+ return false;
+ }
+
+ if (!var7 && par5 == 0) {
+ return false;
+ }
+ }
+
+ if (par5 == 0) {
+ if (!this.tryExtend(par1World, par2, par3, par4, par6)) {
+ return false;
+ }
+
+ par1World.setBlockMetadata(par2, par3, par4, par6 | 8, 2);
+ par1World.playSoundEffect((double) par2 + 0.5D, (double) par3 + 0.5D, (double) par4 + 0.5D,
+ "tile.piston.out", 0.5F, par1World.rand.nextFloat() * 0.25F + 0.6F);
+ } else if (par5 == 1) {
+ TileEntity var16 = par1World.getBlockTileEntity(par2 + Facing.offsetsXForSide[par6],
+ par3 + Facing.offsetsYForSide[par6], par4 + Facing.offsetsZForSide[par6]);
+
+ if (var16 instanceof TileEntityPiston) {
+ ((TileEntityPiston) var16).clearPistonTileEntity();
+ }
+
+ par1World.setBlock(par2, par3, par4, Block.pistonMoving.blockID, par6, 3);
+ par1World.setBlockTileEntity(par2, par3, par4,
+ BlockPistonMoving.getTileEntity(this.blockID, par6, par6, false, true));
+
+ if (this.isSticky) {
+ int var8 = par2 + Facing.offsetsXForSide[par6] * 2;
+ int var9 = par3 + Facing.offsetsYForSide[par6] * 2;
+ int var10 = par4 + Facing.offsetsZForSide[par6] * 2;
+ int var11 = par1World.getBlockId(var8, var9, var10);
+ int var12 = par1World.getBlockMetadata(var8, var9, var10);
+ boolean var13 = false;
+
+ if (var11 == Block.pistonMoving.blockID) {
+ TileEntity var14 = par1World.getBlockTileEntity(var8, var9, var10);
+
+ if (var14 instanceof TileEntityPiston) {
+ TileEntityPiston var15 = (TileEntityPiston) var14;
+
+ if (var15.getPistonOrientation() == par6 && var15.isExtending()) {
+ var15.clearPistonTileEntity();
+ var11 = var15.getStoredBlockID();
+ var12 = var15.getBlockMetadata();
+ var13 = true;
+ }
+ }
+ }
+
+ if (!var13 && var11 > 0 && canPushBlock(var11, par1World, var8, var9, var10, false)
+ && (Block.blocksList[var11].getMobilityFlag() == 0 || var11 == Block.pistonBase.blockID
+ || var11 == Block.pistonStickyBase.blockID)) {
+ par2 += Facing.offsetsXForSide[par6];
+ par3 += Facing.offsetsYForSide[par6];
+ par4 += Facing.offsetsZForSide[par6];
+ par1World.setBlock(par2, par3, par4, Block.pistonMoving.blockID, var12, 3);
+ par1World.setBlockTileEntity(par2, par3, par4,
+ BlockPistonMoving.getTileEntity(var11, var12, par6, false, false));
+ par1World.setBlockToAir(var8, var9, var10);
+ } else if (!var13) {
+ par1World.setBlockToAir(par2 + Facing.offsetsXForSide[par6], par3 + Facing.offsetsYForSide[par6],
+ par4 + Facing.offsetsZForSide[par6]);
+ }
+ } else {
+ par1World.setBlockToAir(par2 + Facing.offsetsXForSide[par6], par3 + Facing.offsetsYForSide[par6],
+ par4 + Facing.offsetsZForSide[par6]);
+ }
+
+ par1World.playSoundEffect((double) par2 + 0.5D, (double) par3 + 0.5D, (double) par4 + 0.5D,
+ "tile.piston.in", 0.5F, par1World.rand.nextFloat() * 0.15F + 0.6F);
+ }
+
+ return true;
+ }
+
+ /**
+ * Updates the blocks bounds based on its current state. Args: world, x, y, z
+ */
+ public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ int var5 = par1IBlockAccess.getBlockMetadata(par2, par3, par4);
+
+ if (isExtended(var5)) {
+ switch (getOrientation(var5)) {
+ case 0:
+ this.setBlockBounds(0.0F, 0.25F, 0.0F, 1.0F, 1.0F, 1.0F);
+ break;
+
+ case 1:
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.75F, 1.0F);
+ break;
+
+ case 2:
+ this.setBlockBounds(0.0F, 0.0F, 0.25F, 1.0F, 1.0F, 1.0F);
+ break;
+
+ case 3:
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 0.75F);
+ break;
+
+ case 4:
+ this.setBlockBounds(0.25F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
+ break;
+
+ case 5:
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 0.75F, 1.0F, 1.0F);
+ }
+ } else {
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
+ }
+ }
+
+ /**
+ * Sets the block's bounds for rendering it as an item
+ */
+ public void setBlockBoundsForItemRender() {
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
+ }
+
+ /**
+ * Adds all intersecting collision boxes to a list. (Be sure to only add boxes
+ * to the list if they intersect the mask.) Parameters: World, X, Y, Z, mask,
+ * list, colliding entity
+ */
+ public void addCollisionBoxesToList(World par1World, int par2, int par3, int par4, AxisAlignedBB par5AxisAlignedBB,
+ List par6List, Entity par7Entity) {
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
+ super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
+ }
+
+ /**
+ * Returns a bounding box from the pool of bounding boxes (this means this box
+ * can change after the pool has been cleared to be reused)
+ */
+ public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) {
+ this.setBlockBoundsBasedOnState(par1World, par2, par3, par4);
+ return super.getCollisionBoundingBoxFromPool(par1World, par2, par3, par4);
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ /**
+ * returns an int which describes the direction the piston faces
+ */
+ public static int getOrientation(int par0) {
+ return par0 & 7;
+ }
+
+ /**
+ * Determine if the metadata is related to something powered.
+ */
+ public static boolean isExtended(int par0) {
+ return (par0 & 8) != 0;
+ }
+
+ /**
+ * gets the way this piston should face for that entity that placed it.
+ */
+ public static int determineOrientation(World par0World, int par1, int par2, int par3,
+ EntityLiving par4EntityLiving) {
+ if (MathHelper.abs((float) par4EntityLiving.posX - (float) par1) < 2.0F
+ && MathHelper.abs((float) par4EntityLiving.posZ - (float) par3) < 2.0F) {
+ double var5 = par4EntityLiving.posY + 1.82D - (double) par4EntityLiving.yOffset;
+
+ if (var5 - (double) par2 > 2.0D) {
+ return 1;
+ }
+
+ if ((double) par2 - var5 > 0.0D) {
+ return 0;
+ }
+ }
+
+ int var7 = MathHelper.floor_double((double) (par4EntityLiving.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3;
+ return var7 == 0 ? 2 : (var7 == 1 ? 5 : (var7 == 2 ? 3 : (var7 == 3 ? 4 : 0)));
+ }
+
+ /**
+ * returns true if the piston can push the specified block
+ */
+ private static boolean canPushBlock(int par0, World par1World, int par2, int par3, int par4, boolean par5) {
+ if (par0 == Block.obsidian.blockID) {
+ return false;
+ } else {
+ if (par0 != Block.pistonBase.blockID && par0 != Block.pistonStickyBase.blockID) {
+ if (Block.blocksList[par0].getBlockHardness(par1World, par2, par3, par4) == -1.0F) {
+ return false;
+ }
+
+ if (Block.blocksList[par0].getMobilityFlag() == 2) {
+ return false;
+ }
+
+ if (Block.blocksList[par0].getMobilityFlag() == 1) {
+ if (!par5) {
+ return false;
+ }
+
+ return true;
+ }
+ } else if (isExtended(par1World.getBlockMetadata(par2, par3, par4))) {
+ return false;
+ }
+
+ return !(Block.blocksList[par0] instanceof ITileEntityProvider);
+ }
+ }
+
+ /**
+ * checks to see if this piston could push the blocks in front of it.
+ */
+ private static boolean canExtend(World par0World, int par1, int par2, int par3, int par4) {
+ int var5 = par1 + Facing.offsetsXForSide[par4];
+ int var6 = par2 + Facing.offsetsYForSide[par4];
+ int var7 = par3 + Facing.offsetsZForSide[par4];
+ int var8 = 0;
+
+ while (true) {
+ if (var8 < 13) {
+ if (var6 <= 0 || var6 >= 255) {
+ return false;
+ }
+
+ int var9 = par0World.getBlockId(var5, var6, var7);
+
+ if (var9 != 0) {
+ if (!canPushBlock(var9, par0World, var5, var6, var7, true)) {
+ return false;
+ }
+
+ if (Block.blocksList[var9].getMobilityFlag() != 1) {
+ if (var8 == 12) {
+ return false;
+ }
+
+ var5 += Facing.offsetsXForSide[par4];
+ var6 += Facing.offsetsYForSide[par4];
+ var7 += Facing.offsetsZForSide[par4];
+ ++var8;
+ continue;
+ }
+ }
+ }
+
+ return true;
+ }
+ }
+
+ /**
+ * attempts to extend the piston. returns false if impossible.
+ */
+ private boolean tryExtend(World par1World, int par2, int par3, int par4, int par5) {
+ int var6 = par2 + Facing.offsetsXForSide[par5];
+ int var7 = par3 + Facing.offsetsYForSide[par5];
+ int var8 = par4 + Facing.offsetsZForSide[par5];
+ int var9 = 0;
+
+ while (true) {
+ int var10;
+
+ if (var9 < 13) {
+ if (var7 <= 0 || var7 >= 255) {
+ return false;
+ }
+
+ var10 = par1World.getBlockId(var6, var7, var8);
+
+ if (var10 != 0) {
+ if (!canPushBlock(var10, par1World, var6, var7, var8, true)) {
+ return false;
+ }
+
+ if (Block.blocksList[var10].getMobilityFlag() != 1) {
+ if (var9 == 12) {
+ return false;
+ }
+
+ var6 += Facing.offsetsXForSide[par5];
+ var7 += Facing.offsetsYForSide[par5];
+ var8 += Facing.offsetsZForSide[par5];
+ ++var9;
+ continue;
+ }
+
+ Block.blocksList[var10].dropBlockAsItem(par1World, var6, var7, var8,
+ par1World.getBlockMetadata(var6, var7, var8), 0);
+ par1World.setBlockToAir(var6, var7, var8);
+ }
+ }
+
+ var9 = var6;
+ var10 = var7;
+ int var11 = var8;
+ int var12 = 0;
+ int[] var13;
+ int var14;
+ int var15;
+ int var16;
+
+ for (var13 = new int[13]; var6 != par2 || var7 != par3 || var8 != par4; var8 = var16) {
+ var14 = var6 - Facing.offsetsXForSide[par5];
+ var15 = var7 - Facing.offsetsYForSide[par5];
+ var16 = var8 - Facing.offsetsZForSide[par5];
+ int var17 = par1World.getBlockId(var14, var15, var16);
+ int var18 = par1World.getBlockMetadata(var14, var15, var16);
+
+ if (var17 == this.blockID && var14 == par2 && var15 == par3 && var16 == par4) {
+ par1World.setBlock(var6, var7, var8, Block.pistonMoving.blockID, par5 | (this.isSticky ? 8 : 0), 4);
+ par1World.setBlockTileEntity(var6, var7, var8, BlockPistonMoving.getTileEntity(
+ Block.pistonExtension.blockID, par5 | (this.isSticky ? 8 : 0), par5, true, false));
+ } else {
+ par1World.setBlock(var6, var7, var8, Block.pistonMoving.blockID, var18, 4);
+ par1World.setBlockTileEntity(var6, var7, var8,
+ BlockPistonMoving.getTileEntity(var17, var18, par5, true, false));
+ }
+
+ var13[var12++] = var17;
+ var6 = var14;
+ var7 = var15;
+ }
+
+ var6 = var9;
+ var7 = var10;
+ var8 = var11;
+
+ for (var12 = 0; var6 != par2 || var7 != par3 || var8 != par4; var8 = var16) {
+ var14 = var6 - Facing.offsetsXForSide[par5];
+ var15 = var7 - Facing.offsetsYForSide[par5];
+ var16 = var8 - Facing.offsetsZForSide[par5];
+ par1World.notifyBlocksOfNeighborChange(var14, var15, var16, var13[var12++]);
+ var6 = var14;
+ var7 = var15;
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockPistonExtension.java b/sp-server/src/main/java/net/minecraft/src/BlockPistonExtension.java
new file mode 100644
index 0000000..1c7f7b3
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockPistonExtension.java
@@ -0,0 +1,194 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockPistonExtension extends Block {
+ /** The texture for the 'head' of the piston. Sticky or normal. */
+ private Icon headTexture = null;
+
+ public BlockPistonExtension(int par1) {
+ super(par1, Material.piston);
+ this.setStepSound(soundStoneFootstep);
+ this.setHardness(0.5F);
+ }
+
+ /**
+ * ejects contained items into the world, and notifies neighbours of an update,
+ * as appropriate
+ */
+ public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) {
+ super.breakBlock(par1World, par2, par3, par4, par5, par6);
+ int var7 = Facing.oppositeSide[getDirectionMeta(par6)];
+ par2 += Facing.offsetsXForSide[var7];
+ par3 += Facing.offsetsYForSide[var7];
+ par4 += Facing.offsetsZForSide[var7];
+ int var8 = par1World.getBlockId(par2, par3, par4);
+
+ if (var8 == Block.pistonBase.blockID || var8 == Block.pistonStickyBase.blockID) {
+ par6 = par1World.getBlockMetadata(par2, par3, par4);
+
+ if (BlockPistonBase.isExtended(par6)) {
+ Block.blocksList[var8].dropBlockAsItem(par1World, par2, par3, par4, par6, 0);
+ par1World.setBlockToAir(par2, par3, par4);
+ }
+ }
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 17;
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ /**
+ * Checks to see if its valid to put this block at the specified coordinates.
+ * Args: world, x, y, z
+ */
+ public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4) {
+ return false;
+ }
+
+ /**
+ * checks to see if you can place this block can be placed on that side of a
+ * block: BlockLever overrides
+ */
+ public boolean canPlaceBlockOnSide(World par1World, int par2, int par3, int par4, int par5) {
+ return false;
+ }
+
+ /**
+ * Returns the quantity of items to drop on block destruction.
+ */
+ public int quantityDropped(EaglercraftRandom par1Random) {
+ return 0;
+ }
+
+ /**
+ * Adds all intersecting collision boxes to a list. (Be sure to only add boxes
+ * to the list if they intersect the mask.) Parameters: World, X, Y, Z, mask,
+ * list, colliding entity
+ */
+ public void addCollisionBoxesToList(World par1World, int par2, int par3, int par4, AxisAlignedBB par5AxisAlignedBB,
+ List par6List, Entity par7Entity) {
+ int var8 = par1World.getBlockMetadata(par2, par3, par4);
+
+ switch (getDirectionMeta(var8)) {
+ case 0:
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.25F, 1.0F);
+ super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
+ this.setBlockBounds(0.375F, 0.25F, 0.375F, 0.625F, 1.0F, 0.625F);
+ super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
+ break;
+
+ case 1:
+ this.setBlockBounds(0.0F, 0.75F, 0.0F, 1.0F, 1.0F, 1.0F);
+ super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
+ this.setBlockBounds(0.375F, 0.0F, 0.375F, 0.625F, 0.75F, 0.625F);
+ super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
+ break;
+
+ case 2:
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 0.25F);
+ super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
+ this.setBlockBounds(0.25F, 0.375F, 0.25F, 0.75F, 0.625F, 1.0F);
+ super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
+ break;
+
+ case 3:
+ this.setBlockBounds(0.0F, 0.0F, 0.75F, 1.0F, 1.0F, 1.0F);
+ super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
+ this.setBlockBounds(0.25F, 0.375F, 0.0F, 0.75F, 0.625F, 0.75F);
+ super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
+ break;
+
+ case 4:
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 0.25F, 1.0F, 1.0F);
+ super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
+ this.setBlockBounds(0.375F, 0.25F, 0.25F, 0.625F, 0.75F, 1.0F);
+ super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
+ break;
+
+ case 5:
+ this.setBlockBounds(0.75F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
+ super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
+ this.setBlockBounds(0.0F, 0.375F, 0.25F, 0.75F, 0.625F, 0.75F);
+ super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
+ }
+
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
+ }
+
+ /**
+ * Updates the blocks bounds based on its current state. Args: world, x, y, z
+ */
+ public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ int var5 = par1IBlockAccess.getBlockMetadata(par2, par3, par4);
+
+ switch (getDirectionMeta(var5)) {
+ case 0:
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.25F, 1.0F);
+ break;
+
+ case 1:
+ this.setBlockBounds(0.0F, 0.75F, 0.0F, 1.0F, 1.0F, 1.0F);
+ break;
+
+ case 2:
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 0.25F);
+ break;
+
+ case 3:
+ this.setBlockBounds(0.0F, 0.0F, 0.75F, 1.0F, 1.0F, 1.0F);
+ break;
+
+ case 4:
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 0.25F, 1.0F, 1.0F);
+ break;
+
+ case 5:
+ this.setBlockBounds(0.75F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
+ }
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ int var6 = getDirectionMeta(par1World.getBlockMetadata(par2, par3, par4));
+ int var7 = par1World.getBlockId(par2 - Facing.offsetsXForSide[var6], par3 - Facing.offsetsYForSide[var6],
+ par4 - Facing.offsetsZForSide[var6]);
+
+ if (var7 != Block.pistonBase.blockID && var7 != Block.pistonStickyBase.blockID) {
+ par1World.setBlockToAir(par2, par3, par4);
+ } else {
+ Block.blocksList[var7].onNeighborBlockChange(par1World, par2 - Facing.offsetsXForSide[var6],
+ par3 - Facing.offsetsYForSide[var6], par4 - Facing.offsetsZForSide[var6], par5);
+ }
+ }
+
+ public static int getDirectionMeta(int par0) {
+ return par0 & 7;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockPistonMoving.java b/sp-server/src/main/java/net/minecraft/src/BlockPistonMoving.java
new file mode 100644
index 0000000..0572a61
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockPistonMoving.java
@@ -0,0 +1,223 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockPistonMoving extends BlockContainer {
+ public BlockPistonMoving(int par1) {
+ super(par1, Material.piston);
+ this.setHardness(-1.0F);
+ }
+
+ /**
+ * Returns a new instance of a block's tile entity class. Called on placing the
+ * block.
+ */
+ public TileEntity createNewTileEntity(World par1World) {
+ return null;
+ }
+
+ /**
+ * Called whenever the block is added into the world. Args: world, x, y, z
+ */
+ public void onBlockAdded(World par1World, int par2, int par3, int par4) {
+ }
+
+ /**
+ * ejects contained items into the world, and notifies neighbours of an update,
+ * as appropriate
+ */
+ public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) {
+ TileEntity var7 = par1World.getBlockTileEntity(par2, par3, par4);
+
+ if (var7 instanceof TileEntityPiston) {
+ ((TileEntityPiston) var7).clearPistonTileEntity();
+ } else {
+ super.breakBlock(par1World, par2, par3, par4, par5, par6);
+ }
+ }
+
+ /**
+ * Checks to see if its valid to put this block at the specified coordinates.
+ * Args: world, x, y, z
+ */
+ public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4) {
+ return false;
+ }
+
+ /**
+ * checks to see if you can place this block can be placed on that side of a
+ * block: BlockLever overrides
+ */
+ public boolean canPlaceBlockOnSide(World par1World, int par2, int par3, int par4, int par5) {
+ return false;
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return -1;
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ /**
+ * Called upon block activation (right click on the block.)
+ */
+ public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer,
+ int par6, float par7, float par8, float par9) {
+ if (!par1World.isRemote && par1World.getBlockTileEntity(par2, par3, par4) == null) {
+ par1World.setBlockToAir(par2, par3, par4);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return 0;
+ }
+
+ /**
+ * Drops the block items with a specified chance of dropping the specified items
+ */
+ public void dropBlockAsItemWithChance(World par1World, int par2, int par3, int par4, int par5, float par6,
+ int par7) {
+ if (!par1World.isRemote) {
+ TileEntityPiston var8 = this.getTileEntityAtLocation(par1World, par2, par3, par4);
+
+ if (var8 != null) {
+ Block.blocksList[var8.getStoredBlockID()].dropBlockAsItem(par1World, par2, par3, par4,
+ var8.getBlockMetadata(), 0);
+ }
+ }
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ if (!par1World.isRemote && par1World.getBlockTileEntity(par2, par3, par4) == null) {
+ ;
+ }
+ }
+
+ /**
+ * gets a new TileEntityPiston created with the arguments provided.
+ */
+ public static TileEntity getTileEntity(int par0, int par1, int par2, boolean par3, boolean par4) {
+ return new TileEntityPiston(par0, par1, par2, par3, par4);
+ }
+
+ /**
+ * Returns a bounding box from the pool of bounding boxes (this means this box
+ * can change after the pool has been cleared to be reused)
+ */
+ public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) {
+ TileEntityPiston var5 = this.getTileEntityAtLocation(par1World, par2, par3, par4);
+
+ if (var5 == null) {
+ return null;
+ } else {
+ float var6 = var5.getProgress(0.0F);
+
+ if (var5.isExtending()) {
+ var6 = 1.0F - var6;
+ }
+
+ return this.getAxisAlignedBB(par1World, par2, par3, par4, var5.getStoredBlockID(), var6,
+ var5.getPistonOrientation());
+ }
+ }
+
+ /**
+ * Updates the blocks bounds based on its current state. Args: world, x, y, z
+ */
+ public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ TileEntityPiston var5 = this.getTileEntityAtLocation(par1IBlockAccess, par2, par3, par4);
+
+ if (var5 != null) {
+ Block var6 = Block.blocksList[var5.getStoredBlockID()];
+
+ if (var6 == null || var6 == this) {
+ return;
+ }
+
+ var6.setBlockBoundsBasedOnState(par1IBlockAccess, par2, par3, par4);
+ float var7 = var5.getProgress(0.0F);
+
+ if (var5.isExtending()) {
+ var7 = 1.0F - var7;
+ }
+
+ int var8 = var5.getPistonOrientation();
+ this.minX = var6.getMinX() - (double) ((float) Facing.offsetsXForSide[var8] * var7);
+ this.minY = var6.getBlockBoundsMinY() - (double) ((float) Facing.offsetsYForSide[var8] * var7);
+ this.minZ = var6.getBlockBoundsMinZ() - (double) ((float) Facing.offsetsZForSide[var8] * var7);
+ this.maxX = var6.getBlockBoundsMaxX() - (double) ((float) Facing.offsetsXForSide[var8] * var7);
+ this.maxY = var6.getBlockBoundsMaxY() - (double) ((float) Facing.offsetsYForSide[var8] * var7);
+ this.maxZ = var6.getBlockBoundsMaxZ() - (double) ((float) Facing.offsetsZForSide[var8] * var7);
+ }
+ }
+
+ public AxisAlignedBB getAxisAlignedBB(World par1World, int par2, int par3, int par4, int par5, float par6,
+ int par7) {
+ if (par5 != 0 && par5 != this.blockID) {
+ AxisAlignedBB var8 = Block.blocksList[par5].getCollisionBoundingBoxFromPool(par1World, par2, par3, par4);
+
+ if (var8 == null) {
+ return null;
+ } else {
+ if (Facing.offsetsXForSide[par7] < 0) {
+ var8.minX -= (double) ((float) Facing.offsetsXForSide[par7] * par6);
+ } else {
+ var8.maxX -= (double) ((float) Facing.offsetsXForSide[par7] * par6);
+ }
+
+ if (Facing.offsetsYForSide[par7] < 0) {
+ var8.minY -= (double) ((float) Facing.offsetsYForSide[par7] * par6);
+ } else {
+ var8.maxY -= (double) ((float) Facing.offsetsYForSide[par7] * par6);
+ }
+
+ if (Facing.offsetsZForSide[par7] < 0) {
+ var8.minZ -= (double) ((float) Facing.offsetsZForSide[par7] * par6);
+ } else {
+ var8.maxZ -= (double) ((float) Facing.offsetsZForSide[par7] * par6);
+ }
+
+ return var8;
+ }
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * gets the piston tile entity at the specified location
+ */
+ private TileEntityPiston getTileEntityAtLocation(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ TileEntity var5 = par1IBlockAccess.getBlockTileEntity(par2, par3, par4);
+ return var5 instanceof TileEntityPiston ? (TileEntityPiston) var5 : null;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockPortal.java b/sp-server/src/main/java/net/minecraft/src/BlockPortal.java
new file mode 100644
index 0000000..906e559
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockPortal.java
@@ -0,0 +1,204 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockPortal extends BlockBreakable {
+ public BlockPortal(int par1) {
+ super(par1, "portal", Material.portal, false);
+ this.setTickRandomly(true);
+ }
+
+ /**
+ * Ticks the block if it's been scheduled
+ */
+ public void updateTick(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ super.updateTick(par1World, par2, par3, par4, par5Random);
+
+ if (par1World.provider.isSurfaceWorld() && par5Random.nextInt(2000) < par1World.difficultySetting) {
+ int var6;
+
+ for (var6 = par3; !par1World.doesBlockHaveSolidTopSurface(par2, var6, par4) && var6 > 0; --var6) {
+ ;
+ }
+
+ if (var6 > 0 && !par1World.isBlockNormalCube(par2, var6 + 1, par4)) {
+ Entity var7 = ItemMonsterPlacer.spawnCreature(par1World, 57, (double) par2 + 0.5D, (double) var6 + 1.1D,
+ (double) par4 + 0.5D);
+
+ if (var7 != null) {
+ var7.timeUntilPortal = var7.getPortalCooldown();
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns a bounding box from the pool of bounding boxes (this means this box
+ * can change after the pool has been cleared to be reused)
+ */
+ public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) {
+ return null;
+ }
+
+ /**
+ * Updates the blocks bounds based on its current state. Args: world, x, y, z
+ */
+ public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ float var5;
+ float var6;
+
+ if (par1IBlockAccess.getBlockId(par2 - 1, par3, par4) != this.blockID
+ && par1IBlockAccess.getBlockId(par2 + 1, par3, par4) != this.blockID) {
+ var5 = 0.125F;
+ var6 = 0.5F;
+ this.setBlockBounds(0.5F - var5, 0.0F, 0.5F - var6, 0.5F + var5, 1.0F, 0.5F + var6);
+ } else {
+ var5 = 0.5F;
+ var6 = 0.125F;
+ this.setBlockBounds(0.5F - var5, 0.0F, 0.5F - var6, 0.5F + var5, 1.0F, 0.5F + var6);
+ }
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ /**
+ * Checks to see if this location is valid to create a portal and will return
+ * True if it does. Args: world, x, y, z
+ */
+ public boolean tryToCreatePortal(World par1World, int par2, int par3, int par4) {
+ byte var5 = 0;
+ byte var6 = 0;
+
+ if (par1World.getBlockId(par2 - 1, par3, par4) == Block.obsidian.blockID
+ || par1World.getBlockId(par2 + 1, par3, par4) == Block.obsidian.blockID) {
+ var5 = 1;
+ }
+
+ if (par1World.getBlockId(par2, par3, par4 - 1) == Block.obsidian.blockID
+ || par1World.getBlockId(par2, par3, par4 + 1) == Block.obsidian.blockID) {
+ var6 = 1;
+ }
+
+ if (var5 == var6) {
+ return false;
+ } else {
+ if (par1World.getBlockId(par2 - var5, par3, par4 - var6) == 0) {
+ par2 -= var5;
+ par4 -= var6;
+ }
+
+ int var7;
+ int var8;
+
+ for (var7 = -1; var7 <= 2; ++var7) {
+ for (var8 = -1; var8 <= 3; ++var8) {
+ boolean var9 = var7 == -1 || var7 == 2 || var8 == -1 || var8 == 3;
+
+ if (var7 != -1 && var7 != 2 || var8 != -1 && var8 != 3) {
+ int var10 = par1World.getBlockId(par2 + var5 * var7, par3 + var8, par4 + var6 * var7);
+
+ if (var9) {
+ if (var10 != Block.obsidian.blockID) {
+ return false;
+ }
+ } else if (var10 != 0 && var10 != Block.fire.blockID) {
+ return false;
+ }
+ }
+ }
+ }
+
+ for (var7 = 0; var7 < 2; ++var7) {
+ for (var8 = 0; var8 < 3; ++var8) {
+ par1World.setBlock(par2 + var5 * var7, par3 + var8, par4 + var6 * var7, Block.portal.blockID, 0, 2);
+ }
+ }
+
+ return true;
+ }
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ byte var6 = 0;
+ byte var7 = 1;
+
+ if (par1World.getBlockId(par2 - 1, par3, par4) == this.blockID
+ || par1World.getBlockId(par2 + 1, par3, par4) == this.blockID) {
+ var6 = 1;
+ var7 = 0;
+ }
+
+ int var8;
+
+ for (var8 = par3; par1World.getBlockId(par2, var8 - 1, par4) == this.blockID; --var8) {
+ ;
+ }
+
+ if (par1World.getBlockId(par2, var8 - 1, par4) != Block.obsidian.blockID) {
+ par1World.setBlockToAir(par2, par3, par4);
+ } else {
+ int var9;
+
+ for (var9 = 1; var9 < 4 && par1World.getBlockId(par2, var8 + var9, par4) == this.blockID; ++var9) {
+ ;
+ }
+
+ if (var9 == 3 && par1World.getBlockId(par2, var8 + var9, par4) == Block.obsidian.blockID) {
+ boolean var10 = par1World.getBlockId(par2 - 1, par3, par4) == this.blockID
+ || par1World.getBlockId(par2 + 1, par3, par4) == this.blockID;
+ boolean var11 = par1World.getBlockId(par2, par3, par4 - 1) == this.blockID
+ || par1World.getBlockId(par2, par3, par4 + 1) == this.blockID;
+
+ if (var10 && var11) {
+ par1World.setBlockToAir(par2, par3, par4);
+ } else {
+ if ((par1World.getBlockId(par2 + var6, par3, par4 + var7) != Block.obsidian.blockID
+ || par1World.getBlockId(par2 - var6, par3, par4 - var7) != this.blockID)
+ && (par1World.getBlockId(par2 - var6, par3, par4 - var7) != Block.obsidian.blockID
+ || par1World.getBlockId(par2 + var6, par3, par4 + var7) != this.blockID)) {
+ par1World.setBlockToAir(par2, par3, par4);
+ }
+ }
+ } else {
+ par1World.setBlockToAir(par2, par3, par4);
+ }
+ }
+ }
+
+ /**
+ * Returns the quantity of items to drop on block destruction.
+ */
+ public int quantityDropped(EaglercraftRandom par1Random) {
+ return 0;
+ }
+
+ /**
+ * Triggered whenever an entity collides with this block (enters into the
+ * block). Args: world, x, y, z, entity
+ */
+ public void onEntityCollidedWithBlock(World par1World, int par2, int par3, int par4, Entity par5Entity) {
+ if (par5Entity.ridingEntity == null && par5Entity.riddenByEntity == null) {
+ par5Entity.setInPortal();
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockPotato.java b/sp-server/src/main/java/net/minecraft/src/BlockPotato.java
new file mode 100644
index 0000000..2bd6d9f
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockPotato.java
@@ -0,0 +1,35 @@
+package net.minecraft.src;
+
+public class BlockPotato extends BlockCrops {
+ public BlockPotato(int par1) {
+ super(par1);
+ }
+
+ /**
+ * Generate a seed ItemStack for this crop.
+ */
+ protected int getSeedItem() {
+ return Item.potato.itemID;
+ }
+
+ /**
+ * Generate a crop produce ItemStack for this crop.
+ */
+ protected int getCropItem() {
+ return Item.potato.itemID;
+ }
+
+ /**
+ * Drops the block items with a specified chance of dropping the specified items
+ */
+ public void dropBlockAsItemWithChance(World par1World, int par2, int par3, int par4, int par5, float par6,
+ int par7) {
+ super.dropBlockAsItemWithChance(par1World, par2, par3, par4, par5, par6, par7);
+
+ if (!par1World.isRemote) {
+ if (par5 >= 7 && par1World.rand.nextInt(50) == 0) {
+ this.dropBlockAsItem_do(par1World, par2, par3, par4, new ItemStack(Item.poisonousPotato));
+ }
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockPoweredOre.java b/sp-server/src/main/java/net/minecraft/src/BlockPoweredOre.java
new file mode 100644
index 0000000..fba795c
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockPoweredOre.java
@@ -0,0 +1,27 @@
+package net.minecraft.src;
+
+public class BlockPoweredOre extends BlockOreStorage {
+ public BlockPoweredOre(int par1) {
+ super(par1);
+ this.setCreativeTab(CreativeTabs.tabRedstone);
+ }
+
+ /**
+ * Can this block provide power. Only wire currently seems to have this change
+ * based on its state.
+ */
+ public boolean canProvidePower() {
+ return true;
+ }
+
+ /**
+ * Returns true if the block is emitting indirect/weak redstone power on the
+ * specified side. If isBlockNormalCube returns true, standard redstone
+ * propagation rules will apply instead and this will not be called. Args:
+ * World, X, Y, Z, side. Note that the side is reversed - eg it is 1 (up) when
+ * checking the bottom of the block.
+ */
+ public int isProvidingWeakPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) {
+ return 15;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockPressurePlate.java b/sp-server/src/main/java/net/minecraft/src/BlockPressurePlate.java
new file mode 100644
index 0000000..0ff7df0
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockPressurePlate.java
@@ -0,0 +1,63 @@
+package net.minecraft.src;
+
+import java.util.Iterator;
+import java.util.List;
+
+public class BlockPressurePlate extends BlockBasePressurePlate {
+ /** The mob type that can trigger this pressure plate. */
+ private EnumMobType triggerMobType;
+
+ protected BlockPressurePlate(int par1, String par2Str, Material par3Material, EnumMobType par4EnumMobType) {
+ super(par1, par2Str, par3Material);
+ this.triggerMobType = par4EnumMobType;
+ }
+
+ /**
+ * Argument is weight (0-15). Return the metadata to be set because of it.
+ */
+ protected int getMetaFromWeight(int par1) {
+ return par1 > 0 ? 1 : 0;
+ }
+
+ /**
+ * Argument is metadata. Returns power level (0-15)
+ */
+ protected int getPowerSupply(int par1) {
+ return par1 == 1 ? 15 : 0;
+ }
+
+ /**
+ * Returns the current state of the pressure plate. Returns a value between 0
+ * and 15 based on the number of items on it.
+ */
+ protected int getPlateState(World par1World, int par2, int par3, int par4) {
+ List var5 = null;
+
+ if (this.triggerMobType == EnumMobType.everything) {
+ var5 = par1World.getEntitiesWithinAABBExcludingEntity((Entity) null,
+ this.getSensitiveAABB(par2, par3, par4));
+ }
+
+ if (this.triggerMobType == EnumMobType.mobs) {
+ var5 = par1World.getEntitiesWithinAABB(EntityLiving.class, this.getSensitiveAABB(par2, par3, par4));
+ }
+
+ if (this.triggerMobType == EnumMobType.players) {
+ var5 = par1World.getEntitiesWithinAABB(EntityPlayer.class, this.getSensitiveAABB(par2, par3, par4));
+ }
+
+ if (!var5.isEmpty()) {
+ Iterator var6 = var5.iterator();
+
+ while (var6.hasNext()) {
+ Entity var7 = (Entity) var6.next();
+
+ if (!var7.doesEntityNotTriggerPressurePlate()) {
+ return 15;
+ }
+ }
+ }
+
+ return 0;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockPressurePlateWeighted.java b/sp-server/src/main/java/net/minecraft/src/BlockPressurePlateWeighted.java
new file mode 100644
index 0000000..3aa341c
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockPressurePlateWeighted.java
@@ -0,0 +1,60 @@
+package net.minecraft.src;
+
+import java.util.Iterator;
+
+public class BlockPressurePlateWeighted extends BlockBasePressurePlate {
+ /** The maximum number of items the plate weights. */
+ private final int maxItemsWeighted;
+
+ protected BlockPressurePlateWeighted(int par1, String par2Str, Material par3Material, int par4) {
+ super(par1, par2Str, par3Material);
+ this.maxItemsWeighted = par4;
+ }
+
+ /**
+ * Returns the current state of the pressure plate. Returns a value between 0
+ * and 15 based on the number of items on it.
+ */
+ protected int getPlateState(World par1World, int par2, int par3, int par4) {
+ int var5 = 0;
+ Iterator var6 = par1World.getEntitiesWithinAABB(EntityItem.class, this.getSensitiveAABB(par2, par3, par4))
+ .iterator();
+
+ while (var6.hasNext()) {
+ EntityItem var7 = (EntityItem) var6.next();
+ var5 += var7.getEntityItem().stackSize;
+
+ if (var5 >= this.maxItemsWeighted) {
+ break;
+ }
+ }
+
+ if (var5 <= 0) {
+ return 0;
+ } else {
+ float var8 = (float) Math.min(this.maxItemsWeighted, var5) / (float) this.maxItemsWeighted;
+ return MathHelper.ceiling_float_int(var8 * 15.0F);
+ }
+ }
+
+ /**
+ * Argument is metadata. Returns power level (0-15)
+ */
+ protected int getPowerSupply(int par1) {
+ return par1;
+ }
+
+ /**
+ * Argument is weight (0-15). Return the metadata to be set because of it.
+ */
+ protected int getMetaFromWeight(int par1) {
+ return par1;
+ }
+
+ /**
+ * How many world ticks before ticking
+ */
+ public int tickRate(World par1World) {
+ return 10;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockPumpkin.java b/sp-server/src/main/java/net/minecraft/src/BlockPumpkin.java
new file mode 100644
index 0000000..5347c58
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockPumpkin.java
@@ -0,0 +1,105 @@
+package net.minecraft.src;
+
+public class BlockPumpkin extends BlockDirectional {
+ /** Boolean used to seperate different states of blocks */
+ private boolean blockType;
+
+ protected BlockPumpkin(int par1, boolean par2) {
+ super(par1, Material.pumpkin);
+ this.setTickRandomly(true);
+ this.blockType = par2;
+ this.setCreativeTab(CreativeTabs.tabBlock);
+ }
+
+ /**
+ * Called whenever the block is added into the world. Args: world, x, y, z
+ */
+ public void onBlockAdded(World par1World, int par2, int par3, int par4) {
+ super.onBlockAdded(par1World, par2, par3, par4);
+
+ if (par1World.getBlockId(par2, par3 - 1, par4) == Block.blockSnow.blockID
+ && par1World.getBlockId(par2, par3 - 2, par4) == Block.blockSnow.blockID) {
+ if (!par1World.isRemote) {
+ par1World.setBlock(par2, par3, par4, 0, 0, 2);
+ par1World.setBlock(par2, par3 - 1, par4, 0, 0, 2);
+ par1World.setBlock(par2, par3 - 2, par4, 0, 0, 2);
+ EntitySnowman var9 = new EntitySnowman(par1World);
+ var9.setLocationAndAngles((double) par2 + 0.5D, (double) par3 - 1.95D, (double) par4 + 0.5D, 0.0F,
+ 0.0F);
+ par1World.spawnEntityInWorld(var9);
+ par1World.notifyBlockChange(par2, par3, par4, 0);
+ par1World.notifyBlockChange(par2, par3 - 1, par4, 0);
+ par1World.notifyBlockChange(par2, par3 - 2, par4, 0);
+ }
+
+ for (int var10 = 0; var10 < 120; ++var10) {
+ par1World.spawnParticle("snowshovel", (double) par2 + par1World.rand.nextDouble(),
+ (double) (par3 - 2) + par1World.rand.nextDouble() * 2.5D,
+ (double) par4 + par1World.rand.nextDouble(), 0.0D, 0.0D, 0.0D);
+ }
+ } else if (par1World.getBlockId(par2, par3 - 1, par4) == Block.blockIron.blockID
+ && par1World.getBlockId(par2, par3 - 2, par4) == Block.blockIron.blockID) {
+ boolean var5 = par1World.getBlockId(par2 - 1, par3 - 1, par4) == Block.blockIron.blockID
+ && par1World.getBlockId(par2 + 1, par3 - 1, par4) == Block.blockIron.blockID;
+ boolean var6 = par1World.getBlockId(par2, par3 - 1, par4 - 1) == Block.blockIron.blockID
+ && par1World.getBlockId(par2, par3 - 1, par4 + 1) == Block.blockIron.blockID;
+
+ if (var5 || var6) {
+ par1World.setBlock(par2, par3, par4, 0, 0, 2);
+ par1World.setBlock(par2, par3 - 1, par4, 0, 0, 2);
+ par1World.setBlock(par2, par3 - 2, par4, 0, 0, 2);
+
+ if (var5) {
+ par1World.setBlock(par2 - 1, par3 - 1, par4, 0, 0, 2);
+ par1World.setBlock(par2 + 1, par3 - 1, par4, 0, 0, 2);
+ } else {
+ par1World.setBlock(par2, par3 - 1, par4 - 1, 0, 0, 2);
+ par1World.setBlock(par2, par3 - 1, par4 + 1, 0, 0, 2);
+ }
+
+ EntityIronGolem var7 = new EntityIronGolem(par1World);
+ var7.setPlayerCreated(true);
+ var7.setLocationAndAngles((double) par2 + 0.5D, (double) par3 - 1.95D, (double) par4 + 0.5D, 0.0F,
+ 0.0F);
+ par1World.spawnEntityInWorld(var7);
+
+ for (int var8 = 0; var8 < 120; ++var8) {
+ par1World.spawnParticle("snowballpoof", (double) par2 + par1World.rand.nextDouble(),
+ (double) (par3 - 2) + par1World.rand.nextDouble() * 3.9D,
+ (double) par4 + par1World.rand.nextDouble(), 0.0D, 0.0D, 0.0D);
+ }
+
+ par1World.notifyBlockChange(par2, par3, par4, 0);
+ par1World.notifyBlockChange(par2, par3 - 1, par4, 0);
+ par1World.notifyBlockChange(par2, par3 - 2, par4, 0);
+
+ if (var5) {
+ par1World.notifyBlockChange(par2 - 1, par3 - 1, par4, 0);
+ par1World.notifyBlockChange(par2 + 1, par3 - 1, par4, 0);
+ } else {
+ par1World.notifyBlockChange(par2, par3 - 1, par4 - 1, 0);
+ par1World.notifyBlockChange(par2, par3 - 1, par4 + 1, 0);
+ }
+ }
+ }
+ }
+
+ /**
+ * Checks to see if its valid to put this block at the specified coordinates.
+ * Args: world, x, y, z
+ */
+ public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4) {
+ int var5 = par1World.getBlockId(par2, par3, par4);
+ return (var5 == 0 || Block.blocksList[var5].blockMaterial.isReplaceable())
+ && par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4);
+ }
+
+ /**
+ * Called when the block is placed in the world.
+ */
+ public void onBlockPlacedBy(World par1World, int par2, int par3, int par4, EntityLiving par5EntityLiving,
+ ItemStack par6ItemStack) {
+ int var7 = MathHelper.floor_double((double) (par5EntityLiving.rotationYaw * 4.0F / 360.0F) + 2.5D) & 3;
+ par1World.setBlockMetadata(par2, par3, par4, var7, 2);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockQuartz.java b/sp-server/src/main/java/net/minecraft/src/BlockQuartz.java
new file mode 100644
index 0000000..4328897
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockQuartz.java
@@ -0,0 +1,62 @@
+package net.minecraft.src;
+
+public class BlockQuartz extends Block {
+ public static final String[] quartzBlockTypes = new String[] { "default", "chiseled", "lines" };
+ private static final String[] quartzBlockTextureTypes = new String[] { "quartzblock_side", "quartzblock_chiseled",
+ "quartzblock_lines", null, null };
+
+ public BlockQuartz(int par1) {
+ super(par1, Material.rock);
+ this.setCreativeTab(CreativeTabs.tabBlock);
+ }
+
+ /**
+ * Called when a block is placed using its ItemBlock. Args: World, X, Y, Z,
+ * side, hitX, hitY, hitZ, block metadata
+ */
+ public int onBlockPlaced(World par1World, int par2, int par3, int par4, int par5, float par6, float par7,
+ float par8, int par9) {
+ if (par9 == 2) {
+ switch (par5) {
+ case 0:
+ case 1:
+ par9 = 2;
+ break;
+
+ case 2:
+ case 3:
+ par9 = 4;
+ break;
+
+ case 4:
+ case 5:
+ par9 = 3;
+ }
+ }
+
+ return par9;
+ }
+
+ /**
+ * Determines the damage on the item the block drops. Used in cloth and wood.
+ */
+ public int damageDropped(int par1) {
+ return par1 != 3 && par1 != 4 ? par1 : 2;
+ }
+
+ /**
+ * Returns an item stack containing a single instance of the current block type.
+ * 'i' is the block's subtype/damage and is ignored for blocks which do not
+ * support subtypes. Blocks which cannot be harvested should return null.
+ */
+ protected ItemStack createStackedBlock(int par1) {
+ return par1 != 3 && par1 != 4 ? super.createStackedBlock(par1) : new ItemStack(this.blockID, 1, 2);
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 39;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockRail.java b/sp-server/src/main/java/net/minecraft/src/BlockRail.java
new file mode 100644
index 0000000..fc997fb
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockRail.java
@@ -0,0 +1,14 @@
+package net.minecraft.src;
+
+public class BlockRail extends BlockRailBase {
+ protected BlockRail(int par1) {
+ super(par1, false);
+ }
+
+ protected void func_94358_a(World par1World, int par2, int par3, int par4, int par5, int par6, int par7) {
+ if (par7 > 0 && Block.blocksList[par7].canProvidePower()
+ && (new BlockBaseRailLogic(this, par1World, par2, par3, par4)).getNumberOfAdjacentTracks() == 3) {
+ this.refreshTrackShape(par1World, par2, par3, par4, false);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockRailBase.java b/sp-server/src/main/java/net/minecraft/src/BlockRailBase.java
new file mode 100644
index 0000000..e0751a2
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockRailBase.java
@@ -0,0 +1,211 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public abstract class BlockRailBase extends Block {
+ /** Power related rails have this field at true. */
+ protected final boolean isPowered;
+
+ /**
+ * Returns true if the block at the coordinates of world passed is a valid rail
+ * block (current is rail, powered or detector).
+ */
+ public static final boolean isRailBlockAt(World par0World, int par1, int par2, int par3) {
+ return isRailBlock(par0World.getBlockId(par1, par2, par3));
+ }
+
+ /**
+ * Return true if the parameter is a blockID for a valid rail block (current is
+ * rail, powered or detector).
+ */
+ public static final boolean isRailBlock(int par0) {
+ return par0 == Block.rail.blockID || par0 == Block.railPowered.blockID || par0 == Block.railDetector.blockID
+ || par0 == Block.railActivator.blockID;
+ }
+
+ protected BlockRailBase(int par1, boolean par2) {
+ super(par1, Material.circuits);
+ this.isPowered = par2;
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.125F, 1.0F);
+ this.setCreativeTab(CreativeTabs.tabTransport);
+ }
+
+ /**
+ * Returns true if the block is power related rail.
+ */
+ public boolean isPowered() {
+ return this.isPowered;
+ }
+
+ /**
+ * Returns a bounding box from the pool of bounding boxes (this means this box
+ * can change after the pool has been cleared to be reused)
+ */
+ public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) {
+ return null;
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * Ray traces through the blocks collision from start vector to end vector
+ * returning a ray trace hit. Args: world, x, y, z, startVec, endVec
+ */
+ public MovingObjectPosition collisionRayTrace(World par1World, int par2, int par3, int par4, Vec3 par5Vec3,
+ Vec3 par6Vec3) {
+ this.setBlockBoundsBasedOnState(par1World, par2, par3, par4);
+ return super.collisionRayTrace(par1World, par2, par3, par4, par5Vec3, par6Vec3);
+ }
+
+ /**
+ * Updates the blocks bounds based on its current state. Args: world, x, y, z
+ */
+ public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ int var5 = par1IBlockAccess.getBlockMetadata(par2, par3, par4);
+
+ if (var5 >= 2 && var5 <= 5) {
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.625F, 1.0F);
+ } else {
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.125F, 1.0F);
+ }
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 9;
+ }
+
+ /**
+ * Returns the quantity of items to drop on block destruction.
+ */
+ public int quantityDropped(EaglercraftRandom par1Random) {
+ return 1;
+ }
+
+ /**
+ * Checks to see if its valid to put this block at the specified coordinates.
+ * Args: world, x, y, z
+ */
+ public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4) {
+ return par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4);
+ }
+
+ /**
+ * Called whenever the block is added into the world. Args: world, x, y, z
+ */
+ public void onBlockAdded(World par1World, int par2, int par3, int par4) {
+ if (!par1World.isRemote) {
+ this.refreshTrackShape(par1World, par2, par3, par4, true);
+
+ if (this.isPowered) {
+ this.onNeighborBlockChange(par1World, par2, par3, par4, this.blockID);
+ }
+ }
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ if (!par1World.isRemote) {
+ int var6 = par1World.getBlockMetadata(par2, par3, par4);
+ int var7 = var6;
+
+ if (this.isPowered) {
+ var7 = var6 & 7;
+ }
+
+ boolean var8 = false;
+
+ if (!par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4)) {
+ var8 = true;
+ }
+
+ if (var7 == 2 && !par1World.doesBlockHaveSolidTopSurface(par2 + 1, par3, par4)) {
+ var8 = true;
+ }
+
+ if (var7 == 3 && !par1World.doesBlockHaveSolidTopSurface(par2 - 1, par3, par4)) {
+ var8 = true;
+ }
+
+ if (var7 == 4 && !par1World.doesBlockHaveSolidTopSurface(par2, par3, par4 - 1)) {
+ var8 = true;
+ }
+
+ if (var7 == 5 && !par1World.doesBlockHaveSolidTopSurface(par2, par3, par4 + 1)) {
+ var8 = true;
+ }
+
+ if (var8) {
+ this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
+ par1World.setBlockToAir(par2, par3, par4);
+ } else {
+ this.func_94358_a(par1World, par2, par3, par4, var6, var7, par5);
+ }
+ }
+ }
+
+ protected void func_94358_a(World par1World, int par2, int par3, int par4, int par5, int par6, int par7) {
+ }
+
+ /**
+ * Completely recalculates the track shape based on neighboring tracks
+ */
+ protected void refreshTrackShape(World par1World, int par2, int par3, int par4, boolean par5) {
+ if (!par1World.isRemote) {
+ (new BlockBaseRailLogic(this, par1World, par2, par3, par4))
+ .func_94511_a(par1World.isBlockIndirectlyGettingPowered(par2, par3, par4), par5);
+ }
+ }
+
+ /**
+ * Returns the mobility information of the block, 0 = free, 1 = can't push but
+ * can move over, 2 = total immobility and stop pistons
+ */
+ public int getMobilityFlag() {
+ return 0;
+ }
+
+ /**
+ * ejects contained items into the world, and notifies neighbours of an update,
+ * as appropriate
+ */
+ public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) {
+ int var7 = par6;
+
+ if (this.isPowered) {
+ var7 = par6 & 7;
+ }
+
+ super.breakBlock(par1World, par2, par3, par4, par5, par6);
+
+ if (var7 == 2 || var7 == 3 || var7 == 4 || var7 == 5) {
+ par1World.notifyBlocksOfNeighborChange(par2, par3 + 1, par4, par5);
+ }
+
+ if (this.isPowered) {
+ par1World.notifyBlocksOfNeighborChange(par2, par3, par4, par5);
+ par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, par5);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockRailPowered.java b/sp-server/src/main/java/net/minecraft/src/BlockRailPowered.java
new file mode 100644
index 0000000..da42353
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockRailPowered.java
@@ -0,0 +1,136 @@
+package net.minecraft.src;
+
+public class BlockRailPowered extends BlockRailBase {
+ protected BlockRailPowered(int par1) {
+ super(par1, true);
+ }
+
+ protected boolean func_94360_a(World par1World, int par2, int par3, int par4, int par5, boolean par6, int par7) {
+ if (par7 >= 8) {
+ return false;
+ } else {
+ int var8 = par5 & 7;
+ boolean var9 = true;
+
+ switch (var8) {
+ case 0:
+ if (par6) {
+ ++par4;
+ } else {
+ --par4;
+ }
+
+ break;
+
+ case 1:
+ if (par6) {
+ --par2;
+ } else {
+ ++par2;
+ }
+
+ break;
+
+ case 2:
+ if (par6) {
+ --par2;
+ } else {
+ ++par2;
+ ++par3;
+ var9 = false;
+ }
+
+ var8 = 1;
+ break;
+
+ case 3:
+ if (par6) {
+ --par2;
+ ++par3;
+ var9 = false;
+ } else {
+ ++par2;
+ }
+
+ var8 = 1;
+ break;
+
+ case 4:
+ if (par6) {
+ ++par4;
+ } else {
+ --par4;
+ ++par3;
+ var9 = false;
+ }
+
+ var8 = 0;
+ break;
+
+ case 5:
+ if (par6) {
+ ++par4;
+ ++par3;
+ var9 = false;
+ } else {
+ --par4;
+ }
+
+ var8 = 0;
+ }
+
+ return this.func_94361_a(par1World, par2, par3, par4, par6, par7, var8) ? true
+ : var9 && this.func_94361_a(par1World, par2, par3 - 1, par4, par6, par7, var8);
+ }
+ }
+
+ protected boolean func_94361_a(World par1World, int par2, int par3, int par4, boolean par5, int par6, int par7) {
+ int var8 = par1World.getBlockId(par2, par3, par4);
+
+ if (var8 == this.blockID) {
+ int var9 = par1World.getBlockMetadata(par2, par3, par4);
+ int var10 = var9 & 7;
+
+ if (par7 == 1 && (var10 == 0 || var10 == 4 || var10 == 5)) {
+ return false;
+ }
+
+ if (par7 == 0 && (var10 == 1 || var10 == 2 || var10 == 3)) {
+ return false;
+ }
+
+ if ((var9 & 8) != 0) {
+ if (par1World.isBlockIndirectlyGettingPowered(par2, par3, par4)) {
+ return true;
+ }
+
+ return this.func_94360_a(par1World, par2, par3, par4, var9, par5, par6 + 1);
+ }
+ }
+
+ return false;
+ }
+
+ protected void func_94358_a(World par1World, int par2, int par3, int par4, int par5, int par6, int par7) {
+ boolean var8 = par1World.isBlockIndirectlyGettingPowered(par2, par3, par4);
+ var8 = var8 || this.func_94360_a(par1World, par2, par3, par4, par5, true, 0)
+ || this.func_94360_a(par1World, par2, par3, par4, par5, false, 0);
+ boolean var9 = false;
+
+ if (var8 && (par5 & 8) == 0) {
+ par1World.setBlockMetadata(par2, par3, par4, par6 | 8, 3);
+ var9 = true;
+ } else if (!var8 && (par5 & 8) != 0) {
+ par1World.setBlockMetadata(par2, par3, par4, par6, 3);
+ var9 = true;
+ }
+
+ if (var9) {
+ par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID);
+
+ if (par6 == 2 || par6 == 3 || par6 == 4 || par6 == 5) {
+ par1World.notifyBlocksOfNeighborChange(par2, par3 + 1, par4, this.blockID);
+ }
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockRedstoneLight.java b/sp-server/src/main/java/net/minecraft/src/BlockRedstoneLight.java
new file mode 100644
index 0000000..a43382f
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockRedstoneLight.java
@@ -0,0 +1,61 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockRedstoneLight extends Block {
+ /** Whether this lamp block is the powered version. */
+ private final boolean powered;
+
+ public BlockRedstoneLight(int par1, boolean par2) {
+ super(par1, Material.redstoneLight);
+ this.powered = par2;
+
+ if (par2) {
+ this.setLightValue(1.0F);
+ }
+ }
+
+ /**
+ * Called whenever the block is added into the world. Args: world, x, y, z
+ */
+ public void onBlockAdded(World par1World, int par2, int par3, int par4) {
+ if (!par1World.isRemote) {
+ if (this.powered && !par1World.isBlockIndirectlyGettingPowered(par2, par3, par4)) {
+ par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, 4);
+ } else if (!this.powered && par1World.isBlockIndirectlyGettingPowered(par2, par3, par4)) {
+ par1World.setBlock(par2, par3, par4, Block.redstoneLampActive.blockID, 0, 2);
+ }
+ }
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ if (!par1World.isRemote) {
+ if (this.powered && !par1World.isBlockIndirectlyGettingPowered(par2, par3, par4)) {
+ par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, 4);
+ } else if (!this.powered && par1World.isBlockIndirectlyGettingPowered(par2, par3, par4)) {
+ par1World.setBlock(par2, par3, par4, Block.redstoneLampActive.blockID, 0, 2);
+ }
+ }
+ }
+
+ /**
+ * Ticks the block if it's been scheduled
+ */
+ public void updateTick(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ if (!par1World.isRemote && this.powered && !par1World.isBlockIndirectlyGettingPowered(par2, par3, par4)) {
+ par1World.setBlock(par2, par3, par4, Block.redstoneLampIdle.blockID, 0, 2);
+ }
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return Block.redstoneLampIdle.blockID;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockRedstoneLogic.java b/sp-server/src/main/java/net/minecraft/src/BlockRedstoneLogic.java
new file mode 100644
index 0000000..b589f14
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockRedstoneLogic.java
@@ -0,0 +1,325 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public abstract class BlockRedstoneLogic extends BlockDirectional {
+ /** Tells whether the repeater is powered or not */
+ protected final boolean isRepeaterPowered;
+
+ protected BlockRedstoneLogic(int par1, boolean par2) {
+ super(par1, Material.circuits);
+ this.isRepeaterPowered = par2;
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.125F, 1.0F);
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ /**
+ * Checks to see if its valid to put this block at the specified coordinates.
+ * Args: world, x, y, z
+ */
+ public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4) {
+ return !par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4) ? false
+ : super.canPlaceBlockAt(par1World, par2, par3, par4);
+ }
+
+ /**
+ * Can this block stay at this position. Similar to canPlaceBlockAt except gets
+ * checked often with plants.
+ */
+ public boolean canBlockStay(World par1World, int par2, int par3, int par4) {
+ return !par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4) ? false
+ : super.canBlockStay(par1World, par2, par3, par4);
+ }
+
+ /**
+ * Ticks the block if it's been scheduled
+ */
+ public void updateTick(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ int var6 = par1World.getBlockMetadata(par2, par3, par4);
+
+ if (!this.func_94476_e(par1World, par2, par3, par4, var6)) {
+ boolean var7 = this.func_94478_d(par1World, par2, par3, par4, var6);
+
+ if (this.isRepeaterPowered && !var7) {
+ par1World.setBlock(par2, par3, par4, this.func_94484_i().blockID, var6, 2);
+ } else if (!this.isRepeaterPowered) {
+ par1World.setBlock(par2, par3, par4, this.func_94485_e().blockID, var6, 2);
+
+ if (!var7) {
+ par1World.func_82740_a(par2, par3, par4, this.func_94485_e().blockID, this.func_94486_g(var6), -1);
+ }
+ }
+ }
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 36;
+ }
+
+ protected boolean func_96470_c(int par1) {
+ return this.isRepeaterPowered;
+ }
+
+ /**
+ * Returns true if the block is emitting direct/strong redstone power on the
+ * specified side. Args: World, X, Y, Z, side. Note that the side is reversed -
+ * eg it is 1 (up) when checking the bottom of the block.
+ */
+ public int isProvidingStrongPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) {
+ return this.isProvidingWeakPower(par1IBlockAccess, par2, par3, par4, par5);
+ }
+
+ /**
+ * Returns true if the block is emitting indirect/weak redstone power on the
+ * specified side. If isBlockNormalCube returns true, standard redstone
+ * propagation rules will apply instead and this will not be called. Args:
+ * World, X, Y, Z, side. Note that the side is reversed - eg it is 1 (up) when
+ * checking the bottom of the block.
+ */
+ public int isProvidingWeakPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) {
+ int var6 = par1IBlockAccess.getBlockMetadata(par2, par3, par4);
+
+ if (!this.func_96470_c(var6)) {
+ return 0;
+ } else {
+ int var7 = getDirection(var6);
+ return var7 == 0 && par5 == 3 ? this.func_94480_d(par1IBlockAccess, par2, par3, par4, var6)
+ : (var7 == 1 && par5 == 4 ? this.func_94480_d(par1IBlockAccess, par2, par3, par4, var6)
+ : (var7 == 2 && par5 == 2 ? this.func_94480_d(par1IBlockAccess, par2, par3, par4, var6)
+ : (var7 == 3 && par5 == 5
+ ? this.func_94480_d(par1IBlockAccess, par2, par3, par4, var6)
+ : 0)));
+ }
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ if (!this.canBlockStay(par1World, par2, par3, par4)) {
+ this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
+ par1World.setBlockToAir(par2, par3, par4);
+ par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID);
+ par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID);
+ par1World.notifyBlocksOfNeighborChange(par2, par3, par4 + 1, this.blockID);
+ par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID);
+ par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID);
+ par1World.notifyBlocksOfNeighborChange(par2, par3 + 1, par4, this.blockID);
+ } else {
+ this.func_94479_f(par1World, par2, par3, par4, par5);
+ }
+ }
+
+ protected void func_94479_f(World par1World, int par2, int par3, int par4, int par5) {
+ int var6 = par1World.getBlockMetadata(par2, par3, par4);
+
+ if (!this.func_94476_e(par1World, par2, par3, par4, var6)) {
+ boolean var7 = this.func_94478_d(par1World, par2, par3, par4, var6);
+
+ if ((this.isRepeaterPowered && !var7 || !this.isRepeaterPowered && var7)
+ && !par1World.isBlockTickScheduled(par2, par3, par4, this.blockID)) {
+ byte var8 = -1;
+
+ if (this.func_83011_d(par1World, par2, par3, par4, var6)) {
+ var8 = -3;
+ } else if (this.isRepeaterPowered) {
+ var8 = -2;
+ }
+
+ par1World.func_82740_a(par2, par3, par4, this.blockID, this.func_94481_j_(var6), var8);
+ }
+ }
+ }
+
+ public boolean func_94476_e(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) {
+ return false;
+ }
+
+ protected boolean func_94478_d(World par1World, int par2, int par3, int par4, int par5) {
+ return this.getInputStrength(par1World, par2, par3, par4, par5) > 0;
+ }
+
+ /**
+ * Returns the signal strength at one input of the block. Args: world, X, Y, Z,
+ * side
+ */
+ protected int getInputStrength(World par1World, int par2, int par3, int par4, int par5) {
+ int var6 = getDirection(par5);
+ int var7 = par2 + Direction.offsetX[var6];
+ int var8 = par4 + Direction.offsetZ[var6];
+ int var9 = par1World.getIndirectPowerLevelTo(var7, par3, var8, Direction.directionToFacing[var6]);
+ return var9 >= 15 ? var9
+ : Math.max(var9,
+ par1World.getBlockId(var7, par3, var8) == Block.redstoneWire.blockID
+ ? par1World.getBlockMetadata(var7, par3, var8)
+ : 0);
+ }
+
+ protected int func_94482_f(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) {
+ int var6 = getDirection(par5);
+
+ switch (var6) {
+ case 0:
+ case 2:
+ return Math.max(this.func_94488_g(par1IBlockAccess, par2 - 1, par3, par4, 4),
+ this.func_94488_g(par1IBlockAccess, par2 + 1, par3, par4, 5));
+
+ case 1:
+ case 3:
+ return Math.max(this.func_94488_g(par1IBlockAccess, par2, par3, par4 + 1, 3),
+ this.func_94488_g(par1IBlockAccess, par2, par3, par4 - 1, 2));
+
+ default:
+ return 0;
+ }
+ }
+
+ protected int func_94488_g(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) {
+ int var6 = par1IBlockAccess.getBlockId(par2, par3, par4);
+ return this.func_94477_d(var6)
+ ? (var6 == Block.redstoneWire.blockID ? par1IBlockAccess.getBlockMetadata(par2, par3, par4)
+ : par1IBlockAccess.isBlockProvidingPowerTo(par2, par3, par4, par5))
+ : 0;
+ }
+
+ /**
+ * Can this block provide power. Only wire currently seems to have this change
+ * based on its state.
+ */
+ public boolean canProvidePower() {
+ return true;
+ }
+
+ /**
+ * Called when the block is placed in the world.
+ */
+ public void onBlockPlacedBy(World par1World, int par2, int par3, int par4, EntityLiving par5EntityLiving,
+ ItemStack par6ItemStack) {
+ int var7 = ((MathHelper.floor_double((double) (par5EntityLiving.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3) + 2)
+ % 4;
+ par1World.setBlockMetadata(par2, par3, par4, var7, 3);
+ boolean var8 = this.func_94478_d(par1World, par2, par3, par4, var7);
+
+ if (var8) {
+ par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, 1);
+ }
+ }
+
+ /**
+ * Called whenever the block is added into the world. Args: world, x, y, z
+ */
+ public void onBlockAdded(World par1World, int par2, int par3, int par4) {
+ this.func_94483_i_(par1World, par2, par3, par4);
+ }
+
+ protected void func_94483_i_(World par1World, int par2, int par3, int par4) {
+ int var5 = getDirection(par1World.getBlockMetadata(par2, par3, par4));
+
+ if (var5 == 1) {
+ par1World.notifyBlockOfNeighborChange(par2 + 1, par3, par4, this.blockID);
+ par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID, 4);
+ }
+
+ if (var5 == 3) {
+ par1World.notifyBlockOfNeighborChange(par2 - 1, par3, par4, this.blockID);
+ par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID, 5);
+ }
+
+ if (var5 == 2) {
+ par1World.notifyBlockOfNeighborChange(par2, par3, par4 + 1, this.blockID);
+ par1World.notifyBlocksOfNeighborChange(par2, par3, par4 + 1, this.blockID, 2);
+ }
+
+ if (var5 == 0) {
+ par1World.notifyBlockOfNeighborChange(par2, par3, par4 - 1, this.blockID);
+ par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID, 3);
+ }
+ }
+
+ /**
+ * Called right before the block is destroyed by a player. Args: world, x, y, z,
+ * metaData
+ */
+ public void onBlockDestroyedByPlayer(World par1World, int par2, int par3, int par4, int par5) {
+ if (this.isRepeaterPowered) {
+ par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID);
+ par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID);
+ par1World.notifyBlocksOfNeighborChange(par2, par3, par4 + 1, this.blockID);
+ par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID);
+ par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID);
+ par1World.notifyBlocksOfNeighborChange(par2, par3 + 1, par4, this.blockID);
+ }
+
+ super.onBlockDestroyedByPlayer(par1World, par2, par3, par4, par5);
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ protected boolean func_94477_d(int par1) {
+ Block var2 = Block.blocksList[par1];
+ return var2 != null && var2.canProvidePower();
+ }
+
+ protected int func_94480_d(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) {
+ return 15;
+ }
+
+ public static boolean isRedstoneRepeaterBlockID(int par0) {
+ return Block.redstoneRepeaterIdle.func_94487_f(par0) || Block.redstoneComparatorIdle.func_94487_f(par0);
+ }
+
+ public boolean func_94487_f(int par1) {
+ return par1 == this.func_94485_e().blockID || par1 == this.func_94484_i().blockID;
+ }
+
+ public boolean func_83011_d(World par1World, int par2, int par3, int par4, int par5) {
+ int var6 = getDirection(par5);
+
+ if (isRedstoneRepeaterBlockID(
+ par1World.getBlockId(par2 - Direction.offsetX[var6], par3, par4 - Direction.offsetZ[var6]))) {
+ int var7 = par1World.getBlockMetadata(par2 - Direction.offsetX[var6], par3, par4 - Direction.offsetZ[var6]);
+ int var8 = getDirection(var7);
+ return var8 != var6;
+ } else {
+ return false;
+ }
+ }
+
+ protected int func_94486_g(int par1) {
+ return this.func_94481_j_(par1);
+ }
+
+ protected abstract int func_94481_j_(int var1);
+
+ protected abstract BlockRedstoneLogic func_94485_e();
+
+ protected abstract BlockRedstoneLogic func_94484_i();
+
+ /**
+ * Returns true if the given block ID is equivalent to this one. Example:
+ * redstoneTorchOn matches itself and redstoneTorchOff, and vice versa. Most
+ * blocks only match themselves.
+ */
+ public boolean isAssociatedBlockID(int par1) {
+ return this.func_94487_f(par1);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockRedstoneOre.java b/sp-server/src/main/java/net/minecraft/src/BlockRedstoneOre.java
new file mode 100644
index 0000000..8220fac
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockRedstoneOre.java
@@ -0,0 +1,157 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockRedstoneOre extends Block {
+ private boolean glowing;
+
+ public BlockRedstoneOre(int par1, boolean par2) {
+ super(par1, Material.rock);
+
+ if (par2) {
+ this.setTickRandomly(true);
+ }
+
+ this.glowing = par2;
+ }
+
+ /**
+ * How many world ticks before ticking
+ */
+ public int tickRate(World par1World) {
+ return 30;
+ }
+
+ /**
+ * Called when the block is clicked by a player. Args: x, y, z, entityPlayer
+ */
+ public void onBlockClicked(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer) {
+ this.glow(par1World, par2, par3, par4);
+ super.onBlockClicked(par1World, par2, par3, par4, par5EntityPlayer);
+ }
+
+ /**
+ * Called whenever an entity is walking on top of this block. Args: world, x, y,
+ * z, entity
+ */
+ public void onEntityWalking(World par1World, int par2, int par3, int par4, Entity par5Entity) {
+ this.glow(par1World, par2, par3, par4);
+ super.onEntityWalking(par1World, par2, par3, par4, par5Entity);
+ }
+
+ /**
+ * Called upon block activation (right click on the block.)
+ */
+ public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer,
+ int par6, float par7, float par8, float par9) {
+ this.glow(par1World, par2, par3, par4);
+ return super.onBlockActivated(par1World, par2, par3, par4, par5EntityPlayer, par6, par7, par8, par9);
+ }
+
+ /**
+ * The redstone ore glows.
+ */
+ private void glow(World par1World, int par2, int par3, int par4) {
+ this.sparkle(par1World, par2, par3, par4);
+
+ if (this.blockID == Block.oreRedstone.blockID) {
+ par1World.setBlock(par2, par3, par4, Block.oreRedstoneGlowing.blockID);
+ }
+ }
+
+ /**
+ * Ticks the block if it's been scheduled
+ */
+ public void updateTick(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ if (this.blockID == Block.oreRedstoneGlowing.blockID) {
+ par1World.setBlock(par2, par3, par4, Block.oreRedstone.blockID);
+ }
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return Item.redstone.itemID;
+ }
+
+ /**
+ * Returns the usual quantity dropped by the block plus a bonus of 1 to 'i'
+ * (inclusive).
+ */
+ public int quantityDroppedWithBonus(int par1, EaglercraftRandom par2Random) {
+ return this.quantityDropped(par2Random) + par2Random.nextInt(par1 + 1);
+ }
+
+ /**
+ * Returns the quantity of items to drop on block destruction.
+ */
+ public int quantityDropped(EaglercraftRandom par1Random) {
+ return 4 + par1Random.nextInt(2);
+ }
+
+ /**
+ * Drops the block items with a specified chance of dropping the specified items
+ */
+ public void dropBlockAsItemWithChance(World par1World, int par2, int par3, int par4, int par5, float par6,
+ int par7) {
+ super.dropBlockAsItemWithChance(par1World, par2, par3, par4, par5, par6, par7);
+
+ if (this.idDropped(par5, par1World.rand, par7) != this.blockID) {
+ int var8 = 1 + par1World.rand.nextInt(5);
+ this.dropXpOnBlockBreak(par1World, par2, par3, par4, var8);
+ }
+ }
+
+ /**
+ * The redstone ore sparkles.
+ */
+ private void sparkle(World par1World, int par2, int par3, int par4) {
+ EaglercraftRandom var5 = par1World.rand;
+ double var6 = 0.0625D;
+
+ for (int var8 = 0; var8 < 6; ++var8) {
+ double var9 = (double) ((float) par2 + var5.nextFloat());
+ double var11 = (double) ((float) par3 + var5.nextFloat());
+ double var13 = (double) ((float) par4 + var5.nextFloat());
+
+ if (var8 == 0 && !par1World.isBlockOpaqueCube(par2, par3 + 1, par4)) {
+ var11 = (double) (par3 + 1) + var6;
+ }
+
+ if (var8 == 1 && !par1World.isBlockOpaqueCube(par2, par3 - 1, par4)) {
+ var11 = (double) (par3 + 0) - var6;
+ }
+
+ if (var8 == 2 && !par1World.isBlockOpaqueCube(par2, par3, par4 + 1)) {
+ var13 = (double) (par4 + 1) + var6;
+ }
+
+ if (var8 == 3 && !par1World.isBlockOpaqueCube(par2, par3, par4 - 1)) {
+ var13 = (double) (par4 + 0) - var6;
+ }
+
+ if (var8 == 4 && !par1World.isBlockOpaqueCube(par2 + 1, par3, par4)) {
+ var9 = (double) (par2 + 1) + var6;
+ }
+
+ if (var8 == 5 && !par1World.isBlockOpaqueCube(par2 - 1, par3, par4)) {
+ var9 = (double) (par2 + 0) - var6;
+ }
+
+ if (var9 < (double) par2 || var9 > (double) (par2 + 1) || var11 < 0.0D || var11 > (double) (par3 + 1)
+ || var13 < (double) par4 || var13 > (double) (par4 + 1)) {
+ par1World.spawnParticle("reddust", var9, var11, var13, 0.0D, 0.0D, 0.0D);
+ }
+ }
+ }
+
+ /**
+ * Returns an item stack containing a single instance of the current block type.
+ * 'i' is the block's subtype/damage and is ignored for blocks which do not
+ * support subtypes. Blocks which cannot be harvested should return null.
+ */
+ protected ItemStack createStackedBlock(int par1) {
+ return new ItemStack(Block.oreRedstone);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockRedstoneRepeater.java b/sp-server/src/main/java/net/minecraft/src/BlockRedstoneRepeater.java
new file mode 100644
index 0000000..7ba970e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockRedstoneRepeater.java
@@ -0,0 +1,70 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockRedstoneRepeater extends BlockRedstoneLogic {
+ /** The offsets for the two torches in redstone repeater blocks. */
+ public static final double[] repeaterTorchOffset = new double[] { -0.0625D, 0.0625D, 0.1875D, 0.3125D };
+
+ /** The states in which the redstone repeater blocks can be. */
+ private static final int[] repeaterState = new int[] { 1, 2, 3, 4 };
+
+ protected BlockRedstoneRepeater(int par1, boolean par2) {
+ super(par1, par2);
+ }
+
+ /**
+ * Called upon block activation (right click on the block.)
+ */
+ public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer,
+ int par6, float par7, float par8, float par9) {
+ int var10 = par1World.getBlockMetadata(par2, par3, par4);
+ int var11 = (var10 & 12) >> 2;
+ var11 = var11 + 1 << 2 & 12;
+ par1World.setBlockMetadata(par2, par3, par4, var11 | var10 & 3, 3);
+ return true;
+ }
+
+ protected int func_94481_j_(int par1) {
+ return repeaterState[(par1 & 12) >> 2] * 2;
+ }
+
+ protected BlockRedstoneLogic func_94485_e() {
+ return Block.redstoneRepeaterActive;
+ }
+
+ protected BlockRedstoneLogic func_94484_i() {
+ return Block.redstoneRepeaterIdle;
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return Item.redstoneRepeater.itemID;
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 15;
+ }
+
+ public boolean func_94476_e(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) {
+ return this.func_94482_f(par1IBlockAccess, par2, par3, par4, par5) > 0;
+ }
+
+ protected boolean func_94477_d(int par1) {
+ return isRedstoneRepeaterBlockID(par1);
+ }
+
+ /**
+ * ejects contained items into the world, and notifies neighbours of an update,
+ * as appropriate
+ */
+ public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) {
+ super.breakBlock(par1World, par2, par3, par4, par5, par6);
+ this.func_94483_i_(par1World, par2, par3, par4);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockRedstoneTorch.java b/sp-server/src/main/java/net/minecraft/src/BlockRedstoneTorch.java
new file mode 100644
index 0000000..bfd4e57
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockRedstoneTorch.java
@@ -0,0 +1,207 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockRedstoneTorch extends BlockTorch {
+ /** Whether the redstone torch is currently active or not. */
+ private boolean torchActive = false;
+
+ /** Map of ArrayLists of RedstoneUpdateInfo. Key of map is World. */
+ private static Map redstoneUpdateInfoCache = new HashMap();
+
+ private boolean checkForBurnout(World par1World, int par2, int par3, int par4, boolean par5) {
+ if (!redstoneUpdateInfoCache.containsKey(par1World)) {
+ redstoneUpdateInfoCache.put(par1World, new ArrayList());
+ }
+
+ List var6 = (List) redstoneUpdateInfoCache.get(par1World);
+
+ if (par5) {
+ var6.add(new RedstoneUpdateInfo(par2, par3, par4, par1World.getTotalWorldTime()));
+ }
+
+ int var7 = 0;
+
+ for (int var8 = 0; var8 < var6.size(); ++var8) {
+ RedstoneUpdateInfo var9 = (RedstoneUpdateInfo) var6.get(var8);
+
+ if (var9.x == par2 && var9.y == par3 && var9.z == par4) {
+ ++var7;
+
+ if (var7 >= 8) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ protected BlockRedstoneTorch(int par1, boolean par2) {
+ super(par1);
+ this.torchActive = par2;
+ this.setTickRandomly(true);
+ this.setCreativeTab((CreativeTabs) null);
+ }
+
+ /**
+ * How many world ticks before ticking
+ */
+ public int tickRate(World par1World) {
+ return 2;
+ }
+
+ /**
+ * Called whenever the block is added into the world. Args: world, x, y, z
+ */
+ public void onBlockAdded(World par1World, int par2, int par3, int par4) {
+ if (par1World.getBlockMetadata(par2, par3, par4) == 0) {
+ super.onBlockAdded(par1World, par2, par3, par4);
+ }
+
+ if (this.torchActive) {
+ par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID);
+ par1World.notifyBlocksOfNeighborChange(par2, par3 + 1, par4, this.blockID);
+ par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID);
+ par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID);
+ par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID);
+ par1World.notifyBlocksOfNeighborChange(par2, par3, par4 + 1, this.blockID);
+ }
+ }
+
+ /**
+ * ejects contained items into the world, and notifies neighbours of an update,
+ * as appropriate
+ */
+ public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) {
+ if (this.torchActive) {
+ par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID);
+ par1World.notifyBlocksOfNeighborChange(par2, par3 + 1, par4, this.blockID);
+ par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID);
+ par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID);
+ par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID);
+ par1World.notifyBlocksOfNeighborChange(par2, par3, par4 + 1, this.blockID);
+ }
+ }
+
+ /**
+ * Returns true if the block is emitting indirect/weak redstone power on the
+ * specified side. If isBlockNormalCube returns true, standard redstone
+ * propagation rules will apply instead and this will not be called. Args:
+ * World, X, Y, Z, side. Note that the side is reversed - eg it is 1 (up) when
+ * checking the bottom of the block.
+ */
+ public int isProvidingWeakPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) {
+ if (!this.torchActive) {
+ return 0;
+ } else {
+ int var6 = par1IBlockAccess.getBlockMetadata(par2, par3, par4);
+ return var6 == 5 && par5 == 1 ? 0
+ : (var6 == 3 && par5 == 3 ? 0
+ : (var6 == 4 && par5 == 2 ? 0
+ : (var6 == 1 && par5 == 5 ? 0 : (var6 == 2 && par5 == 4 ? 0 : 15))));
+ }
+ }
+
+ /**
+ * Returns true or false based on whether the block the torch is attached to is
+ * providing indirect power.
+ */
+ private boolean isIndirectlyPowered(World par1World, int par2, int par3, int par4) {
+ int var5 = par1World.getBlockMetadata(par2, par3, par4);
+ return var5 == 5 && par1World.getIndirectPowerOutput(par2, par3 - 1, par4, 0) ? true
+ : (var5 == 3 && par1World.getIndirectPowerOutput(par2, par3, par4 - 1, 2) ? true
+ : (var5 == 4 && par1World.getIndirectPowerOutput(par2, par3, par4 + 1, 3) ? true
+ : (var5 == 1 && par1World.getIndirectPowerOutput(par2 - 1, par3, par4, 4) ? true
+ : var5 == 2 && par1World.getIndirectPowerOutput(par2 + 1, par3, par4, 5))));
+ }
+
+ /**
+ * Ticks the block if it's been scheduled
+ */
+ public void updateTick(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ boolean var6 = this.isIndirectlyPowered(par1World, par2, par3, par4);
+ List var7 = (List) redstoneUpdateInfoCache.get(par1World);
+
+ while (var7 != null && !var7.isEmpty()
+ && par1World.getTotalWorldTime() - ((RedstoneUpdateInfo) var7.get(0)).updateTime > 60L) {
+ var7.remove(0);
+ }
+
+ if (this.torchActive) {
+ if (var6) {
+ par1World.setBlock(par2, par3, par4, Block.torchRedstoneIdle.blockID,
+ par1World.getBlockMetadata(par2, par3, par4), 3);
+
+ if (this.checkForBurnout(par1World, par2, par3, par4, true)) {
+ par1World.playSoundEffect((double) ((float) par2 + 0.5F), (double) ((float) par3 + 0.5F),
+ (double) ((float) par4 + 0.5F), "random.fizz", 0.5F,
+ 2.6F + (par1World.rand.nextFloat() - par1World.rand.nextFloat()) * 0.8F);
+
+ for (int var8 = 0; var8 < 5; ++var8) {
+ double var9 = (double) par2 + par5Random.nextDouble() * 0.6D + 0.2D;
+ double var11 = (double) par3 + par5Random.nextDouble() * 0.6D + 0.2D;
+ double var13 = (double) par4 + par5Random.nextDouble() * 0.6D + 0.2D;
+ par1World.spawnParticle("smoke", var9, var11, var13, 0.0D, 0.0D, 0.0D);
+ }
+ }
+ }
+ } else if (!var6 && !this.checkForBurnout(par1World, par2, par3, par4, false)) {
+ par1World.setBlock(par2, par3, par4, Block.torchRedstoneActive.blockID,
+ par1World.getBlockMetadata(par2, par3, par4), 3);
+ }
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ if (!this.func_94397_d(par1World, par2, par3, par4, par5)) {
+ boolean var6 = this.isIndirectlyPowered(par1World, par2, par3, par4);
+
+ if (this.torchActive && var6 || !this.torchActive && !var6) {
+ par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, this.tickRate(par1World));
+ }
+ }
+ }
+
+ /**
+ * Returns true if the block is emitting direct/strong redstone power on the
+ * specified side. Args: World, X, Y, Z, side. Note that the side is reversed -
+ * eg it is 1 (up) when checking the bottom of the block.
+ */
+ public int isProvidingStrongPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) {
+ return par5 == 0 ? this.isProvidingWeakPower(par1IBlockAccess, par2, par3, par4, par5) : 0;
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return Block.torchRedstoneActive.blockID;
+ }
+
+ /**
+ * Can this block provide power. Only wire currently seems to have this change
+ * based on its state.
+ */
+ public boolean canProvidePower() {
+ return true;
+ }
+
+ /**
+ * Returns true if the given block ID is equivalent to this one. Example:
+ * redstoneTorchOn matches itself and redstoneTorchOff, and vice versa. Most
+ * blocks only match themselves.
+ */
+ public boolean isAssociatedBlockID(int par1) {
+ return par1 == Block.torchRedstoneIdle.blockID || par1 == Block.torchRedstoneActive.blockID;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockRedstoneWire.java b/sp-server/src/main/java/net/minecraft/src/BlockRedstoneWire.java
new file mode 100644
index 0000000..b5891b3
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockRedstoneWire.java
@@ -0,0 +1,410 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockRedstoneWire extends Block {
+ /**
+ * When false, power transmission methods do not look at other redstone wires.
+ * Used internally during updateCurrentStrength.
+ */
+ private boolean wiresProvidePower = true;
+ private Set blocksNeedingUpdate = new HashSet();
+
+ public BlockRedstoneWire(int par1) {
+ super(par1, Material.circuits);
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.0625F, 1.0F);
+ }
+
+ /**
+ * Returns a bounding box from the pool of bounding boxes (this means this box
+ * can change after the pool has been cleared to be reused)
+ */
+ public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) {
+ return null;
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 5;
+ }
+
+ /**
+ * Checks to see if its valid to put this block at the specified coordinates.
+ * Args: world, x, y, z
+ */
+ public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4) {
+ return par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4)
+ || par1World.getBlockId(par2, par3 - 1, par4) == Block.glowStone.blockID;
+ }
+
+ /**
+ * Sets the strength of the wire current (0-15) for this block based on
+ * neighboring blocks and propagates to neighboring redstone wires
+ */
+ private void updateAndPropagateCurrentStrength(World par1World, int par2, int par3, int par4) {
+ this.calculateCurrentChanges(par1World, par2, par3, par4, par2, par3, par4);
+ ArrayList var5 = new ArrayList(this.blocksNeedingUpdate);
+ this.blocksNeedingUpdate.clear();
+
+ for (int var6 = 0; var6 < var5.size(); ++var6) {
+ ChunkPosition var7 = (ChunkPosition) var5.get(var6);
+ par1World.notifyBlocksOfNeighborChange(var7.x, var7.y, var7.z, this.blockID);
+ }
+ }
+
+ private void calculateCurrentChanges(World par1World, int par2, int par3, int par4, int par5, int par6, int par7) {
+ int var8 = par1World.getBlockMetadata(par2, par3, par4);
+ byte var9 = 0;
+ int var15 = this.getMaxCurrentStrength(par1World, par5, par6, par7, var9);
+ this.wiresProvidePower = false;
+ int var10 = par1World.getStrongestIndirectPower(par2, par3, par4);
+ this.wiresProvidePower = true;
+
+ if (var10 > 0 && var10 > var15 - 1) {
+ var15 = var10;
+ }
+
+ int var11 = 0;
+
+ for (int var12 = 0; var12 < 4; ++var12) {
+ int var13 = par2;
+ int var14 = par4;
+
+ if (var12 == 0) {
+ var13 = par2 - 1;
+ }
+
+ if (var12 == 1) {
+ ++var13;
+ }
+
+ if (var12 == 2) {
+ var14 = par4 - 1;
+ }
+
+ if (var12 == 3) {
+ ++var14;
+ }
+
+ if (var13 != par5 || var14 != par7) {
+ var11 = this.getMaxCurrentStrength(par1World, var13, par3, var14, var11);
+ }
+
+ if (par1World.isBlockNormalCube(var13, par3, var14) && !par1World.isBlockNormalCube(par2, par3 + 1, par4)) {
+ if ((var13 != par5 || var14 != par7) && par3 >= par6) {
+ var11 = this.getMaxCurrentStrength(par1World, var13, par3 + 1, var14, var11);
+ }
+ } else if (!par1World.isBlockNormalCube(var13, par3, var14) && (var13 != par5 || var14 != par7)
+ && par3 <= par6) {
+ var11 = this.getMaxCurrentStrength(par1World, var13, par3 - 1, var14, var11);
+ }
+ }
+
+ if (var11 > var15) {
+ var15 = var11 - 1;
+ } else if (var15 > 0) {
+ --var15;
+ } else {
+ var15 = 0;
+ }
+
+ if (var10 > var15 - 1) {
+ var15 = var10;
+ }
+
+ if (var8 != var15) {
+ par1World.setBlockMetadata(par2, par3, par4, var15, 2);
+ this.blocksNeedingUpdate.add(new ChunkPosition(par2, par3, par4));
+ this.blocksNeedingUpdate.add(new ChunkPosition(par2 - 1, par3, par4));
+ this.blocksNeedingUpdate.add(new ChunkPosition(par2 + 1, par3, par4));
+ this.blocksNeedingUpdate.add(new ChunkPosition(par2, par3 - 1, par4));
+ this.blocksNeedingUpdate.add(new ChunkPosition(par2, par3 + 1, par4));
+ this.blocksNeedingUpdate.add(new ChunkPosition(par2, par3, par4 - 1));
+ this.blocksNeedingUpdate.add(new ChunkPosition(par2, par3, par4 + 1));
+ }
+ }
+
+ /**
+ * Calls World.notifyBlocksOfNeighborChange() for all neighboring blocks, but
+ * only if the given block is a redstone wire.
+ */
+ private void notifyWireNeighborsOfNeighborChange(World par1World, int par2, int par3, int par4) {
+ if (par1World.getBlockId(par2, par3, par4) == this.blockID) {
+ par1World.notifyBlocksOfNeighborChange(par2, par3, par4, this.blockID);
+ par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID);
+ par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID);
+ par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID);
+ par1World.notifyBlocksOfNeighborChange(par2, par3, par4 + 1, this.blockID);
+ par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID);
+ par1World.notifyBlocksOfNeighborChange(par2, par3 + 1, par4, this.blockID);
+ }
+ }
+
+ /**
+ * Called whenever the block is added into the world. Args: world, x, y, z
+ */
+ public void onBlockAdded(World par1World, int par2, int par3, int par4) {
+ super.onBlockAdded(par1World, par2, par3, par4);
+
+ if (!par1World.isRemote) {
+ this.updateAndPropagateCurrentStrength(par1World, par2, par3, par4);
+ par1World.notifyBlocksOfNeighborChange(par2, par3 + 1, par4, this.blockID);
+ par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID);
+ this.notifyWireNeighborsOfNeighborChange(par1World, par2 - 1, par3, par4);
+ this.notifyWireNeighborsOfNeighborChange(par1World, par2 + 1, par3, par4);
+ this.notifyWireNeighborsOfNeighborChange(par1World, par2, par3, par4 - 1);
+ this.notifyWireNeighborsOfNeighborChange(par1World, par2, par3, par4 + 1);
+
+ if (par1World.isBlockNormalCube(par2 - 1, par3, par4)) {
+ this.notifyWireNeighborsOfNeighborChange(par1World, par2 - 1, par3 + 1, par4);
+ } else {
+ this.notifyWireNeighborsOfNeighborChange(par1World, par2 - 1, par3 - 1, par4);
+ }
+
+ if (par1World.isBlockNormalCube(par2 + 1, par3, par4)) {
+ this.notifyWireNeighborsOfNeighborChange(par1World, par2 + 1, par3 + 1, par4);
+ } else {
+ this.notifyWireNeighborsOfNeighborChange(par1World, par2 + 1, par3 - 1, par4);
+ }
+
+ if (par1World.isBlockNormalCube(par2, par3, par4 - 1)) {
+ this.notifyWireNeighborsOfNeighborChange(par1World, par2, par3 + 1, par4 - 1);
+ } else {
+ this.notifyWireNeighborsOfNeighborChange(par1World, par2, par3 - 1, par4 - 1);
+ }
+
+ if (par1World.isBlockNormalCube(par2, par3, par4 + 1)) {
+ this.notifyWireNeighborsOfNeighborChange(par1World, par2, par3 + 1, par4 + 1);
+ } else {
+ this.notifyWireNeighborsOfNeighborChange(par1World, par2, par3 - 1, par4 + 1);
+ }
+ }
+ }
+
+ /**
+ * ejects contained items into the world, and notifies neighbours of an update,
+ * as appropriate
+ */
+ public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) {
+ super.breakBlock(par1World, par2, par3, par4, par5, par6);
+
+ if (!par1World.isRemote) {
+ par1World.notifyBlocksOfNeighborChange(par2, par3 + 1, par4, this.blockID);
+ par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID);
+ par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID);
+ par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID);
+ par1World.notifyBlocksOfNeighborChange(par2, par3, par4 + 1, this.blockID);
+ par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID);
+ this.updateAndPropagateCurrentStrength(par1World, par2, par3, par4);
+ this.notifyWireNeighborsOfNeighborChange(par1World, par2 - 1, par3, par4);
+ this.notifyWireNeighborsOfNeighborChange(par1World, par2 + 1, par3, par4);
+ this.notifyWireNeighborsOfNeighborChange(par1World, par2, par3, par4 - 1);
+ this.notifyWireNeighborsOfNeighborChange(par1World, par2, par3, par4 + 1);
+
+ if (par1World.isBlockNormalCube(par2 - 1, par3, par4)) {
+ this.notifyWireNeighborsOfNeighborChange(par1World, par2 - 1, par3 + 1, par4);
+ } else {
+ this.notifyWireNeighborsOfNeighborChange(par1World, par2 - 1, par3 - 1, par4);
+ }
+
+ if (par1World.isBlockNormalCube(par2 + 1, par3, par4)) {
+ this.notifyWireNeighborsOfNeighborChange(par1World, par2 + 1, par3 + 1, par4);
+ } else {
+ this.notifyWireNeighborsOfNeighborChange(par1World, par2 + 1, par3 - 1, par4);
+ }
+
+ if (par1World.isBlockNormalCube(par2, par3, par4 - 1)) {
+ this.notifyWireNeighborsOfNeighborChange(par1World, par2, par3 + 1, par4 - 1);
+ } else {
+ this.notifyWireNeighborsOfNeighborChange(par1World, par2, par3 - 1, par4 - 1);
+ }
+
+ if (par1World.isBlockNormalCube(par2, par3, par4 + 1)) {
+ this.notifyWireNeighborsOfNeighborChange(par1World, par2, par3 + 1, par4 + 1);
+ } else {
+ this.notifyWireNeighborsOfNeighborChange(par1World, par2, par3 - 1, par4 + 1);
+ }
+ }
+ }
+
+ /**
+ * Returns the current strength at the specified block if it is greater than the
+ * passed value, or the passed value otherwise. Signature: (world, x, y, z,
+ * strength)
+ */
+ private int getMaxCurrentStrength(World par1World, int par2, int par3, int par4, int par5) {
+ if (par1World.getBlockId(par2, par3, par4) != this.blockID) {
+ return par5;
+ } else {
+ int var6 = par1World.getBlockMetadata(par2, par3, par4);
+ return var6 > par5 ? var6 : par5;
+ }
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ if (!par1World.isRemote) {
+ boolean var6 = this.canPlaceBlockAt(par1World, par2, par3, par4);
+
+ if (var6) {
+ this.updateAndPropagateCurrentStrength(par1World, par2, par3, par4);
+ } else {
+ this.dropBlockAsItem(par1World, par2, par3, par4, 0, 0);
+ par1World.setBlockToAir(par2, par3, par4);
+ }
+
+ super.onNeighborBlockChange(par1World, par2, par3, par4, par5);
+ }
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return Item.redstone.itemID;
+ }
+
+ /**
+ * Returns true if the block is emitting direct/strong redstone power on the
+ * specified side. Args: World, X, Y, Z, side. Note that the side is reversed -
+ * eg it is 1 (up) when checking the bottom of the block.
+ */
+ public int isProvidingStrongPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) {
+ return !this.wiresProvidePower ? 0 : this.isProvidingWeakPower(par1IBlockAccess, par2, par3, par4, par5);
+ }
+
+ /**
+ * Returns true if the block is emitting indirect/weak redstone power on the
+ * specified side. If isBlockNormalCube returns true, standard redstone
+ * propagation rules will apply instead and this will not be called. Args:
+ * World, X, Y, Z, side. Note that the side is reversed - eg it is 1 (up) when
+ * checking the bottom of the block.
+ */
+ public int isProvidingWeakPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) {
+ if (!this.wiresProvidePower) {
+ return 0;
+ } else {
+ int var6 = par1IBlockAccess.getBlockMetadata(par2, par3, par4);
+
+ if (var6 == 0) {
+ return 0;
+ } else if (par5 == 1) {
+ return var6;
+ } else {
+ boolean var7 = isPoweredOrRepeater(par1IBlockAccess, par2 - 1, par3, par4, 1)
+ || !par1IBlockAccess.isBlockNormalCube(par2 - 1, par3, par4)
+ && isPoweredOrRepeater(par1IBlockAccess, par2 - 1, par3 - 1, par4, -1);
+ boolean var8 = isPoweredOrRepeater(par1IBlockAccess, par2 + 1, par3, par4, 3)
+ || !par1IBlockAccess.isBlockNormalCube(par2 + 1, par3, par4)
+ && isPoweredOrRepeater(par1IBlockAccess, par2 + 1, par3 - 1, par4, -1);
+ boolean var9 = isPoweredOrRepeater(par1IBlockAccess, par2, par3, par4 - 1, 2)
+ || !par1IBlockAccess.isBlockNormalCube(par2, par3, par4 - 1)
+ && isPoweredOrRepeater(par1IBlockAccess, par2, par3 - 1, par4 - 1, -1);
+ boolean var10 = isPoweredOrRepeater(par1IBlockAccess, par2, par3, par4 + 1, 0)
+ || !par1IBlockAccess.isBlockNormalCube(par2, par3, par4 + 1)
+ && isPoweredOrRepeater(par1IBlockAccess, par2, par3 - 1, par4 + 1, -1);
+
+ if (!par1IBlockAccess.isBlockNormalCube(par2, par3 + 1, par4)) {
+ if (par1IBlockAccess.isBlockNormalCube(par2 - 1, par3, par4)
+ && isPoweredOrRepeater(par1IBlockAccess, par2 - 1, par3 + 1, par4, -1)) {
+ var7 = true;
+ }
+
+ if (par1IBlockAccess.isBlockNormalCube(par2 + 1, par3, par4)
+ && isPoweredOrRepeater(par1IBlockAccess, par2 + 1, par3 + 1, par4, -1)) {
+ var8 = true;
+ }
+
+ if (par1IBlockAccess.isBlockNormalCube(par2, par3, par4 - 1)
+ && isPoweredOrRepeater(par1IBlockAccess, par2, par3 + 1, par4 - 1, -1)) {
+ var9 = true;
+ }
+
+ if (par1IBlockAccess.isBlockNormalCube(par2, par3, par4 + 1)
+ && isPoweredOrRepeater(par1IBlockAccess, par2, par3 + 1, par4 + 1, -1)) {
+ var10 = true;
+ }
+ }
+
+ return !var9 && !var8 && !var7 && !var10 && par5 >= 2 && par5 <= 5 ? var6
+ : (par5 == 2 && var9 && !var7 && !var8 ? var6
+ : (par5 == 3 && var10 && !var7 && !var8 ? var6
+ : (par5 == 4 && var7 && !var9 && !var10 ? var6
+ : (par5 == 5 && var8 && !var9 && !var10 ? var6 : 0))));
+ }
+ }
+ }
+
+ /**
+ * Can this block provide power. Only wire currently seems to have this change
+ * based on its state.
+ */
+ public boolean canProvidePower() {
+ return this.wiresProvidePower;
+ }
+
+ /**
+ * Returns true if redstone wire can connect to the specified block. Params:
+ * World, X, Y, Z, side (not a normal notch-side, this can be 0, 1, 2, 3 or -1)
+ */
+ public static boolean isPowerProviderOrWire(IBlockAccess par0IBlockAccess, int par1, int par2, int par3, int par4) {
+ int var5 = par0IBlockAccess.getBlockId(par1, par2, par3);
+
+ if (var5 == Block.redstoneWire.blockID) {
+ return true;
+ } else if (var5 == 0) {
+ return false;
+ } else if (!Block.redstoneRepeaterIdle.func_94487_f(var5)) {
+ return Block.blocksList[var5].canProvidePower() && par4 != -1;
+ } else {
+ int var6 = par0IBlockAccess.getBlockMetadata(par1, par2, par3);
+ return par4 == (var6 & 3) || par4 == Direction.footInvisibleFaceRemap[var6 & 3];
+ }
+ }
+
+ /**
+ * Returns true if the block coordinate passed can provide power, or is a
+ * redstone wire, or if its a repeater that is powered.
+ */
+ public static boolean isPoweredOrRepeater(IBlockAccess par0IBlockAccess, int par1, int par2, int par3, int par4) {
+ if (isPowerProviderOrWire(par0IBlockAccess, par1, par2, par3, par4)) {
+ return true;
+ } else {
+ int var5 = par0IBlockAccess.getBlockId(par1, par2, par3);
+
+ if (var5 == Block.redstoneRepeaterActive.blockID) {
+ int var6 = par0IBlockAccess.getBlockMetadata(par1, par2, par3);
+ return par4 == (var6 & 3);
+ } else {
+ return false;
+ }
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockReed.java b/sp-server/src/main/java/net/minecraft/src/BlockReed.java
new file mode 100644
index 0000000..c83f161
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockReed.java
@@ -0,0 +1,118 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockReed extends Block {
+ protected BlockReed(int par1) {
+ super(par1, Material.plants);
+ float var2 = 0.375F;
+ this.setBlockBounds(0.5F - var2, 0.0F, 0.5F - var2, 0.5F + var2, 1.0F, 0.5F + var2);
+ this.setTickRandomly(true);
+ }
+
+ /**
+ * Ticks the block if it's been scheduled
+ */
+ public void updateTick(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ if (par1World.isAirBlock(par2, par3 + 1, par4)) {
+ int var6;
+
+ for (var6 = 1; par1World.getBlockId(par2, par3 - var6, par4) == this.blockID; ++var6) {
+ ;
+ }
+
+ if (var6 < 3) {
+ int var7 = par1World.getBlockMetadata(par2, par3, par4);
+
+ if (var7 == 15) {
+ par1World.setBlock(par2, par3 + 1, par4, this.blockID);
+ par1World.setBlockMetadata(par2, par3, par4, 0, 4);
+ } else {
+ par1World.setBlockMetadata(par2, par3, par4, var7 + 1, 4);
+ }
+ }
+ }
+ }
+
+ /**
+ * Checks to see if its valid to put this block at the specified coordinates.
+ * Args: world, x, y, z
+ */
+ public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4) {
+ int var5 = par1World.getBlockId(par2, par3 - 1, par4);
+ return var5 == this.blockID ? true
+ : (var5 != Block.grass.blockID && var5 != Block.dirt.blockID && var5 != Block.sand.blockID ? false
+ : (par1World.getBlockMaterial(par2 - 1, par3 - 1, par4) == Material.water ? true
+ : (par1World.getBlockMaterial(par2 + 1, par3 - 1, par4) == Material.water ? true
+ : (par1World.getBlockMaterial(par2, par3 - 1, par4 - 1) == Material.water ? true
+ : par1World.getBlockMaterial(par2, par3 - 1,
+ par4 + 1) == Material.water))));
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ this.checkBlockCoordValid(par1World, par2, par3, par4);
+ }
+
+ /**
+ * Checks if current block pos is valid, if not, breaks the block as dropable
+ * item. Used for reed and cactus.
+ */
+ protected final void checkBlockCoordValid(World par1World, int par2, int par3, int par4) {
+ if (!this.canBlockStay(par1World, par2, par3, par4)) {
+ this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
+ par1World.setBlockToAir(par2, par3, par4);
+ }
+ }
+
+ /**
+ * Can this block stay at this position. Similar to canPlaceBlockAt except gets
+ * checked often with plants.
+ */
+ public boolean canBlockStay(World par1World, int par2, int par3, int par4) {
+ return this.canPlaceBlockAt(par1World, par2, par3, par4);
+ }
+
+ /**
+ * Returns a bounding box from the pool of bounding boxes (this means this box
+ * can change after the pool has been cleared to be reused)
+ */
+ public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) {
+ return null;
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return Item.reed.itemID;
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 1;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockSand.java b/sp-server/src/main/java/net/minecraft/src/BlockSand.java
new file mode 100644
index 0000000..856d466
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockSand.java
@@ -0,0 +1,108 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockSand extends Block {
+ /** Do blocks fall instantly to where they stop or do they fall over time */
+ public static boolean fallInstantly = false;
+
+ public BlockSand(int par1) {
+ super(par1, Material.sand);
+ this.setCreativeTab(CreativeTabs.tabBlock);
+ }
+
+ public BlockSand(int par1, Material par2Material) {
+ super(par1, par2Material);
+ }
+
+ /**
+ * Called whenever the block is added into the world. Args: world, x, y, z
+ */
+ public void onBlockAdded(World par1World, int par2, int par3, int par4) {
+ par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, this.tickRate(par1World));
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, this.tickRate(par1World));
+ }
+
+ /**
+ * Ticks the block if it's been scheduled
+ */
+ public void updateTick(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ if (!par1World.isRemote) {
+ this.tryToFall(par1World, par2, par3, par4);
+ }
+ }
+
+ /**
+ * If there is space to fall below will start this block falling
+ */
+ private void tryToFall(World par1World, int par2, int par3, int par4) {
+ if (canFallBelow(par1World, par2, par3 - 1, par4) && par3 >= 0) {
+ byte var8 = 32;
+
+ if (!fallInstantly && par1World.checkChunksExist(par2 - var8, par3 - var8, par4 - var8, par2 + var8,
+ par3 + var8, par4 + var8)) {
+ if (!par1World.isRemote) {
+ EntityFallingSand var9 = new EntityFallingSand(par1World, (double) ((float) par2 + 0.5F),
+ (double) ((float) par3 + 0.5F), (double) ((float) par4 + 0.5F), this.blockID,
+ par1World.getBlockMetadata(par2, par3, par4));
+ this.onStartFalling(var9);
+ par1World.spawnEntityInWorld(var9);
+ }
+ } else {
+ par1World.setBlockToAir(par2, par3, par4);
+
+ while (canFallBelow(par1World, par2, par3 - 1, par4) && par3 > 0) {
+ --par3;
+ }
+
+ if (par3 > 0) {
+ par1World.setBlock(par2, par3, par4, this.blockID);
+ }
+ }
+ }
+ }
+
+ /**
+ * Called when the falling block entity for this block is created
+ */
+ protected void onStartFalling(EntityFallingSand par1EntityFallingSand) {
+ }
+
+ /**
+ * How many world ticks before ticking
+ */
+ public int tickRate(World par1World) {
+ return 2;
+ }
+
+ /**
+ * Checks to see if the sand can fall into the block below it
+ */
+ public static boolean canFallBelow(World par0World, int par1, int par2, int par3) {
+ int var4 = par0World.getBlockId(par1, par2, par3);
+
+ if (var4 == 0) {
+ return true;
+ } else if (var4 == Block.fire.blockID) {
+ return true;
+ } else {
+ Material var5 = Block.blocksList[var4].blockMaterial;
+ return var5 == Material.water ? true : var5 == Material.lava;
+ }
+ }
+
+ /**
+ * Called when the falling block entity for this block hits the ground and turns
+ * back into a block
+ */
+ public void onFinishFalling(World par1World, int par2, int par3, int par4, int par5) {
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockSandStone.java b/sp-server/src/main/java/net/minecraft/src/BlockSandStone.java
new file mode 100644
index 0000000..32b26d4
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockSandStone.java
@@ -0,0 +1,19 @@
+package net.minecraft.src;
+
+public class BlockSandStone extends Block {
+ public static final String[] SAND_STONE_TYPES = new String[] { "default", "chiseled", "smooth" };
+ private static final String[] field_94405_b = new String[] { "sandstone_side", "sandstone_carved",
+ "sandstone_smooth" };
+
+ public BlockSandStone(int par1) {
+ super(par1, Material.rock);
+ this.setCreativeTab(CreativeTabs.tabBlock);
+ }
+
+ /**
+ * Determines the damage on the item the block drops. Used in cloth and wood.
+ */
+ public int damageDropped(int par1) {
+ return par1;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockSapling.java b/sp-server/src/main/java/net/minecraft/src/BlockSapling.java
new file mode 100644
index 0000000..04d25cf
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockSapling.java
@@ -0,0 +1,120 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockSapling extends BlockFlower {
+ public static final String[] WOOD_TYPES = new String[] { "oak", "spruce", "birch", "jungle" };
+ private static final String[] field_94370_b = new String[] { "sapling", "sapling_spruce", "sapling_birch",
+ "sapling_jungle" };
+
+ protected BlockSapling(int par1) {
+ super(par1);
+ float var2 = 0.4F;
+ this.setBlockBounds(0.5F - var2, 0.0F, 0.5F - var2, 0.5F + var2, var2 * 2.0F, 0.5F + var2);
+ this.setCreativeTab(CreativeTabs.tabDecorations);
+ }
+
+ /**
+ * Ticks the block if it's been scheduled
+ */
+ public void updateTick(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ if (!par1World.isRemote) {
+ super.updateTick(par1World, par2, par3, par4, par5Random);
+
+ if (par1World.getBlockLightValue(par2, par3 + 1, par4) >= 9 && par5Random.nextInt(7) == 0) {
+ this.markOrGrowMarked(par1World, par2, par3, par4, par5Random);
+ }
+ }
+ }
+
+ public void markOrGrowMarked(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ int var6 = par1World.getBlockMetadata(par2, par3, par4);
+
+ if ((var6 & 8) == 0) {
+ par1World.setBlockMetadata(par2, par3, par4, var6 | 8, 4);
+ } else {
+ this.growTree(par1World, par2, par3, par4, par5Random);
+ }
+ }
+
+ /**
+ * Attempts to grow a sapling into a tree
+ */
+ public void growTree(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ int var6 = par1World.getBlockMetadata(par2, par3, par4) & 3;
+ Object var7 = null;
+ int var8 = 0;
+ int var9 = 0;
+ boolean var10 = false;
+
+ if (var6 == 1) {
+ var7 = new WorldGenTaiga2(true);
+ } else if (var6 == 2) {
+ var7 = new WorldGenForest(true);
+ } else if (var6 == 3) {
+ for (var8 = 0; var8 >= -1; --var8) {
+ for (var9 = 0; var9 >= -1; --var9) {
+ if (this.isSameSapling(par1World, par2 + var8, par3, par4 + var9, 3)
+ && this.isSameSapling(par1World, par2 + var8 + 1, par3, par4 + var9, 3)
+ && this.isSameSapling(par1World, par2 + var8, par3, par4 + var9 + 1, 3)
+ && this.isSameSapling(par1World, par2 + var8 + 1, par3, par4 + var9 + 1, 3)) {
+ var7 = new WorldGenHugeTrees(true, 10 + par5Random.nextInt(20), 3, 3);
+ var10 = true;
+ break;
+ }
+ }
+
+ if (var7 != null) {
+ break;
+ }
+ }
+
+ if (var7 == null) {
+ var9 = 0;
+ var8 = 0;
+ var7 = new WorldGenTrees(true, 4 + par5Random.nextInt(7), 3, 3, false);
+ }
+ } else {
+ var7 = new WorldGenTrees(true);
+
+ if (par5Random.nextInt(10) == 0) {
+ var7 = new WorldGenBigTree(true);
+ }
+ }
+
+ if (var10) {
+ par1World.setBlock(par2 + var8, par3, par4 + var9, 0, 0, 4);
+ par1World.setBlock(par2 + var8 + 1, par3, par4 + var9, 0, 0, 4);
+ par1World.setBlock(par2 + var8, par3, par4 + var9 + 1, 0, 0, 4);
+ par1World.setBlock(par2 + var8 + 1, par3, par4 + var9 + 1, 0, 0, 4);
+ } else {
+ par1World.setBlock(par2, par3, par4, 0, 0, 4);
+ }
+
+ if (!((WorldGenerator) var7).generate(par1World, par5Random, par2 + var8, par3, par4 + var9)) {
+ if (var10) {
+ par1World.setBlock(par2 + var8, par3, par4 + var9, this.blockID, var6, 4);
+ par1World.setBlock(par2 + var8 + 1, par3, par4 + var9, this.blockID, var6, 4);
+ par1World.setBlock(par2 + var8, par3, par4 + var9 + 1, this.blockID, var6, 4);
+ par1World.setBlock(par2 + var8 + 1, par3, par4 + var9 + 1, this.blockID, var6, 4);
+ } else {
+ par1World.setBlock(par2, par3, par4, this.blockID, var6, 4);
+ }
+ }
+ }
+
+ /**
+ * Determines if the same sapling is present at the given location.
+ */
+ public boolean isSameSapling(World par1World, int par2, int par3, int par4, int par5) {
+ return par1World.getBlockId(par2, par3, par4) == this.blockID
+ && (par1World.getBlockMetadata(par2, par3, par4) & 3) == par5;
+ }
+
+ /**
+ * Determines the damage on the item the block drops. Used in cloth and wood.
+ */
+ public int damageDropped(int par1) {
+ return par1 & 3;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockSign.java b/sp-server/src/main/java/net/minecraft/src/BlockSign.java
new file mode 100644
index 0000000..ae99dd7
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockSign.java
@@ -0,0 +1,146 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockSign extends BlockContainer {
+ private Class signEntityClass;
+
+ /** Whether this is a freestanding sign or a wall-mounted sign */
+ private boolean isFreestanding;
+
+ protected BlockSign(int par1, Class par2Class, boolean par3) {
+ super(par1, Material.wood);
+ this.isFreestanding = par3;
+ this.signEntityClass = par2Class;
+ float var4 = 0.25F;
+ float var5 = 1.0F;
+ this.setBlockBounds(0.5F - var4, 0.0F, 0.5F - var4, 0.5F + var4, var5, 0.5F + var4);
+ }
+
+ /**
+ * Returns a bounding box from the pool of bounding boxes (this means this box
+ * can change after the pool has been cleared to be reused)
+ */
+ public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) {
+ return null;
+ }
+
+ /**
+ * Updates the blocks bounds based on its current state. Args: world, x, y, z
+ */
+ public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ if (!this.isFreestanding) {
+ int var5 = par1IBlockAccess.getBlockMetadata(par2, par3, par4);
+ float var6 = 0.28125F;
+ float var7 = 0.78125F;
+ float var8 = 0.0F;
+ float var9 = 1.0F;
+ float var10 = 0.125F;
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
+
+ if (var5 == 2) {
+ this.setBlockBounds(var8, var6, 1.0F - var10, var9, var7, 1.0F);
+ }
+
+ if (var5 == 3) {
+ this.setBlockBounds(var8, var6, 0.0F, var9, var7, var10);
+ }
+
+ if (var5 == 4) {
+ this.setBlockBounds(1.0F - var10, var6, var8, 1.0F, var7, var9);
+ }
+
+ if (var5 == 5) {
+ this.setBlockBounds(0.0F, var6, var8, var10, var7, var9);
+ }
+ }
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return -1;
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ public boolean getBlocksMovement(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ return true;
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * Returns a new instance of a block's tile entity class. Called on placing the
+ * block.
+ */
+ public TileEntity createNewTileEntity(World par1World) {
+ try {
+ return (TileEntity) this.signEntityClass.newInstance();
+ } catch (Exception var3) {
+ throw new RuntimeException(var3);
+ }
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return Item.sign.itemID;
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ boolean var6 = false;
+
+ if (this.isFreestanding) {
+ if (!par1World.getBlockMaterial(par2, par3 - 1, par4).isSolid()) {
+ var6 = true;
+ }
+ } else {
+ int var7 = par1World.getBlockMetadata(par2, par3, par4);
+ var6 = true;
+
+ if (var7 == 2 && par1World.getBlockMaterial(par2, par3, par4 + 1).isSolid()) {
+ var6 = false;
+ }
+
+ if (var7 == 3 && par1World.getBlockMaterial(par2, par3, par4 - 1).isSolid()) {
+ var6 = false;
+ }
+
+ if (var7 == 4 && par1World.getBlockMaterial(par2 + 1, par3, par4).isSolid()) {
+ var6 = false;
+ }
+
+ if (var7 == 5 && par1World.getBlockMaterial(par2 - 1, par3, par4).isSolid()) {
+ var6 = false;
+ }
+ }
+
+ if (var6) {
+ this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
+ par1World.setBlockToAir(par2, par3, par4);
+ }
+
+ super.onNeighborBlockChange(par1World, par2, par3, par4, par5);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockSilverfish.java b/sp-server/src/main/java/net/minecraft/src/BlockSilverfish.java
new file mode 100644
index 0000000..45e4a5d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockSilverfish.java
@@ -0,0 +1,79 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockSilverfish extends Block {
+ /** Block names that can be a silverfish stone. */
+ public static final String[] silverfishStoneTypes = new String[] { "stone", "cobble", "brick" };
+
+ public BlockSilverfish(int par1) {
+ super(par1, Material.clay);
+ this.setHardness(0.0F);
+ this.setCreativeTab(CreativeTabs.tabDecorations);
+ }
+
+ /**
+ * Called right before the block is destroyed by a player. Args: world, x, y, z,
+ * metaData
+ */
+ public void onBlockDestroyedByPlayer(World par1World, int par2, int par3, int par4, int par5) {
+ if (!par1World.isRemote) {
+ EntitySilverfish var6 = new EntitySilverfish(par1World);
+ var6.setLocationAndAngles((double) par2 + 0.5D, (double) par3, (double) par4 + 0.5D, 0.0F, 0.0F);
+ par1World.spawnEntityInWorld(var6);
+ var6.spawnExplosionParticle();
+ }
+
+ super.onBlockDestroyedByPlayer(par1World, par2, par3, par4, par5);
+ }
+
+ /**
+ * Returns the quantity of items to drop on block destruction.
+ */
+ public int quantityDropped(EaglercraftRandom par1Random) {
+ return 0;
+ }
+
+ /**
+ * Gets the blockID of the block this block is pretending to be according to
+ * this block's metadata.
+ */
+ public static boolean getPosingIdByMetadata(int par0) {
+ return par0 == Block.stone.blockID || par0 == Block.cobblestone.blockID || par0 == Block.stoneBrick.blockID;
+ }
+
+ /**
+ * Returns the metadata to use when a Silverfish hides in the block. Sets the
+ * block to BlockSilverfish with this metadata. It changes the displayed texture
+ * client side to look like a normal block.
+ */
+ public static int getMetadataForBlockType(int par0) {
+ return par0 == Block.cobblestone.blockID ? 1 : (par0 == Block.stoneBrick.blockID ? 2 : 0);
+ }
+
+ /**
+ * Returns an item stack containing a single instance of the current block type.
+ * 'i' is the block's subtype/damage and is ignored for blocks which do not
+ * support subtypes. Blocks which cannot be harvested should return null.
+ */
+ protected ItemStack createStackedBlock(int par1) {
+ Block var2 = Block.stone;
+
+ if (par1 == 1) {
+ var2 = Block.cobblestone;
+ }
+
+ if (par1 == 2) {
+ var2 = Block.stoneBrick;
+ }
+
+ return new ItemStack(var2);
+ }
+
+ /**
+ * Get the block's damage value (for use with pick block).
+ */
+ public int getDamageValue(World par1World, int par2, int par3, int par4) {
+ return par1World.getBlockMetadata(par2, par3, par4);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockSkull.java b/sp-server/src/main/java/net/minecraft/src/BlockSkull.java
new file mode 100644
index 0000000..fb3b8fa
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockSkull.java
@@ -0,0 +1,267 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockSkull extends BlockContainer {
+ protected BlockSkull(int par1) {
+ super(par1, Material.circuits);
+ this.setBlockBounds(0.25F, 0.0F, 0.25F, 0.75F, 0.5F, 0.75F);
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return -1;
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ /**
+ * Updates the blocks bounds based on its current state. Args: world, x, y, z
+ */
+ public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ int var5 = par1IBlockAccess.getBlockMetadata(par2, par3, par4) & 7;
+
+ switch (var5) {
+ case 1:
+ default:
+ this.setBlockBounds(0.25F, 0.0F, 0.25F, 0.75F, 0.5F, 0.75F);
+ break;
+
+ case 2:
+ this.setBlockBounds(0.25F, 0.25F, 0.5F, 0.75F, 0.75F, 1.0F);
+ break;
+
+ case 3:
+ this.setBlockBounds(0.25F, 0.25F, 0.0F, 0.75F, 0.75F, 0.5F);
+ break;
+
+ case 4:
+ this.setBlockBounds(0.5F, 0.25F, 0.25F, 1.0F, 0.75F, 0.75F);
+ break;
+
+ case 5:
+ this.setBlockBounds(0.0F, 0.25F, 0.25F, 0.5F, 0.75F, 0.75F);
+ }
+ }
+
+ /**
+ * Returns a bounding box from the pool of bounding boxes (this means this box
+ * can change after the pool has been cleared to be reused)
+ */
+ public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) {
+ this.setBlockBoundsBasedOnState(par1World, par2, par3, par4);
+ return super.getCollisionBoundingBoxFromPool(par1World, par2, par3, par4);
+ }
+
+ /**
+ * Called when the block is placed in the world.
+ */
+ public void onBlockPlacedBy(World par1World, int par2, int par3, int par4, EntityLiving par5EntityLiving,
+ ItemStack par6ItemStack) {
+ int var7 = MathHelper.floor_double((double) (par5EntityLiving.rotationYaw * 4.0F / 360.0F) + 2.5D) & 3;
+ par1World.setBlockMetadata(par2, par3, par4, var7, 2);
+ }
+
+ /**
+ * Returns a new instance of a block's tile entity class. Called on placing the
+ * block.
+ */
+ public TileEntity createNewTileEntity(World par1World) {
+ return new TileEntitySkull();
+ }
+
+ /**
+ * Get the block's damage value (for use with pick block).
+ */
+ public int getDamageValue(World par1World, int par2, int par3, int par4) {
+ TileEntity var5 = par1World.getBlockTileEntity(par2, par3, par4);
+ return var5 != null && var5 instanceof TileEntitySkull ? ((TileEntitySkull) var5).getSkullType()
+ : super.getDamageValue(par1World, par2, par3, par4);
+ }
+
+ /**
+ * Determines the damage on the item the block drops. Used in cloth and wood.
+ */
+ public int damageDropped(int par1) {
+ return par1;
+ }
+
+ /**
+ * Drops the block items with a specified chance of dropping the specified items
+ */
+ public void dropBlockAsItemWithChance(World par1World, int par2, int par3, int par4, int par5, float par6,
+ int par7) {
+ }
+
+ /**
+ * Called when the block is attempted to be harvested
+ */
+ public void onBlockHarvested(World par1World, int par2, int par3, int par4, int par5,
+ EntityPlayer par6EntityPlayer) {
+ if (par6EntityPlayer.capabilities.isCreativeMode) {
+ par5 |= 8;
+ par1World.setBlockMetadata(par2, par3, par4, par5, 4);
+ }
+
+ super.onBlockHarvested(par1World, par2, par3, par4, par5, par6EntityPlayer);
+ }
+
+ /**
+ * ejects contained items into the world, and notifies neighbours of an update,
+ * as appropriate
+ */
+ public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) {
+ if (!par1World.isRemote) {
+ if ((par6 & 8) == 0) {
+ ItemStack var7 = new ItemStack(Item.skull.itemID, 1, this.getDamageValue(par1World, par2, par3, par4));
+ TileEntitySkull var8 = (TileEntitySkull) par1World.getBlockTileEntity(par2, par3, par4);
+
+ if (var8.getSkullType() == 3 && var8.getExtraType() != null && var8.getExtraType().length() > 0) {
+ var7.setTagCompound(new NBTTagCompound());
+ var7.getTagCompound().setString("SkullOwner", var8.getExtraType());
+ }
+
+ this.dropBlockAsItem_do(par1World, par2, par3, par4, var7);
+ }
+
+ super.breakBlock(par1World, par2, par3, par4, par5, par6);
+ }
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return Item.skull.itemID;
+ }
+
+ /**
+ * This method attempts to create a wither at the given location and skull
+ */
+ public void makeWither(World par1World, int par2, int par3, int par4, TileEntitySkull par5TileEntitySkull) {
+ if (par5TileEntitySkull.getSkullType() == 1 && par3 >= 2 && par1World.difficultySetting > 0
+ && !par1World.isRemote) {
+ int var6 = Block.slowSand.blockID;
+ int var7;
+ EntityWither var8;
+ int var9;
+
+ for (var7 = -2; var7 <= 0; ++var7) {
+ if (par1World.getBlockId(par2, par3 - 1, par4 + var7) == var6
+ && par1World.getBlockId(par2, par3 - 1, par4 + var7 + 1) == var6
+ && par1World.getBlockId(par2, par3 - 2, par4 + var7 + 1) == var6
+ && par1World.getBlockId(par2, par3 - 1, par4 + var7 + 2) == var6
+ && this.func_82528_d(par1World, par2, par3, par4 + var7, 1)
+ && this.func_82528_d(par1World, par2, par3, par4 + var7 + 1, 1)
+ && this.func_82528_d(par1World, par2, par3, par4 + var7 + 2, 1)) {
+ par1World.setBlockMetadata(par2, par3, par4 + var7, 8, 2);
+ par1World.setBlockMetadata(par2, par3, par4 + var7 + 1, 8, 2);
+ par1World.setBlockMetadata(par2, par3, par4 + var7 + 2, 8, 2);
+ par1World.setBlock(par2, par3, par4 + var7, 0, 0, 2);
+ par1World.setBlock(par2, par3, par4 + var7 + 1, 0, 0, 2);
+ par1World.setBlock(par2, par3, par4 + var7 + 2, 0, 0, 2);
+ par1World.setBlock(par2, par3 - 1, par4 + var7, 0, 0, 2);
+ par1World.setBlock(par2, par3 - 1, par4 + var7 + 1, 0, 0, 2);
+ par1World.setBlock(par2, par3 - 1, par4 + var7 + 2, 0, 0, 2);
+ par1World.setBlock(par2, par3 - 2, par4 + var7 + 1, 0, 0, 2);
+
+ if (!par1World.isRemote) {
+ var8 = new EntityWither(par1World);
+ var8.setLocationAndAngles((double) par2 + 0.5D, (double) par3 - 1.45D,
+ (double) (par4 + var7) + 1.5D, 90.0F, 0.0F);
+ var8.renderYawOffset = 90.0F;
+ var8.func_82206_m();
+ par1World.spawnEntityInWorld(var8);
+ }
+
+ for (var9 = 0; var9 < 120; ++var9) {
+ par1World.spawnParticle("snowballpoof", (double) par2 + par1World.rand.nextDouble(),
+ (double) (par3 - 2) + par1World.rand.nextDouble() * 3.9D,
+ (double) (par4 + var7 + 1) + par1World.rand.nextDouble(), 0.0D, 0.0D, 0.0D);
+ }
+
+ par1World.notifyBlockChange(par2, par3, par4 + var7, 0);
+ par1World.notifyBlockChange(par2, par3, par4 + var7 + 1, 0);
+ par1World.notifyBlockChange(par2, par3, par4 + var7 + 2, 0);
+ par1World.notifyBlockChange(par2, par3 - 1, par4 + var7, 0);
+ par1World.notifyBlockChange(par2, par3 - 1, par4 + var7 + 1, 0);
+ par1World.notifyBlockChange(par2, par3 - 1, par4 + var7 + 2, 0);
+ par1World.notifyBlockChange(par2, par3 - 2, par4 + var7 + 1, 0);
+ return;
+ }
+ }
+
+ for (var7 = -2; var7 <= 0; ++var7) {
+ if (par1World.getBlockId(par2 + var7, par3 - 1, par4) == var6
+ && par1World.getBlockId(par2 + var7 + 1, par3 - 1, par4) == var6
+ && par1World.getBlockId(par2 + var7 + 1, par3 - 2, par4) == var6
+ && par1World.getBlockId(par2 + var7 + 2, par3 - 1, par4) == var6
+ && this.func_82528_d(par1World, par2 + var7, par3, par4, 1)
+ && this.func_82528_d(par1World, par2 + var7 + 1, par3, par4, 1)
+ && this.func_82528_d(par1World, par2 + var7 + 2, par3, par4, 1)) {
+ par1World.setBlockMetadata(par2 + var7, par3, par4, 8, 2);
+ par1World.setBlockMetadata(par2 + var7 + 1, par3, par4, 8, 2);
+ par1World.setBlockMetadata(par2 + var7 + 2, par3, par4, 8, 2);
+ par1World.setBlock(par2 + var7, par3, par4, 0, 0, 2);
+ par1World.setBlock(par2 + var7 + 1, par3, par4, 0, 0, 2);
+ par1World.setBlock(par2 + var7 + 2, par3, par4, 0, 0, 2);
+ par1World.setBlock(par2 + var7, par3 - 1, par4, 0, 0, 2);
+ par1World.setBlock(par2 + var7 + 1, par3 - 1, par4, 0, 0, 2);
+ par1World.setBlock(par2 + var7 + 2, par3 - 1, par4, 0, 0, 2);
+ par1World.setBlock(par2 + var7 + 1, par3 - 2, par4, 0, 0, 2);
+
+ if (!par1World.isRemote) {
+ var8 = new EntityWither(par1World);
+ var8.setLocationAndAngles((double) (par2 + var7) + 1.5D, (double) par3 - 1.45D,
+ (double) par4 + 0.5D, 0.0F, 0.0F);
+ var8.func_82206_m();
+ par1World.spawnEntityInWorld(var8);
+ }
+
+ for (var9 = 0; var9 < 120; ++var9) {
+ par1World.spawnParticle("snowballpoof",
+ (double) (par2 + var7 + 1) + par1World.rand.nextDouble(),
+ (double) (par3 - 2) + par1World.rand.nextDouble() * 3.9D,
+ (double) par4 + par1World.rand.nextDouble(), 0.0D, 0.0D, 0.0D);
+ }
+
+ par1World.notifyBlockChange(par2 + var7, par3, par4, 0);
+ par1World.notifyBlockChange(par2 + var7 + 1, par3, par4, 0);
+ par1World.notifyBlockChange(par2 + var7 + 2, par3, par4, 0);
+ par1World.notifyBlockChange(par2 + var7, par3 - 1, par4, 0);
+ par1World.notifyBlockChange(par2 + var7 + 1, par3 - 1, par4, 0);
+ par1World.notifyBlockChange(par2 + var7 + 2, par3 - 1, par4, 0);
+ par1World.notifyBlockChange(par2 + var7 + 1, par3 - 2, par4, 0);
+ return;
+ }
+ }
+ }
+ }
+
+ private boolean func_82528_d(World par1World, int par2, int par3, int par4, int par5) {
+ if (par1World.getBlockId(par2, par3, par4) != this.blockID) {
+ return false;
+ } else {
+ TileEntity var6 = par1World.getBlockTileEntity(par2, par3, par4);
+ return var6 != null && var6 instanceof TileEntitySkull ? ((TileEntitySkull) var6).getSkullType() == par5
+ : false;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockSnow.java b/sp-server/src/main/java/net/minecraft/src/BlockSnow.java
new file mode 100644
index 0000000..0cfa2dc
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockSnow.java
@@ -0,0 +1,136 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockSnow extends Block {
+ protected BlockSnow(int par1) {
+ super(par1, Material.snow);
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.125F, 1.0F);
+ this.setTickRandomly(true);
+ this.setCreativeTab(CreativeTabs.tabDecorations);
+ this.setBlockBoundsForSnowDepth(0);
+ }
+
+ /**
+ * Returns a bounding box from the pool of bounding boxes (this means this box
+ * can change after the pool has been cleared to be reused)
+ */
+ public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) {
+ int var5 = par1World.getBlockMetadata(par2, par3, par4) & 7;
+ float var6 = 0.125F;
+ return AxisAlignedBB.getAABBPool().getAABB((double) par2 + this.minX, (double) par3 + this.minY,
+ (double) par4 + this.minZ, (double) par2 + this.maxX, (double) ((float) par3 + (float) var5 * var6),
+ (double) par4 + this.maxZ);
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ /**
+ * Sets the block's bounds for rendering it as an item
+ */
+ public void setBlockBoundsForItemRender() {
+ this.setBlockBoundsForSnowDepth(0);
+ }
+
+ /**
+ * Updates the blocks bounds based on its current state. Args: world, x, y, z
+ */
+ public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ this.setBlockBoundsForSnowDepth(par1IBlockAccess.getBlockMetadata(par2, par3, par4));
+ }
+
+ /**
+ * calls setBlockBounds based on the depth of the snow. Int is any values
+ * 0x0-0x7, usually this blocks metadata.
+ */
+ protected void setBlockBoundsForSnowDepth(int par1) {
+ int var2 = par1 & 7;
+ float var3 = (float) (2 * (1 + var2)) / 16.0F;
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, var3, 1.0F);
+ }
+
+ /**
+ * Checks to see if its valid to put this block at the specified coordinates.
+ * Args: world, x, y, z
+ */
+ public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4) {
+ int var5 = par1World.getBlockId(par2, par3 - 1, par4);
+ return var5 == 0 ? false
+ : (var5 == this.blockID && (par1World.getBlockMetadata(par2, par3 - 1, par4) & 7) == 7 ? true
+ : (var5 != Block.leaves.blockID && !Block.blocksList[var5].isOpaqueCube() ? false
+ : par1World.getBlockMaterial(par2, par3 - 1, par4).blocksMovement()));
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ this.canSnowStay(par1World, par2, par3, par4);
+ }
+
+ /**
+ * Checks if this snow block can stay at this location.
+ */
+ private boolean canSnowStay(World par1World, int par2, int par3, int par4) {
+ if (!this.canPlaceBlockAt(par1World, par2, par3, par4)) {
+ this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
+ par1World.setBlockToAir(par2, par3, par4);
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * Called when the player destroys a block with an item that can harvest it. (i,
+ * j, k) are the coordinates of the block and l is the block's subtype/damage.
+ */
+ public void harvestBlock(World par1World, EntityPlayer par2EntityPlayer, int par3, int par4, int par5, int par6) {
+ int var7 = Item.snowball.itemID;
+ int var8 = par6 & 7;
+ this.dropBlockAsItem_do(par1World, par3, par4, par5, new ItemStack(var7, var8 + 1, 0));
+ par1World.setBlockToAir(par3, par4, par5);
+ par2EntityPlayer.addStat(StatList.mineBlockStatArray[this.blockID], 1);
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return Item.snowball.itemID;
+ }
+
+ /**
+ * Returns the quantity of items to drop on block destruction.
+ */
+ public int quantityDropped(EaglercraftRandom par1Random) {
+ return 0;
+ }
+
+ /**
+ * Ticks the block if it's been scheduled
+ */
+ public void updateTick(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ if (par1World.getSavedLightValue(EnumSkyBlock.Block, par2, par3, par4) > 11) {
+ this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
+ par1World.setBlockToAir(par2, par3, par4);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockSnowBlock.java b/sp-server/src/main/java/net/minecraft/src/BlockSnowBlock.java
new file mode 100644
index 0000000..f1589c4
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockSnowBlock.java
@@ -0,0 +1,35 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockSnowBlock extends Block {
+ protected BlockSnowBlock(int par1) {
+ super(par1, Material.craftedSnow);
+ this.setTickRandomly(true);
+ this.setCreativeTab(CreativeTabs.tabBlock);
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return Item.snowball.itemID;
+ }
+
+ /**
+ * Returns the quantity of items to drop on block destruction.
+ */
+ public int quantityDropped(EaglercraftRandom par1Random) {
+ return 4;
+ }
+
+ /**
+ * Ticks the block if it's been scheduled
+ */
+ public void updateTick(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ if (par1World.getSavedLightValue(EnumSkyBlock.Block, par2, par3, par4) > 11) {
+ this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
+ par1World.setBlockToAir(par2, par3, par4);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockSoulSand.java b/sp-server/src/main/java/net/minecraft/src/BlockSoulSand.java
new file mode 100644
index 0000000..a1f23cc
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockSoulSand.java
@@ -0,0 +1,27 @@
+package net.minecraft.src;
+
+public class BlockSoulSand extends Block {
+ public BlockSoulSand(int par1) {
+ super(par1, Material.sand);
+ this.setCreativeTab(CreativeTabs.tabBlock);
+ }
+
+ /**
+ * Returns a bounding box from the pool of bounding boxes (this means this box
+ * can change after the pool has been cleared to be reused)
+ */
+ public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) {
+ float var5 = 0.125F;
+ return AxisAlignedBB.getAABBPool().getAABB((double) par2, (double) par3, (double) par4, (double) (par2 + 1),
+ (double) ((float) (par3 + 1) - var5), (double) (par4 + 1));
+ }
+
+ /**
+ * Triggered whenever an entity collides with this block (enters into the
+ * block). Args: world, x, y, z, entity
+ */
+ public void onEntityCollidedWithBlock(World par1World, int par2, int par3, int par4, Entity par5Entity) {
+ par5Entity.motionX *= 0.4D;
+ par5Entity.motionZ *= 0.4D;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockSourceImpl.java b/sp-server/src/main/java/net/minecraft/src/BlockSourceImpl.java
new file mode 100644
index 0000000..f114e1a
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockSourceImpl.java
@@ -0,0 +1,51 @@
+package net.minecraft.src;
+
+public class BlockSourceImpl implements IBlockSource {
+ private final World worldObj;
+ private final int xPos;
+ private final int yPos;
+ private final int zPos;
+
+ public BlockSourceImpl(World par1World, int par2, int par3, int par4) {
+ this.worldObj = par1World;
+ this.xPos = par2;
+ this.yPos = par3;
+ this.zPos = par4;
+ }
+
+ public World getWorld() {
+ return this.worldObj;
+ }
+
+ public double getX() {
+ return (double) this.xPos + 0.5D;
+ }
+
+ public double getY() {
+ return (double) this.yPos + 0.5D;
+ }
+
+ public double getZ() {
+ return (double) this.zPos + 0.5D;
+ }
+
+ public int getXInt() {
+ return this.xPos;
+ }
+
+ public int getYInt() {
+ return this.yPos;
+ }
+
+ public int getZInt() {
+ return this.zPos;
+ }
+
+ public int getBlockMetadata() {
+ return this.worldObj.getBlockMetadata(this.xPos, this.yPos, this.zPos);
+ }
+
+ public TileEntity getBlockTileEntity() {
+ return this.worldObj.getBlockTileEntity(this.xPos, this.yPos, this.zPos);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockSponge.java b/sp-server/src/main/java/net/minecraft/src/BlockSponge.java
new file mode 100644
index 0000000..866c50f
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockSponge.java
@@ -0,0 +1,8 @@
+package net.minecraft.src;
+
+public class BlockSponge extends Block {
+ protected BlockSponge(int par1) {
+ super(par1, Material.sponge);
+ this.setCreativeTab(CreativeTabs.tabBlock);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockStairs.java b/sp-server/src/main/java/net/minecraft/src/BlockStairs.java
new file mode 100644
index 0000000..9b9b75e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockStairs.java
@@ -0,0 +1,496 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockStairs extends Block {
+ private static final int[][] field_72159_a = new int[][] { { 2, 6 }, { 3, 7 }, { 2, 3 }, { 6, 7 }, { 0, 4 },
+ { 1, 5 }, { 0, 1 }, { 4, 5 } };
+
+ /** The block that is used as model for the stair. */
+ private final Block modelBlock;
+ private final int modelBlockMetadata;
+ private boolean field_72156_cr = false;
+ private int field_72160_cs = 0;
+
+ protected BlockStairs(int par1, Block par2Block, int par3) {
+ super(par1, par2Block.blockMaterial);
+ this.modelBlock = par2Block;
+ this.modelBlockMetadata = par3;
+ this.setHardness(par2Block.blockHardness);
+ this.setResistance(par2Block.blockResistance / 3.0F);
+ this.setStepSound(par2Block.stepSound);
+ this.setLightOpacity(255);
+ this.setCreativeTab(CreativeTabs.tabBlock);
+ }
+
+ /**
+ * Updates the blocks bounds based on its current state. Args: world, x, y, z
+ */
+ public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ if (this.field_72156_cr) {
+ this.setBlockBounds(0.5F * (float) (this.field_72160_cs % 2), 0.5F * (float) (this.field_72160_cs / 2 % 2),
+ 0.5F * (float) (this.field_72160_cs / 4 % 2), 0.5F + 0.5F * (float) (this.field_72160_cs % 2),
+ 0.5F + 0.5F * (float) (this.field_72160_cs / 2 % 2),
+ 0.5F + 0.5F * (float) (this.field_72160_cs / 4 % 2));
+ } else {
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
+ }
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 10;
+ }
+
+ public void func_82541_d(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ int var5 = par1IBlockAccess.getBlockMetadata(par2, par3, par4);
+
+ if ((var5 & 4) != 0) {
+ this.setBlockBounds(0.0F, 0.5F, 0.0F, 1.0F, 1.0F, 1.0F);
+ } else {
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.5F, 1.0F);
+ }
+ }
+
+ /**
+ * Checks if supplied ID is one of a BlockStairs
+ */
+ public static boolean isBlockStairsID(int par0) {
+ return par0 > 0 && Block.blocksList[par0] instanceof BlockStairs;
+ }
+
+ private boolean func_82540_f(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) {
+ int var6 = par1IBlockAccess.getBlockId(par2, par3, par4);
+ return isBlockStairsID(var6) && par1IBlockAccess.getBlockMetadata(par2, par3, par4) == par5;
+ }
+
+ public boolean func_82542_g(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ int var5 = par1IBlockAccess.getBlockMetadata(par2, par3, par4);
+ int var6 = var5 & 3;
+ float var7 = 0.5F;
+ float var8 = 1.0F;
+
+ if ((var5 & 4) != 0) {
+ var7 = 0.0F;
+ var8 = 0.5F;
+ }
+
+ float var9 = 0.0F;
+ float var10 = 1.0F;
+ float var11 = 0.0F;
+ float var12 = 0.5F;
+ boolean var13 = true;
+ int var14;
+ int var15;
+ int var16;
+
+ if (var6 == 0) {
+ var9 = 0.5F;
+ var12 = 1.0F;
+ var14 = par1IBlockAccess.getBlockId(par2 + 1, par3, par4);
+ var15 = par1IBlockAccess.getBlockMetadata(par2 + 1, par3, par4);
+
+ if (isBlockStairsID(var14) && (var5 & 4) == (var15 & 4)) {
+ var16 = var15 & 3;
+
+ if (var16 == 3 && !this.func_82540_f(par1IBlockAccess, par2, par3, par4 + 1, var5)) {
+ var12 = 0.5F;
+ var13 = false;
+ } else if (var16 == 2 && !this.func_82540_f(par1IBlockAccess, par2, par3, par4 - 1, var5)) {
+ var11 = 0.5F;
+ var13 = false;
+ }
+ }
+ } else if (var6 == 1) {
+ var10 = 0.5F;
+ var12 = 1.0F;
+ var14 = par1IBlockAccess.getBlockId(par2 - 1, par3, par4);
+ var15 = par1IBlockAccess.getBlockMetadata(par2 - 1, par3, par4);
+
+ if (isBlockStairsID(var14) && (var5 & 4) == (var15 & 4)) {
+ var16 = var15 & 3;
+
+ if (var16 == 3 && !this.func_82540_f(par1IBlockAccess, par2, par3, par4 + 1, var5)) {
+ var12 = 0.5F;
+ var13 = false;
+ } else if (var16 == 2 && !this.func_82540_f(par1IBlockAccess, par2, par3, par4 - 1, var5)) {
+ var11 = 0.5F;
+ var13 = false;
+ }
+ }
+ } else if (var6 == 2) {
+ var11 = 0.5F;
+ var12 = 1.0F;
+ var14 = par1IBlockAccess.getBlockId(par2, par3, par4 + 1);
+ var15 = par1IBlockAccess.getBlockMetadata(par2, par3, par4 + 1);
+
+ if (isBlockStairsID(var14) && (var5 & 4) == (var15 & 4)) {
+ var16 = var15 & 3;
+
+ if (var16 == 1 && !this.func_82540_f(par1IBlockAccess, par2 + 1, par3, par4, var5)) {
+ var10 = 0.5F;
+ var13 = false;
+ } else if (var16 == 0 && !this.func_82540_f(par1IBlockAccess, par2 - 1, par3, par4, var5)) {
+ var9 = 0.5F;
+ var13 = false;
+ }
+ }
+ } else if (var6 == 3) {
+ var14 = par1IBlockAccess.getBlockId(par2, par3, par4 - 1);
+ var15 = par1IBlockAccess.getBlockMetadata(par2, par3, par4 - 1);
+
+ if (isBlockStairsID(var14) && (var5 & 4) == (var15 & 4)) {
+ var16 = var15 & 3;
+
+ if (var16 == 1 && !this.func_82540_f(par1IBlockAccess, par2 + 1, par3, par4, var5)) {
+ var10 = 0.5F;
+ var13 = false;
+ } else if (var16 == 0 && !this.func_82540_f(par1IBlockAccess, par2 - 1, par3, par4, var5)) {
+ var9 = 0.5F;
+ var13 = false;
+ }
+ }
+ }
+
+ this.setBlockBounds(var9, var7, var11, var10, var8, var12);
+ return var13;
+ }
+
+ public boolean func_82544_h(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ int var5 = par1IBlockAccess.getBlockMetadata(par2, par3, par4);
+ int var6 = var5 & 3;
+ float var7 = 0.5F;
+ float var8 = 1.0F;
+
+ if ((var5 & 4) != 0) {
+ var7 = 0.0F;
+ var8 = 0.5F;
+ }
+
+ float var9 = 0.0F;
+ float var10 = 0.5F;
+ float var11 = 0.5F;
+ float var12 = 1.0F;
+ boolean var13 = false;
+ int var14;
+ int var15;
+ int var16;
+
+ if (var6 == 0) {
+ var14 = par1IBlockAccess.getBlockId(par2 - 1, par3, par4);
+ var15 = par1IBlockAccess.getBlockMetadata(par2 - 1, par3, par4);
+
+ if (isBlockStairsID(var14) && (var5 & 4) == (var15 & 4)) {
+ var16 = var15 & 3;
+
+ if (var16 == 3 && !this.func_82540_f(par1IBlockAccess, par2, par3, par4 - 1, var5)) {
+ var11 = 0.0F;
+ var12 = 0.5F;
+ var13 = true;
+ } else if (var16 == 2 && !this.func_82540_f(par1IBlockAccess, par2, par3, par4 + 1, var5)) {
+ var11 = 0.5F;
+ var12 = 1.0F;
+ var13 = true;
+ }
+ }
+ } else if (var6 == 1) {
+ var14 = par1IBlockAccess.getBlockId(par2 + 1, par3, par4);
+ var15 = par1IBlockAccess.getBlockMetadata(par2 + 1, par3, par4);
+
+ if (isBlockStairsID(var14) && (var5 & 4) == (var15 & 4)) {
+ var9 = 0.5F;
+ var10 = 1.0F;
+ var16 = var15 & 3;
+
+ if (var16 == 3 && !this.func_82540_f(par1IBlockAccess, par2, par3, par4 - 1, var5)) {
+ var11 = 0.0F;
+ var12 = 0.5F;
+ var13 = true;
+ } else if (var16 == 2 && !this.func_82540_f(par1IBlockAccess, par2, par3, par4 + 1, var5)) {
+ var11 = 0.5F;
+ var12 = 1.0F;
+ var13 = true;
+ }
+ }
+ } else if (var6 == 2) {
+ var14 = par1IBlockAccess.getBlockId(par2, par3, par4 - 1);
+ var15 = par1IBlockAccess.getBlockMetadata(par2, par3, par4 - 1);
+
+ if (isBlockStairsID(var14) && (var5 & 4) == (var15 & 4)) {
+ var11 = 0.0F;
+ var12 = 0.5F;
+ var16 = var15 & 3;
+
+ if (var16 == 1 && !this.func_82540_f(par1IBlockAccess, par2 - 1, par3, par4, var5)) {
+ var13 = true;
+ } else if (var16 == 0 && !this.func_82540_f(par1IBlockAccess, par2 + 1, par3, par4, var5)) {
+ var9 = 0.5F;
+ var10 = 1.0F;
+ var13 = true;
+ }
+ }
+ } else if (var6 == 3) {
+ var14 = par1IBlockAccess.getBlockId(par2, par3, par4 + 1);
+ var15 = par1IBlockAccess.getBlockMetadata(par2, par3, par4 + 1);
+
+ if (isBlockStairsID(var14) && (var5 & 4) == (var15 & 4)) {
+ var16 = var15 & 3;
+
+ if (var16 == 1 && !this.func_82540_f(par1IBlockAccess, par2 - 1, par3, par4, var5)) {
+ var13 = true;
+ } else if (var16 == 0 && !this.func_82540_f(par1IBlockAccess, par2 + 1, par3, par4, var5)) {
+ var9 = 0.5F;
+ var10 = 1.0F;
+ var13 = true;
+ }
+ }
+ }
+
+ if (var13) {
+ this.setBlockBounds(var9, var7, var11, var10, var8, var12);
+ }
+
+ return var13;
+ }
+
+ /**
+ * Adds all intersecting collision boxes to a list. (Be sure to only add boxes
+ * to the list if they intersect the mask.) Parameters: World, X, Y, Z, mask,
+ * list, colliding entity
+ */
+ public void addCollisionBoxesToList(World par1World, int par2, int par3, int par4, AxisAlignedBB par5AxisAlignedBB,
+ List par6List, Entity par7Entity) {
+ this.func_82541_d(par1World, par2, par3, par4);
+ super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
+ boolean var8 = this.func_82542_g(par1World, par2, par3, par4);
+ super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
+
+ if (var8 && this.func_82544_h(par1World, par2, par3, par4)) {
+ super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
+ }
+
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
+ }
+
+ /**
+ * Called when the block is clicked by a player. Args: x, y, z, entityPlayer
+ */
+ public void onBlockClicked(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer) {
+ this.modelBlock.onBlockClicked(par1World, par2, par3, par4, par5EntityPlayer);
+ }
+
+ /**
+ * Called right before the block is destroyed by a player. Args: world, x, y, z,
+ * metaData
+ */
+ public void onBlockDestroyedByPlayer(World par1World, int par2, int par3, int par4, int par5) {
+ this.modelBlock.onBlockDestroyedByPlayer(par1World, par2, par3, par4, par5);
+ }
+
+ /**
+ * Returns how much this block can resist explosions from the passed in entity.
+ */
+ public float getExplosionResistance(Entity par1Entity) {
+ return this.modelBlock.getExplosionResistance(par1Entity);
+ }
+
+ /**
+ * How many world ticks before ticking
+ */
+ public int tickRate(World par1World) {
+ return this.modelBlock.tickRate(par1World);
+ }
+
+ /**
+ * Can add to the passed in vector for a movement vector to be applied to the
+ * entity. Args: x, y, z, entity, vec3d
+ */
+ public void velocityToAddToEntity(World par1World, int par2, int par3, int par4, Entity par5Entity, Vec3 par6Vec3) {
+ this.modelBlock.velocityToAddToEntity(par1World, par2, par3, par4, par5Entity, par6Vec3);
+ }
+
+ /**
+ * Returns if this block is collidable (only used by Fire). Args: x, y, z
+ */
+ public boolean isCollidable() {
+ return this.modelBlock.isCollidable();
+ }
+
+ /**
+ * Returns whether this block is collideable based on the arguments passed in
+ * Args: blockMetaData, unknownFlag
+ */
+ public boolean canCollideCheck(int par1, boolean par2) {
+ return this.modelBlock.canCollideCheck(par1, par2);
+ }
+
+ /**
+ * Checks to see if its valid to put this block at the specified coordinates.
+ * Args: world, x, y, z
+ */
+ public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4) {
+ return this.modelBlock.canPlaceBlockAt(par1World, par2, par3, par4);
+ }
+
+ /**
+ * Called whenever the block is added into the world. Args: world, x, y, z
+ */
+ public void onBlockAdded(World par1World, int par2, int par3, int par4) {
+ this.onNeighborBlockChange(par1World, par2, par3, par4, 0);
+ this.modelBlock.onBlockAdded(par1World, par2, par3, par4);
+ }
+
+ /**
+ * ejects contained items into the world, and notifies neighbours of an update,
+ * as appropriate
+ */
+ public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) {
+ this.modelBlock.breakBlock(par1World, par2, par3, par4, par5, par6);
+ }
+
+ /**
+ * Called whenever an entity is walking on top of this block. Args: world, x, y,
+ * z, entity
+ */
+ public void onEntityWalking(World par1World, int par2, int par3, int par4, Entity par5Entity) {
+ this.modelBlock.onEntityWalking(par1World, par2, par3, par4, par5Entity);
+ }
+
+ /**
+ * Ticks the block if it's been scheduled
+ */
+ public void updateTick(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ this.modelBlock.updateTick(par1World, par2, par3, par4, par5Random);
+ }
+
+ /**
+ * Called upon block activation (right click on the block.)
+ */
+ public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer,
+ int par6, float par7, float par8, float par9) {
+ return this.modelBlock.onBlockActivated(par1World, par2, par3, par4, par5EntityPlayer, 0, 0.0F, 0.0F, 0.0F);
+ }
+
+ /**
+ * Called upon the block being destroyed by an explosion
+ */
+ public void onBlockDestroyedByExplosion(World par1World, int par2, int par3, int par4, Explosion par5Explosion) {
+ this.modelBlock.onBlockDestroyedByExplosion(par1World, par2, par3, par4, par5Explosion);
+ }
+
+ /**
+ * Called when the block is placed in the world.
+ */
+ public void onBlockPlacedBy(World par1World, int par2, int par3, int par4, EntityLiving par5EntityLiving,
+ ItemStack par6ItemStack) {
+ int var7 = MathHelper.floor_double((double) (par5EntityLiving.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3;
+ int var8 = par1World.getBlockMetadata(par2, par3, par4) & 4;
+
+ if (var7 == 0) {
+ par1World.setBlockMetadata(par2, par3, par4, 2 | var8, 2);
+ }
+
+ if (var7 == 1) {
+ par1World.setBlockMetadata(par2, par3, par4, 1 | var8, 2);
+ }
+
+ if (var7 == 2) {
+ par1World.setBlockMetadata(par2, par3, par4, 3 | var8, 2);
+ }
+
+ if (var7 == 3) {
+ par1World.setBlockMetadata(par2, par3, par4, 0 | var8, 2);
+ }
+ }
+
+ /**
+ * Called when a block is placed using its ItemBlock. Args: World, X, Y, Z,
+ * side, hitX, hitY, hitZ, block metadata
+ */
+ public int onBlockPlaced(World par1World, int par2, int par3, int par4, int par5, float par6, float par7,
+ float par8, int par9) {
+ return par5 != 0 && (par5 == 1 || (double) par7 <= 0.5D) ? par9 : par9 | 4;
+ }
+
+ /**
+ * Ray traces through the blocks collision from start vector to end vector
+ * returning a ray trace hit. Args: world, x, y, z, startVec, endVec
+ */
+ public MovingObjectPosition collisionRayTrace(World par1World, int par2, int par3, int par4, Vec3 par5Vec3,
+ Vec3 par6Vec3) {
+ MovingObjectPosition[] var7 = new MovingObjectPosition[8];
+ int var8 = par1World.getBlockMetadata(par2, par3, par4);
+ int var9 = var8 & 3;
+ boolean var10 = (var8 & 4) == 4;
+ int[] var11 = field_72159_a[var9 + (var10 ? 4 : 0)];
+ this.field_72156_cr = true;
+ int var14;
+ int var15;
+ int var16;
+
+ for (int var12 = 0; var12 < 8; ++var12) {
+ this.field_72160_cs = var12;
+ int[] var13 = var11;
+ var14 = var11.length;
+
+ for (var15 = 0; var15 < var14; ++var15) {
+ var16 = var13[var15];
+
+ if (var16 == var12) {
+ ;
+ }
+ }
+
+ var7[var12] = super.collisionRayTrace(par1World, par2, par3, par4, par5Vec3, par6Vec3);
+ }
+
+ int[] var21 = var11;
+ int var23 = var11.length;
+
+ for (var14 = 0; var14 < var23; ++var14) {
+ var15 = var21[var14];
+ var7[var15] = null;
+ }
+
+ MovingObjectPosition var22 = null;
+ double var24 = 0.0D;
+ MovingObjectPosition[] var25 = var7;
+ var16 = var7.length;
+
+ for (int var17 = 0; var17 < var16; ++var17) {
+ MovingObjectPosition var18 = var25[var17];
+
+ if (var18 != null) {
+ double var19 = var18.hitVec.squareDistanceTo(par6Vec3);
+
+ if (var19 > var24) {
+ var22 = var18;
+ var24 = var19;
+ }
+ }
+ }
+
+ return var22;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockStationary.java b/sp-server/src/main/java/net/minecraft/src/BlockStationary.java
new file mode 100644
index 0000000..b6c8353
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockStationary.java
@@ -0,0 +1,93 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockStationary extends BlockFluid {
+ protected BlockStationary(int par1, Material par2Material) {
+ super(par1, par2Material);
+ this.setTickRandomly(false);
+
+ if (par2Material == Material.lava) {
+ this.setTickRandomly(true);
+ }
+ }
+
+ public boolean getBlocksMovement(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ return this.blockMaterial != Material.lava;
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ super.onNeighborBlockChange(par1World, par2, par3, par4, par5);
+
+ if (par1World.getBlockId(par2, par3, par4) == this.blockID) {
+ this.setNotStationary(par1World, par2, par3, par4);
+ }
+ }
+
+ /**
+ * Changes the block ID to that of an updating fluid.
+ */
+ private void setNotStationary(World par1World, int par2, int par3, int par4) {
+ int var5 = par1World.getBlockMetadata(par2, par3, par4);
+ par1World.setBlock(par2, par3, par4, this.blockID - 1, var5, 2);
+ par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID - 1, this.tickRate(par1World));
+ }
+
+ /**
+ * Ticks the block if it's been scheduled
+ */
+ public void updateTick(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ if (this.blockMaterial == Material.lava) {
+ int var6 = par5Random.nextInt(3);
+ int var7;
+ int var8;
+
+ for (var7 = 0; var7 < var6; ++var7) {
+ par2 += par5Random.nextInt(3) - 1;
+ ++par3;
+ par4 += par5Random.nextInt(3) - 1;
+ var8 = par1World.getBlockId(par2, par3, par4);
+
+ if (var8 == 0) {
+ if (this.isFlammable(par1World, par2 - 1, par3, par4)
+ || this.isFlammable(par1World, par2 + 1, par3, par4)
+ || this.isFlammable(par1World, par2, par3, par4 - 1)
+ || this.isFlammable(par1World, par2, par3, par4 + 1)
+ || this.isFlammable(par1World, par2, par3 - 1, par4)
+ || this.isFlammable(par1World, par2, par3 + 1, par4)) {
+ par1World.setBlock(par2, par3, par4, Block.fire.blockID);
+ return;
+ }
+ } else if (Block.blocksList[var8].blockMaterial.blocksMovement()) {
+ return;
+ }
+ }
+
+ if (var6 == 0) {
+ var7 = par2;
+ var8 = par4;
+
+ for (int var9 = 0; var9 < 3; ++var9) {
+ par2 = var7 + par5Random.nextInt(3) - 1;
+ par4 = var8 + par5Random.nextInt(3) - 1;
+
+ if (par1World.isAirBlock(par2, par3 + 1, par4) && this.isFlammable(par1World, par2, par3, par4)) {
+ par1World.setBlock(par2, par3 + 1, par4, Block.fire.blockID);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Checks to see if the block is flammable.
+ */
+ private boolean isFlammable(World par1World, int par2, int par3, int par4) {
+ return par1World.getBlockMaterial(par2, par3, par4).getCanBurn();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockStem.java b/sp-server/src/main/java/net/minecraft/src/BlockStem.java
new file mode 100644
index 0000000..a377e89
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockStem.java
@@ -0,0 +1,206 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockStem extends BlockFlower {
+ /** Defines if it is a Melon or a Pumpkin that the stem is producing. */
+ private final Block fruitType;
+
+ protected BlockStem(int par1, Block par2Block) {
+ super(par1);
+ this.fruitType = par2Block;
+ this.setTickRandomly(true);
+ float var3 = 0.125F;
+ this.setBlockBounds(0.5F - var3, 0.0F, 0.5F - var3, 0.5F + var3, 0.25F, 0.5F + var3);
+ this.setCreativeTab((CreativeTabs) null);
+ }
+
+ /**
+ * Gets passed in the blockID of the block below and supposed to return true if
+ * its allowed to grow on the type of blockID passed in. Args: blockID
+ */
+ protected boolean canThisPlantGrowOnThisBlockID(int par1) {
+ return par1 == Block.tilledField.blockID;
+ }
+
+ /**
+ * Ticks the block if it's been scheduled
+ */
+ public void updateTick(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ super.updateTick(par1World, par2, par3, par4, par5Random);
+
+ if (par1World.getBlockLightValue(par2, par3 + 1, par4) >= 9) {
+ float var6 = this.getGrowthModifier(par1World, par2, par3, par4);
+
+ if (par5Random.nextInt((int) (25.0F / var6) + 1) == 0) {
+ int var7 = par1World.getBlockMetadata(par2, par3, par4);
+
+ if (var7 < 7) {
+ ++var7;
+ par1World.setBlockMetadata(par2, par3, par4, var7, 2);
+ } else {
+ if (par1World.getBlockId(par2 - 1, par3, par4) == this.fruitType.blockID) {
+ return;
+ }
+
+ if (par1World.getBlockId(par2 + 1, par3, par4) == this.fruitType.blockID) {
+ return;
+ }
+
+ if (par1World.getBlockId(par2, par3, par4 - 1) == this.fruitType.blockID) {
+ return;
+ }
+
+ if (par1World.getBlockId(par2, par3, par4 + 1) == this.fruitType.blockID) {
+ return;
+ }
+
+ int var8 = par5Random.nextInt(4);
+ int var9 = par2;
+ int var10 = par4;
+
+ if (var8 == 0) {
+ var9 = par2 - 1;
+ }
+
+ if (var8 == 1) {
+ ++var9;
+ }
+
+ if (var8 == 2) {
+ var10 = par4 - 1;
+ }
+
+ if (var8 == 3) {
+ ++var10;
+ }
+
+ int var11 = par1World.getBlockId(var9, par3 - 1, var10);
+
+ if (par1World.getBlockId(var9, par3, var10) == 0 && (var11 == Block.tilledField.blockID
+ || var11 == Block.dirt.blockID || var11 == Block.grass.blockID)) {
+ par1World.setBlock(var9, par3, var10, this.fruitType.blockID);
+ }
+ }
+ }
+ }
+ }
+
+ public void fertilizeStem(World par1World, int par2, int par3, int par4) {
+ int var5 = par1World.getBlockMetadata(par2, par3, par4)
+ + MathHelper.getRandomIntegerInRange(par1World.rand, 2, 5);
+
+ if (var5 > 7) {
+ var5 = 7;
+ }
+
+ par1World.setBlockMetadata(par2, par3, par4, var5, 2);
+ }
+
+ private float getGrowthModifier(World par1World, int par2, int par3, int par4) {
+ float var5 = 1.0F;
+ int var6 = par1World.getBlockId(par2, par3, par4 - 1);
+ int var7 = par1World.getBlockId(par2, par3, par4 + 1);
+ int var8 = par1World.getBlockId(par2 - 1, par3, par4);
+ int var9 = par1World.getBlockId(par2 + 1, par3, par4);
+ int var10 = par1World.getBlockId(par2 - 1, par3, par4 - 1);
+ int var11 = par1World.getBlockId(par2 + 1, par3, par4 - 1);
+ int var12 = par1World.getBlockId(par2 + 1, par3, par4 + 1);
+ int var13 = par1World.getBlockId(par2 - 1, par3, par4 + 1);
+ boolean var14 = var8 == this.blockID || var9 == this.blockID;
+ boolean var15 = var6 == this.blockID || var7 == this.blockID;
+ boolean var16 = var10 == this.blockID || var11 == this.blockID || var12 == this.blockID
+ || var13 == this.blockID;
+
+ for (int var17 = par2 - 1; var17 <= par2 + 1; ++var17) {
+ for (int var18 = par4 - 1; var18 <= par4 + 1; ++var18) {
+ int var19 = par1World.getBlockId(var17, par3 - 1, var18);
+ float var20 = 0.0F;
+
+ if (var19 == Block.tilledField.blockID) {
+ var20 = 1.0F;
+
+ if (par1World.getBlockMetadata(var17, par3 - 1, var18) > 0) {
+ var20 = 3.0F;
+ }
+ }
+
+ if (var17 != par2 || var18 != par4) {
+ var20 /= 4.0F;
+ }
+
+ var5 += var20;
+ }
+ }
+
+ if (var16 || var14 && var15) {
+ var5 /= 2.0F;
+ }
+
+ return var5;
+ }
+
+ /**
+ * Sets the block's bounds for rendering it as an item
+ */
+ public void setBlockBoundsForItemRender() {
+ float var1 = 0.125F;
+ this.setBlockBounds(0.5F - var1, 0.0F, 0.5F - var1, 0.5F + var1, 0.25F, 0.5F + var1);
+ }
+
+ /**
+ * Updates the blocks bounds based on its current state. Args: world, x, y, z
+ */
+ public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ this.maxY = (double) ((float) (par1IBlockAccess.getBlockMetadata(par2, par3, par4) * 2 + 2) / 16.0F);
+ float var5 = 0.125F;
+ this.setBlockBounds(0.5F - var5, 0.0F, 0.5F - var5, 0.5F + var5, (float) this.maxY, 0.5F + var5);
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 19;
+ }
+
+ /**
+ * Drops the block items with a specified chance of dropping the specified items
+ */
+ public void dropBlockAsItemWithChance(World par1World, int par2, int par3, int par4, int par5, float par6,
+ int par7) {
+ super.dropBlockAsItemWithChance(par1World, par2, par3, par4, par5, par6, par7);
+
+ if (!par1World.isRemote) {
+ Item var8 = null;
+
+ if (this.fruitType == Block.pumpkin) {
+ var8 = Item.pumpkinSeeds;
+ }
+
+ if (this.fruitType == Block.melon) {
+ var8 = Item.melonSeeds;
+ }
+
+ for (int var9 = 0; var9 < 3; ++var9) {
+ if (par1World.rand.nextInt(15) <= par5) {
+ this.dropBlockAsItem_do(par1World, par2, par3, par4, new ItemStack(var8));
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return -1;
+ }
+
+ /**
+ * Returns the quantity of items to drop on block destruction.
+ */
+ public int quantityDropped(EaglercraftRandom par1Random) {
+ return 1;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockStep.java b/sp-server/src/main/java/net/minecraft/src/BlockStep.java
new file mode 100644
index 0000000..9132b11
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockStep.java
@@ -0,0 +1,41 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockStep extends BlockHalfSlab {
+ /** The list of the types of step blocks. */
+ public static final String[] blockStepTypes = new String[] { "stone", "sand", "wood", "cobble", "brick",
+ "smoothStoneBrick", "netherBrick", "quartz" };
+
+ public BlockStep(int par1, boolean par2) {
+ super(par1, par2, Material.rock);
+ this.setCreativeTab(CreativeTabs.tabBlock);
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return Block.stoneSingleSlab.blockID;
+ }
+
+ /**
+ * Returns an item stack containing a single instance of the current block type.
+ * 'i' is the block's subtype/damage and is ignored for blocks which do not
+ * support subtypes. Blocks which cannot be harvested should return null.
+ */
+ protected ItemStack createStackedBlock(int par1) {
+ return new ItemStack(Block.stoneSingleSlab.blockID, 2, par1 & 7);
+ }
+
+ /**
+ * Returns the slab block name with step type.
+ */
+ public String getFullSlabName(int par1) {
+ if (par1 < 0 || par1 >= blockStepTypes.length) {
+ par1 = 0;
+ }
+
+ return super.getUnlocalizedName() + "." + blockStepTypes[par1];
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockStone.java b/sp-server/src/main/java/net/minecraft/src/BlockStone.java
new file mode 100644
index 0000000..eb19707
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockStone.java
@@ -0,0 +1,17 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockStone extends Block {
+ public BlockStone(int par1) {
+ super(par1, Material.rock);
+ this.setCreativeTab(CreativeTabs.tabBlock);
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return Block.cobblestone.blockID;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockStoneBrick.java b/sp-server/src/main/java/net/minecraft/src/BlockStoneBrick.java
new file mode 100644
index 0000000..f716abc
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockStoneBrick.java
@@ -0,0 +1,19 @@
+package net.minecraft.src;
+
+public class BlockStoneBrick extends Block {
+ public static final String[] STONE_BRICK_TYPES = new String[] { "default", "mossy", "cracked", "chiseled" };
+ public static final String[] field_94407_b = new String[] { "stonebricksmooth", "stonebricksmooth_mossy",
+ "stonebricksmooth_cracked", "stonebricksmooth_carved" };
+
+ public BlockStoneBrick(int par1) {
+ super(par1, Material.rock);
+ this.setCreativeTab(CreativeTabs.tabBlock);
+ }
+
+ /**
+ * Determines the damage on the item the block drops. Used in cloth and wood.
+ */
+ public int damageDropped(int par1) {
+ return par1;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockTNT.java b/sp-server/src/main/java/net/minecraft/src/BlockTNT.java
new file mode 100644
index 0000000..5c01d31
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockTNT.java
@@ -0,0 +1,110 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockTNT extends Block {
+ public BlockTNT(int par1) {
+ super(par1, Material.tnt);
+ this.setCreativeTab(CreativeTabs.tabRedstone);
+ }
+
+ /**
+ * Called whenever the block is added into the world. Args: world, x, y, z
+ */
+ public void onBlockAdded(World par1World, int par2, int par3, int par4) {
+ super.onBlockAdded(par1World, par2, par3, par4);
+
+ if (par1World.isBlockIndirectlyGettingPowered(par2, par3, par4)) {
+ this.onBlockDestroyedByPlayer(par1World, par2, par3, par4, 1);
+ par1World.setBlockToAir(par2, par3, par4);
+ }
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ if (par1World.isBlockIndirectlyGettingPowered(par2, par3, par4)) {
+ this.onBlockDestroyedByPlayer(par1World, par2, par3, par4, 1);
+ par1World.setBlockToAir(par2, par3, par4);
+ }
+ }
+
+ /**
+ * Returns the quantity of items to drop on block destruction.
+ */
+ public int quantityDropped(EaglercraftRandom par1Random) {
+ return 1;
+ }
+
+ /**
+ * Called upon the block being destroyed by an explosion
+ */
+ public void onBlockDestroyedByExplosion(World par1World, int par2, int par3, int par4, Explosion par5Explosion) {
+ if (!par1World.isRemote) {
+ EntityTNTPrimed var6 = new EntityTNTPrimed(par1World, (double) ((float) par2 + 0.5F),
+ (double) ((float) par3 + 0.5F), (double) ((float) par4 + 0.5F), par5Explosion.func_94613_c());
+ var6.fuse = par1World.rand.nextInt(var6.fuse / 4) + var6.fuse / 8;
+ par1World.spawnEntityInWorld(var6);
+ }
+ }
+
+ /**
+ * Called right before the block is destroyed by a player. Args: world, x, y, z,
+ * metaData
+ */
+ public void onBlockDestroyedByPlayer(World par1World, int par2, int par3, int par4, int par5) {
+ this.func_94391_a(par1World, par2, par3, par4, par5, (EntityLiving) null);
+ }
+
+ public void func_94391_a(World par1World, int par2, int par3, int par4, int par5, EntityLiving par6EntityLiving) {
+ if (!par1World.isRemote) {
+ if ((par5 & 1) == 1) {
+ EntityTNTPrimed var7 = new EntityTNTPrimed(par1World, (double) ((float) par2 + 0.5F),
+ (double) ((float) par3 + 0.5F), (double) ((float) par4 + 0.5F), par6EntityLiving);
+ par1World.spawnEntityInWorld(var7);
+ par1World.playSoundAtEntity(var7, "random.fuse", 1.0F, 1.0F);
+ }
+ }
+ }
+
+ /**
+ * Called upon block activation (right click on the block.)
+ */
+ public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer,
+ int par6, float par7, float par8, float par9) {
+ if (par5EntityPlayer.getCurrentEquippedItem() != null
+ && par5EntityPlayer.getCurrentEquippedItem().itemID == Item.flintAndSteel.itemID) {
+ this.func_94391_a(par1World, par2, par3, par4, 1, par5EntityPlayer);
+ par1World.setBlockToAir(par2, par3, par4);
+ return true;
+ } else {
+ return super.onBlockActivated(par1World, par2, par3, par4, par5EntityPlayer, par6, par7, par8, par9);
+ }
+ }
+
+ /**
+ * Triggered whenever an entity collides with this block (enters into the
+ * block). Args: world, x, y, z, entity
+ */
+ public void onEntityCollidedWithBlock(World par1World, int par2, int par3, int par4, Entity par5Entity) {
+ if (par5Entity instanceof EntityArrow && !par1World.isRemote) {
+ EntityArrow var6 = (EntityArrow) par5Entity;
+
+ if (var6.isBurning()) {
+ this.func_94391_a(par1World, par2, par3, par4, 1,
+ var6.shootingEntity instanceof EntityLiving ? (EntityLiving) var6.shootingEntity : null);
+ par1World.setBlockToAir(par2, par3, par4);
+ }
+ }
+ }
+
+ /**
+ * Return whether this block can drop from an explosion.
+ */
+ public boolean canDropFromExplosion(Explosion par1Explosion) {
+ return false;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockTallGrass.java b/sp-server/src/main/java/net/minecraft/src/BlockTallGrass.java
new file mode 100644
index 0000000..205ef54
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockTallGrass.java
@@ -0,0 +1,49 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockTallGrass extends BlockFlower {
+ private static final String[] grassTypes = new String[] { "deadbush", "tallgrass", "fern" };
+
+ protected BlockTallGrass(int par1) {
+ super(par1, Material.vine);
+ float var2 = 0.4F;
+ this.setBlockBounds(0.5F - var2, 0.0F, 0.5F - var2, 0.5F + var2, 0.8F, 0.5F + var2);
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return par2Random.nextInt(8) == 0 ? Item.seeds.itemID : -1;
+ }
+
+ /**
+ * Returns the usual quantity dropped by the block plus a bonus of 1 to 'i'
+ * (inclusive).
+ */
+ public int quantityDroppedWithBonus(int par1, EaglercraftRandom par2Random) {
+ return 1 + par2Random.nextInt(par1 * 2 + 1);
+ }
+
+ /**
+ * Called when the player destroys a block with an item that can harvest it. (i,
+ * j, k) are the coordinates of the block and l is the block's subtype/damage.
+ */
+ public void harvestBlock(World par1World, EntityPlayer par2EntityPlayer, int par3, int par4, int par5, int par6) {
+ if (!par1World.isRemote && par2EntityPlayer.getCurrentEquippedItem() != null
+ && par2EntityPlayer.getCurrentEquippedItem().itemID == Item.shears.itemID) {
+ par2EntityPlayer.addStat(StatList.mineBlockStatArray[this.blockID], 1);
+ this.dropBlockAsItem_do(par1World, par3, par4, par5, new ItemStack(Block.tallGrass, 1, par6));
+ } else {
+ super.harvestBlock(par1World, par2EntityPlayer, par3, par4, par5, par6);
+ }
+ }
+
+ /**
+ * Get the block's damage value (for use with pick block).
+ */
+ public int getDamageValue(World par1World, int par2, int par3, int par4) {
+ return par1World.getBlockMetadata(par2, par3, par4);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockTorch.java b/sp-server/src/main/java/net/minecraft/src/BlockTorch.java
new file mode 100644
index 0000000..ed07c92
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockTorch.java
@@ -0,0 +1,220 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockTorch extends Block {
+ protected BlockTorch(int par1) {
+ super(par1, Material.circuits);
+ this.setTickRandomly(true);
+ this.setCreativeTab(CreativeTabs.tabDecorations);
+ }
+
+ /**
+ * Returns a bounding box from the pool of bounding boxes (this means this box
+ * can change after the pool has been cleared to be reused)
+ */
+ public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) {
+ return null;
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 2;
+ }
+
+ /**
+ * Gets if we can place a torch on a block.
+ */
+ private boolean canPlaceTorchOn(World par1World, int par2, int par3, int par4) {
+ if (par1World.doesBlockHaveSolidTopSurface(par2, par3, par4)) {
+ return true;
+ } else {
+ int var5 = par1World.getBlockId(par2, par3, par4);
+ return var5 == Block.fence.blockID || var5 == Block.netherFence.blockID || var5 == Block.glass.blockID
+ || var5 == Block.cobblestoneWall.blockID;
+ }
+ }
+
+ /**
+ * Checks to see if its valid to put this block at the specified coordinates.
+ * Args: world, x, y, z
+ */
+ public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4) {
+ return par1World.isBlockNormalCubeDefault(par2 - 1, par3, par4, true) ? true
+ : (par1World.isBlockNormalCubeDefault(par2 + 1, par3, par4, true) ? true
+ : (par1World.isBlockNormalCubeDefault(par2, par3, par4 - 1, true) ? true
+ : (par1World.isBlockNormalCubeDefault(par2, par3, par4 + 1, true) ? true
+ : this.canPlaceTorchOn(par1World, par2, par3 - 1, par4))));
+ }
+
+ /**
+ * Called when a block is placed using its ItemBlock. Args: World, X, Y, Z,
+ * side, hitX, hitY, hitZ, block metadata
+ */
+ public int onBlockPlaced(World par1World, int par2, int par3, int par4, int par5, float par6, float par7,
+ float par8, int par9) {
+ int var10 = par9;
+
+ if (par5 == 1 && this.canPlaceTorchOn(par1World, par2, par3 - 1, par4)) {
+ var10 = 5;
+ }
+
+ if (par5 == 2 && par1World.isBlockNormalCubeDefault(par2, par3, par4 + 1, true)) {
+ var10 = 4;
+ }
+
+ if (par5 == 3 && par1World.isBlockNormalCubeDefault(par2, par3, par4 - 1, true)) {
+ var10 = 3;
+ }
+
+ if (par5 == 4 && par1World.isBlockNormalCubeDefault(par2 + 1, par3, par4, true)) {
+ var10 = 2;
+ }
+
+ if (par5 == 5 && par1World.isBlockNormalCubeDefault(par2 - 1, par3, par4, true)) {
+ var10 = 1;
+ }
+
+ return var10;
+ }
+
+ /**
+ * Ticks the block if it's been scheduled
+ */
+ public void updateTick(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ super.updateTick(par1World, par2, par3, par4, par5Random);
+
+ if (par1World.getBlockMetadata(par2, par3, par4) == 0) {
+ this.onBlockAdded(par1World, par2, par3, par4);
+ }
+ }
+
+ /**
+ * Called whenever the block is added into the world. Args: world, x, y, z
+ */
+ public void onBlockAdded(World par1World, int par2, int par3, int par4) {
+ if (par1World.getBlockMetadata(par2, par3, par4) == 0) {
+ if (par1World.isBlockNormalCubeDefault(par2 - 1, par3, par4, true)) {
+ par1World.setBlockMetadata(par2, par3, par4, 1, 2);
+ } else if (par1World.isBlockNormalCubeDefault(par2 + 1, par3, par4, true)) {
+ par1World.setBlockMetadata(par2, par3, par4, 2, 2);
+ } else if (par1World.isBlockNormalCubeDefault(par2, par3, par4 - 1, true)) {
+ par1World.setBlockMetadata(par2, par3, par4, 3, 2);
+ } else if (par1World.isBlockNormalCubeDefault(par2, par3, par4 + 1, true)) {
+ par1World.setBlockMetadata(par2, par3, par4, 4, 2);
+ } else if (this.canPlaceTorchOn(par1World, par2, par3 - 1, par4)) {
+ par1World.setBlockMetadata(par2, par3, par4, 5, 2);
+ }
+ }
+
+ this.dropTorchIfCantStay(par1World, par2, par3, par4);
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ this.func_94397_d(par1World, par2, par3, par4, par5);
+ }
+
+ protected boolean func_94397_d(World par1World, int par2, int par3, int par4, int par5) {
+ if (this.dropTorchIfCantStay(par1World, par2, par3, par4)) {
+ int var6 = par1World.getBlockMetadata(par2, par3, par4);
+ boolean var7 = false;
+
+ if (!par1World.isBlockNormalCubeDefault(par2 - 1, par3, par4, true) && var6 == 1) {
+ var7 = true;
+ }
+
+ if (!par1World.isBlockNormalCubeDefault(par2 + 1, par3, par4, true) && var6 == 2) {
+ var7 = true;
+ }
+
+ if (!par1World.isBlockNormalCubeDefault(par2, par3, par4 - 1, true) && var6 == 3) {
+ var7 = true;
+ }
+
+ if (!par1World.isBlockNormalCubeDefault(par2, par3, par4 + 1, true) && var6 == 4) {
+ var7 = true;
+ }
+
+ if (!this.canPlaceTorchOn(par1World, par2, par3 - 1, par4) && var6 == 5) {
+ var7 = true;
+ }
+
+ if (var7) {
+ this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
+ par1World.setBlockToAir(par2, par3, par4);
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * Tests if the block can remain at its current location and will drop as an
+ * item if it is unable to stay. Returns True if it can stay and False if it
+ * drops. Args: world, x, y, z
+ */
+ protected boolean dropTorchIfCantStay(World par1World, int par2, int par3, int par4) {
+ if (!this.canPlaceBlockAt(par1World, par2, par3, par4)) {
+ if (par1World.getBlockId(par2, par3, par4) == this.blockID) {
+ this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
+ par1World.setBlockToAir(par2, par3, par4);
+ }
+
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * Ray traces through the blocks collision from start vector to end vector
+ * returning a ray trace hit. Args: world, x, y, z, startVec, endVec
+ */
+ public MovingObjectPosition collisionRayTrace(World par1World, int par2, int par3, int par4, Vec3 par5Vec3,
+ Vec3 par6Vec3) {
+ int var7 = par1World.getBlockMetadata(par2, par3, par4) & 7;
+ float var8 = 0.15F;
+
+ if (var7 == 1) {
+ this.setBlockBounds(0.0F, 0.2F, 0.5F - var8, var8 * 2.0F, 0.8F, 0.5F + var8);
+ } else if (var7 == 2) {
+ this.setBlockBounds(1.0F - var8 * 2.0F, 0.2F, 0.5F - var8, 1.0F, 0.8F, 0.5F + var8);
+ } else if (var7 == 3) {
+ this.setBlockBounds(0.5F - var8, 0.2F, 0.0F, 0.5F + var8, 0.8F, var8 * 2.0F);
+ } else if (var7 == 4) {
+ this.setBlockBounds(0.5F - var8, 0.2F, 1.0F - var8 * 2.0F, 0.5F + var8, 0.8F, 1.0F);
+ } else {
+ var8 = 0.1F;
+ this.setBlockBounds(0.5F - var8, 0.0F, 0.5F - var8, 0.5F + var8, 0.6F, 0.5F + var8);
+ }
+
+ return super.collisionRayTrace(par1World, par2, par3, par4, par5Vec3, par6Vec3);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockTrapDoor.java b/sp-server/src/main/java/net/minecraft/src/BlockTrapDoor.java
new file mode 100644
index 0000000..f2d83a7
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockTrapDoor.java
@@ -0,0 +1,251 @@
+package net.minecraft.src;
+
+public class BlockTrapDoor extends Block {
+ protected BlockTrapDoor(int par1, Material par2Material) {
+ super(par1, par2Material);
+ float var3 = 0.5F;
+ float var4 = 1.0F;
+ this.setBlockBounds(0.5F - var3, 0.0F, 0.5F - var3, 0.5F + var3, var4, 0.5F + var3);
+ this.setCreativeTab(CreativeTabs.tabRedstone);
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ public boolean getBlocksMovement(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ return !isTrapdoorOpen(par1IBlockAccess.getBlockMetadata(par2, par3, par4));
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 0;
+ }
+
+ /**
+ * Returns a bounding box from the pool of bounding boxes (this means this box
+ * can change after the pool has been cleared to be reused)
+ */
+ public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) {
+ this.setBlockBoundsBasedOnState(par1World, par2, par3, par4);
+ return super.getCollisionBoundingBoxFromPool(par1World, par2, par3, par4);
+ }
+
+ /**
+ * Updates the blocks bounds based on its current state. Args: world, x, y, z
+ */
+ public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ this.setBlockBoundsForBlockRender(par1IBlockAccess.getBlockMetadata(par2, par3, par4));
+ }
+
+ /**
+ * Sets the block's bounds for rendering it as an item
+ */
+ public void setBlockBoundsForItemRender() {
+ float var1 = 0.1875F;
+ this.setBlockBounds(0.0F, 0.5F - var1 / 2.0F, 0.0F, 1.0F, 0.5F + var1 / 2.0F, 1.0F);
+ }
+
+ public void setBlockBoundsForBlockRender(int par1) {
+ float var2 = 0.1875F;
+
+ if ((par1 & 8) != 0) {
+ this.setBlockBounds(0.0F, 1.0F - var2, 0.0F, 1.0F, 1.0F, 1.0F);
+ } else {
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, var2, 1.0F);
+ }
+
+ if (isTrapdoorOpen(par1)) {
+ if ((par1 & 3) == 0) {
+ this.setBlockBounds(0.0F, 0.0F, 1.0F - var2, 1.0F, 1.0F, 1.0F);
+ }
+
+ if ((par1 & 3) == 1) {
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, var2);
+ }
+
+ if ((par1 & 3) == 2) {
+ this.setBlockBounds(1.0F - var2, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
+ }
+
+ if ((par1 & 3) == 3) {
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, var2, 1.0F, 1.0F);
+ }
+ }
+ }
+
+ /**
+ * Called when the block is clicked by a player. Args: x, y, z, entityPlayer
+ */
+ public void onBlockClicked(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer) {
+ }
+
+ /**
+ * Called upon block activation (right click on the block.)
+ */
+ public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer,
+ int par6, float par7, float par8, float par9) {
+ if (this.blockMaterial == Material.iron) {
+ return true;
+ } else {
+ int var10 = par1World.getBlockMetadata(par2, par3, par4);
+ par1World.setBlockMetadata(par2, par3, par4, var10 ^ 4, 2);
+ par1World.playAuxSFXAtEntity(par5EntityPlayer, 1003, par2, par3, par4, 0);
+ return true;
+ }
+ }
+
+ public void onPoweredBlockChange(World par1World, int par2, int par3, int par4, boolean par5) {
+ int var6 = par1World.getBlockMetadata(par2, par3, par4);
+ boolean var7 = (var6 & 4) > 0;
+
+ if (var7 != par5) {
+ par1World.setBlockMetadata(par2, par3, par4, var6 ^ 4, 2);
+ par1World.playAuxSFXAtEntity((EntityPlayer) null, 1003, par2, par3, par4, 0);
+ }
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ if (!par1World.isRemote) {
+ int var6 = par1World.getBlockMetadata(par2, par3, par4);
+ int var7 = par2;
+ int var8 = par4;
+
+ if ((var6 & 3) == 0) {
+ var8 = par4 + 1;
+ }
+
+ if ((var6 & 3) == 1) {
+ --var8;
+ }
+
+ if ((var6 & 3) == 2) {
+ var7 = par2 + 1;
+ }
+
+ if ((var6 & 3) == 3) {
+ --var7;
+ }
+
+ if (!isValidSupportBlock(par1World.getBlockId(var7, par3, var8))) {
+ par1World.setBlockToAir(par2, par3, par4);
+ this.dropBlockAsItem(par1World, par2, par3, par4, var6, 0);
+ }
+
+ boolean var9 = par1World.isBlockIndirectlyGettingPowered(par2, par3, par4);
+
+ if (var9 || par5 > 0 && Block.blocksList[par5].canProvidePower()) {
+ this.onPoweredBlockChange(par1World, par2, par3, par4, var9);
+ }
+ }
+ }
+
+ /**
+ * Ray traces through the blocks collision from start vector to end vector
+ * returning a ray trace hit. Args: world, x, y, z, startVec, endVec
+ */
+ public MovingObjectPosition collisionRayTrace(World par1World, int par2, int par3, int par4, Vec3 par5Vec3,
+ Vec3 par6Vec3) {
+ this.setBlockBoundsBasedOnState(par1World, par2, par3, par4);
+ return super.collisionRayTrace(par1World, par2, par3, par4, par5Vec3, par6Vec3);
+ }
+
+ /**
+ * Called when a block is placed using its ItemBlock. Args: World, X, Y, Z,
+ * side, hitX, hitY, hitZ, block metadata
+ */
+ public int onBlockPlaced(World par1World, int par2, int par3, int par4, int par5, float par6, float par7,
+ float par8, int par9) {
+ int var10 = 0;
+
+ if (par5 == 2) {
+ var10 = 0;
+ }
+
+ if (par5 == 3) {
+ var10 = 1;
+ }
+
+ if (par5 == 4) {
+ var10 = 2;
+ }
+
+ if (par5 == 5) {
+ var10 = 3;
+ }
+
+ if (par5 != 1 && par5 != 0 && par7 > 0.5F) {
+ var10 |= 8;
+ }
+
+ return var10;
+ }
+
+ /**
+ * checks to see if you can place this block can be placed on that side of a
+ * block: BlockLever overrides
+ */
+ public boolean canPlaceBlockOnSide(World par1World, int par2, int par3, int par4, int par5) {
+ if (par5 == 0) {
+ return false;
+ } else if (par5 == 1) {
+ return false;
+ } else {
+ if (par5 == 2) {
+ ++par4;
+ }
+
+ if (par5 == 3) {
+ --par4;
+ }
+
+ if (par5 == 4) {
+ ++par2;
+ }
+
+ if (par5 == 5) {
+ --par2;
+ }
+
+ return isValidSupportBlock(par1World.getBlockId(par2, par3, par4));
+ }
+ }
+
+ public static boolean isTrapdoorOpen(int par0) {
+ return (par0 & 4) != 0;
+ }
+
+ /**
+ * Checks if the block ID is a valid support block for the trap door to connect
+ * with. If it is not the trapdoor is dropped into the world.
+ */
+ private static boolean isValidSupportBlock(int par0) {
+ if (par0 <= 0) {
+ return false;
+ } else {
+ Block var1 = Block.blocksList[par0];
+ return var1 != null && var1.blockMaterial.isOpaque() && var1.renderAsNormalBlock()
+ || var1 == Block.glowStone || var1 instanceof BlockHalfSlab || var1 instanceof BlockStairs;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockTripWire.java b/sp-server/src/main/java/net/minecraft/src/BlockTripWire.java
new file mode 100644
index 0000000..c563928
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockTripWire.java
@@ -0,0 +1,217 @@
+package net.minecraft.src;
+
+import java.util.Iterator;
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockTripWire extends Block {
+ public BlockTripWire(int par1) {
+ super(par1, Material.circuits);
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.15625F, 1.0F);
+ this.setTickRandomly(true);
+ }
+
+ /**
+ * How many world ticks before ticking
+ */
+ public int tickRate(World par1World) {
+ return 10;
+ }
+
+ /**
+ * Returns a bounding box from the pool of bounding boxes (this means this box
+ * can change after the pool has been cleared to be reused)
+ */
+ public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) {
+ return null;
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 30;
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return Item.silk.itemID;
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ int var6 = par1World.getBlockMetadata(par2, par3, par4);
+ boolean var7 = (var6 & 2) == 2;
+ boolean var8 = !par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4);
+
+ if (var7 != var8) {
+ this.dropBlockAsItem(par1World, par2, par3, par4, var6, 0);
+ par1World.setBlockToAir(par2, par3, par4);
+ }
+ }
+
+ /**
+ * Updates the blocks bounds based on its current state. Args: world, x, y, z
+ */
+ public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ int var5 = par1IBlockAccess.getBlockMetadata(par2, par3, par4);
+ boolean var6 = (var5 & 4) == 4;
+ boolean var7 = (var5 & 2) == 2;
+
+ if (!var7) {
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.09375F, 1.0F);
+ } else if (!var6) {
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.5F, 1.0F);
+ } else {
+ this.setBlockBounds(0.0F, 0.0625F, 0.0F, 1.0F, 0.15625F, 1.0F);
+ }
+ }
+
+ /**
+ * Called whenever the block is added into the world. Args: world, x, y, z
+ */
+ public void onBlockAdded(World par1World, int par2, int par3, int par4) {
+ int var5 = par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4) ? 0 : 2;
+ par1World.setBlockMetadata(par2, par3, par4, var5, 3);
+ this.func_72149_e(par1World, par2, par3, par4, var5);
+ }
+
+ /**
+ * ejects contained items into the world, and notifies neighbours of an update,
+ * as appropriate
+ */
+ public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) {
+ this.func_72149_e(par1World, par2, par3, par4, par6 | 1);
+ }
+
+ /**
+ * Called when the block is attempted to be harvested
+ */
+ public void onBlockHarvested(World par1World, int par2, int par3, int par4, int par5,
+ EntityPlayer par6EntityPlayer) {
+ if (!par1World.isRemote) {
+ if (par6EntityPlayer.getCurrentEquippedItem() != null
+ && par6EntityPlayer.getCurrentEquippedItem().itemID == Item.shears.itemID) {
+ par1World.setBlockMetadata(par2, par3, par4, par5 | 8, 4);
+ }
+ }
+ }
+
+ private void func_72149_e(World par1World, int par2, int par3, int par4, int par5) {
+ int var6 = 0;
+
+ while (var6 < 2) {
+ int var7 = 1;
+
+ while (true) {
+ if (var7 < 42) {
+ int var8 = par2 + Direction.offsetX[var6] * var7;
+ int var9 = par4 + Direction.offsetZ[var6] * var7;
+ int var10 = par1World.getBlockId(var8, par3, var9);
+
+ if (var10 == Block.tripWireSource.blockID) {
+ int var11 = par1World.getBlockMetadata(var8, par3, var9) & 3;
+
+ if (var11 == Direction.footInvisibleFaceRemap[var6]) {
+ Block.tripWireSource.func_72143_a(par1World, var8, par3, var9, var10,
+ par1World.getBlockMetadata(var8, par3, var9), true, var7, par5);
+ }
+ } else if (var10 == Block.tripWire.blockID) {
+ ++var7;
+ continue;
+ }
+ }
+
+ ++var6;
+ break;
+ }
+ }
+ }
+
+ /**
+ * Triggered whenever an entity collides with this block (enters into the
+ * block). Args: world, x, y, z, entity
+ */
+ public void onEntityCollidedWithBlock(World par1World, int par2, int par3, int par4, Entity par5Entity) {
+ if (!par1World.isRemote) {
+ if ((par1World.getBlockMetadata(par2, par3, par4) & 1) != 1) {
+ this.updateTripWireState(par1World, par2, par3, par4);
+ }
+ }
+ }
+
+ /**
+ * Ticks the block if it's been scheduled
+ */
+ public void updateTick(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ if (!par1World.isRemote) {
+ if ((par1World.getBlockMetadata(par2, par3, par4) & 1) == 1) {
+ this.updateTripWireState(par1World, par2, par3, par4);
+ }
+ }
+ }
+
+ private void updateTripWireState(World par1World, int par2, int par3, int par4) {
+ int var5 = par1World.getBlockMetadata(par2, par3, par4);
+ boolean var6 = (var5 & 1) == 1;
+ boolean var7 = false;
+ List var8 = par1World.getEntitiesWithinAABBExcludingEntity((Entity) null,
+ AxisAlignedBB.getAABBPool().getAABB((double) par2 + this.minX, (double) par3 + this.minY,
+ (double) par4 + this.minZ, (double) par2 + this.maxX, (double) par3 + this.maxY,
+ (double) par4 + this.maxZ));
+
+ if (!var8.isEmpty()) {
+ Iterator var9 = var8.iterator();
+
+ while (var9.hasNext()) {
+ Entity var10 = (Entity) var9.next();
+
+ if (!var10.doesEntityNotTriggerPressurePlate()) {
+ var7 = true;
+ break;
+ }
+ }
+ }
+
+ if (var7 && !var6) {
+ var5 |= 1;
+ }
+
+ if (!var7 && var6) {
+ var5 &= -2;
+ }
+
+ if (var7 != var6) {
+ par1World.setBlockMetadata(par2, par3, par4, var5, 3);
+ this.func_72149_e(par1World, par2, par3, par4, var5);
+ }
+
+ if (var7) {
+ par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, this.tickRate(par1World));
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockTripWireSource.java b/sp-server/src/main/java/net/minecraft/src/BlockTripWireSource.java
new file mode 100644
index 0000000..e5596cc
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockTripWireSource.java
@@ -0,0 +1,373 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockTripWireSource extends Block {
+ public BlockTripWireSource(int par1) {
+ super(par1, Material.circuits);
+ this.setCreativeTab(CreativeTabs.tabRedstone);
+ this.setTickRandomly(true);
+ }
+
+ /**
+ * Returns a bounding box from the pool of bounding boxes (this means this box
+ * can change after the pool has been cleared to be reused)
+ */
+ public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) {
+ return null;
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 29;
+ }
+
+ /**
+ * How many world ticks before ticking
+ */
+ public int tickRate(World par1World) {
+ return 10;
+ }
+
+ /**
+ * checks to see if you can place this block can be placed on that side of a
+ * block: BlockLever overrides
+ */
+ public boolean canPlaceBlockOnSide(World par1World, int par2, int par3, int par4, int par5) {
+ return par5 == 2 && par1World.isBlockNormalCube(par2, par3, par4 + 1) ? true
+ : (par5 == 3 && par1World.isBlockNormalCube(par2, par3, par4 - 1) ? true
+ : (par5 == 4 && par1World.isBlockNormalCube(par2 + 1, par3, par4) ? true
+ : par5 == 5 && par1World.isBlockNormalCube(par2 - 1, par3, par4)));
+ }
+
+ /**
+ * Checks to see if its valid to put this block at the specified coordinates.
+ * Args: world, x, y, z
+ */
+ public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4) {
+ return par1World.isBlockNormalCube(par2 - 1, par3, par4) ? true
+ : (par1World.isBlockNormalCube(par2 + 1, par3, par4) ? true
+ : (par1World.isBlockNormalCube(par2, par3, par4 - 1) ? true
+ : par1World.isBlockNormalCube(par2, par3, par4 + 1)));
+ }
+
+ /**
+ * Called when a block is placed using its ItemBlock. Args: World, X, Y, Z,
+ * side, hitX, hitY, hitZ, block metadata
+ */
+ public int onBlockPlaced(World par1World, int par2, int par3, int par4, int par5, float par6, float par7,
+ float par8, int par9) {
+ byte var10 = 0;
+
+ if (par5 == 2 && par1World.isBlockNormalCubeDefault(par2, par3, par4 + 1, true)) {
+ var10 = 2;
+ }
+
+ if (par5 == 3 && par1World.isBlockNormalCubeDefault(par2, par3, par4 - 1, true)) {
+ var10 = 0;
+ }
+
+ if (par5 == 4 && par1World.isBlockNormalCubeDefault(par2 + 1, par3, par4, true)) {
+ var10 = 1;
+ }
+
+ if (par5 == 5 && par1World.isBlockNormalCubeDefault(par2 - 1, par3, par4, true)) {
+ var10 = 3;
+ }
+
+ return var10;
+ }
+
+ /**
+ * Called after a block is placed
+ */
+ public void onPostBlockPlaced(World par1World, int par2, int par3, int par4, int par5) {
+ this.func_72143_a(par1World, par2, par3, par4, this.blockID, par5, false, -1, 0);
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ if (par5 != this.blockID) {
+ if (this.func_72144_l(par1World, par2, par3, par4)) {
+ int var6 = par1World.getBlockMetadata(par2, par3, par4);
+ int var7 = var6 & 3;
+ boolean var8 = false;
+
+ if (!par1World.isBlockNormalCube(par2 - 1, par3, par4) && var7 == 3) {
+ var8 = true;
+ }
+
+ if (!par1World.isBlockNormalCube(par2 + 1, par3, par4) && var7 == 1) {
+ var8 = true;
+ }
+
+ if (!par1World.isBlockNormalCube(par2, par3, par4 - 1) && var7 == 0) {
+ var8 = true;
+ }
+
+ if (!par1World.isBlockNormalCube(par2, par3, par4 + 1) && var7 == 2) {
+ var8 = true;
+ }
+
+ if (var8) {
+ this.dropBlockAsItem(par1World, par2, par3, par4, var6, 0);
+ par1World.setBlockToAir(par2, par3, par4);
+ }
+ }
+ }
+ }
+
+ public void func_72143_a(World par1World, int par2, int par3, int par4, int par5, int par6, boolean par7, int par8,
+ int par9) {
+ int var10 = par6 & 3;
+ boolean var11 = (par6 & 4) == 4;
+ boolean var12 = (par6 & 8) == 8;
+ boolean var13 = par5 == Block.tripWireSource.blockID;
+ boolean var14 = false;
+ boolean var15 = !par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4);
+ int var16 = Direction.offsetX[var10];
+ int var17 = Direction.offsetZ[var10];
+ int var18 = 0;
+ int[] var19 = new int[42];
+ int var20;
+ int var21;
+ int var22;
+ int var23;
+ int var24;
+
+ for (var20 = 1; var20 < 42; ++var20) {
+ var21 = par2 + var16 * var20;
+ var22 = par4 + var17 * var20;
+ var23 = par1World.getBlockId(var21, par3, var22);
+
+ if (var23 == Block.tripWireSource.blockID) {
+ var24 = par1World.getBlockMetadata(var21, par3, var22);
+
+ if ((var24 & 3) == Direction.footInvisibleFaceRemap[var10]) {
+ var18 = var20;
+ }
+
+ break;
+ }
+
+ if (var23 != Block.tripWire.blockID && var20 != par8) {
+ var19[var20] = -1;
+ var13 = false;
+ } else {
+ var24 = var20 == par8 ? par9 : par1World.getBlockMetadata(var21, par3, var22);
+ boolean var25 = (var24 & 8) != 8;
+ boolean var26 = (var24 & 1) == 1;
+ boolean var27 = (var24 & 2) == 2;
+ var13 &= var27 == var15;
+ var14 |= var25 && var26;
+ var19[var20] = var24;
+
+ if (var20 == par8) {
+ par1World.scheduleBlockUpdate(par2, par3, par4, par5, this.tickRate(par1World));
+ var13 &= var25;
+ }
+ }
+ }
+
+ var13 &= var18 > 1;
+ var14 &= var13;
+ var20 = (var13 ? 4 : 0) | (var14 ? 8 : 0);
+ par6 = var10 | var20;
+
+ if (var18 > 0) {
+ var21 = par2 + var16 * var18;
+ var22 = par4 + var17 * var18;
+ var23 = Direction.footInvisibleFaceRemap[var10];
+ par1World.setBlockMetadata(var21, par3, var22, var23 | var20, 3);
+ this.notifyNeighborOfChange(par1World, var21, par3, var22, var23);
+ this.playSoundEffect(par1World, var21, par3, var22, var13, var14, var11, var12);
+ }
+
+ this.playSoundEffect(par1World, par2, par3, par4, var13, var14, var11, var12);
+
+ if (par5 > 0) {
+ par1World.setBlockMetadata(par2, par3, par4, par6, 3);
+
+ if (par7) {
+ this.notifyNeighborOfChange(par1World, par2, par3, par4, var10);
+ }
+ }
+
+ if (var11 != var13) {
+ for (var21 = 1; var21 < var18; ++var21) {
+ var22 = par2 + var16 * var21;
+ var23 = par4 + var17 * var21;
+ var24 = var19[var21];
+
+ if (var24 >= 0) {
+ if (var13) {
+ var24 |= 4;
+ } else {
+ var24 &= -5;
+ }
+
+ par1World.setBlockMetadata(var22, par3, var23, var24, 3);
+ }
+ }
+ }
+ }
+
+ /**
+ * Ticks the block if it's been scheduled
+ */
+ public void updateTick(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ this.func_72143_a(par1World, par2, par3, par4, this.blockID, par1World.getBlockMetadata(par2, par3, par4), true,
+ -1, 0);
+ }
+
+ /**
+ * only of the conditions are right
+ */
+ private void playSoundEffect(World par1World, int par2, int par3, int par4, boolean par5, boolean par6,
+ boolean par7, boolean par8) {
+ if (par6 && !par8) {
+ par1World.playSoundEffect((double) par2 + 0.5D, (double) par3 + 0.1D, (double) par4 + 0.5D, "random.click",
+ 0.4F, 0.6F);
+ } else if (!par6 && par8) {
+ par1World.playSoundEffect((double) par2 + 0.5D, (double) par3 + 0.1D, (double) par4 + 0.5D, "random.click",
+ 0.4F, 0.5F);
+ } else if (par5 && !par7) {
+ par1World.playSoundEffect((double) par2 + 0.5D, (double) par3 + 0.1D, (double) par4 + 0.5D, "random.click",
+ 0.4F, 0.7F);
+ } else if (!par5 && par7) {
+ par1World.playSoundEffect((double) par2 + 0.5D, (double) par3 + 0.1D, (double) par4 + 0.5D, "random.bowhit",
+ 0.4F, 1.2F / (par1World.rand.nextFloat() * 0.2F + 0.9F));
+ }
+ }
+
+ private void notifyNeighborOfChange(World par1World, int par2, int par3, int par4, int par5) {
+ par1World.notifyBlocksOfNeighborChange(par2, par3, par4, this.blockID);
+
+ if (par5 == 3) {
+ par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID);
+ } else if (par5 == 1) {
+ par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID);
+ } else if (par5 == 0) {
+ par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID);
+ } else if (par5 == 2) {
+ par1World.notifyBlocksOfNeighborChange(par2, par3, par4 + 1, this.blockID);
+ }
+ }
+
+ private boolean func_72144_l(World par1World, int par2, int par3, int par4) {
+ if (!this.canPlaceBlockAt(par1World, par2, par3, par4)) {
+ this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
+ par1World.setBlockToAir(par2, par3, par4);
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * Updates the blocks bounds based on its current state. Args: world, x, y, z
+ */
+ public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ int var5 = par1IBlockAccess.getBlockMetadata(par2, par3, par4) & 3;
+ float var6 = 0.1875F;
+
+ if (var5 == 3) {
+ this.setBlockBounds(0.0F, 0.2F, 0.5F - var6, var6 * 2.0F, 0.8F, 0.5F + var6);
+ } else if (var5 == 1) {
+ this.setBlockBounds(1.0F - var6 * 2.0F, 0.2F, 0.5F - var6, 1.0F, 0.8F, 0.5F + var6);
+ } else if (var5 == 0) {
+ this.setBlockBounds(0.5F - var6, 0.2F, 0.0F, 0.5F + var6, 0.8F, var6 * 2.0F);
+ } else if (var5 == 2) {
+ this.setBlockBounds(0.5F - var6, 0.2F, 1.0F - var6 * 2.0F, 0.5F + var6, 0.8F, 1.0F);
+ }
+ }
+
+ /**
+ * ejects contained items into the world, and notifies neighbours of an update,
+ * as appropriate
+ */
+ public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) {
+ boolean var7 = (par6 & 4) == 4;
+ boolean var8 = (par6 & 8) == 8;
+
+ if (var7 || var8) {
+ this.func_72143_a(par1World, par2, par3, par4, 0, par6, false, -1, 0);
+ }
+
+ if (var8) {
+ par1World.notifyBlocksOfNeighborChange(par2, par3, par4, this.blockID);
+ int var9 = par6 & 3;
+
+ if (var9 == 3) {
+ par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID);
+ } else if (var9 == 1) {
+ par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID);
+ } else if (var9 == 0) {
+ par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID);
+ } else if (var9 == 2) {
+ par1World.notifyBlocksOfNeighborChange(par2, par3, par4 + 1, this.blockID);
+ }
+ }
+
+ super.breakBlock(par1World, par2, par3, par4, par5, par6);
+ }
+
+ /**
+ * Returns true if the block is emitting indirect/weak redstone power on the
+ * specified side. If isBlockNormalCube returns true, standard redstone
+ * propagation rules will apply instead and this will not be called. Args:
+ * World, X, Y, Z, side. Note that the side is reversed - eg it is 1 (up) when
+ * checking the bottom of the block.
+ */
+ public int isProvidingWeakPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) {
+ return (par1IBlockAccess.getBlockMetadata(par2, par3, par4) & 8) == 8 ? 15 : 0;
+ }
+
+ /**
+ * Returns true if the block is emitting direct/strong redstone power on the
+ * specified side. Args: World, X, Y, Z, side. Note that the side is reversed -
+ * eg it is 1 (up) when checking the bottom of the block.
+ */
+ public int isProvidingStrongPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) {
+ int var6 = par1IBlockAccess.getBlockMetadata(par2, par3, par4);
+
+ if ((var6 & 8) != 8) {
+ return 0;
+ } else {
+ int var7 = var6 & 3;
+ return var7 == 2 && par5 == 2 ? 15
+ : (var7 == 0 && par5 == 3 ? 15 : (var7 == 1 && par5 == 4 ? 15 : (var7 == 3 && par5 == 5 ? 15 : 0)));
+ }
+ }
+
+ /**
+ * Can this block provide power. Only wire currently seems to have this change
+ * based on its state.
+ */
+ public boolean canProvidePower() {
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockVine.java b/sp-server/src/main/java/net/minecraft/src/BlockVine.java
new file mode 100644
index 0000000..d8fd4a9
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockVine.java
@@ -0,0 +1,382 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockVine extends Block {
+ public BlockVine(int par1) {
+ super(par1, Material.vine);
+ this.setTickRandomly(true);
+ this.setCreativeTab(CreativeTabs.tabDecorations);
+ }
+
+ /**
+ * Sets the block's bounds for rendering it as an item
+ */
+ public void setBlockBoundsForItemRender() {
+ this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 20;
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ /**
+ * Updates the blocks bounds based on its current state. Args: world, x, y, z
+ */
+ public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ int var6 = par1IBlockAccess.getBlockMetadata(par2, par3, par4);
+ float var7 = 1.0F;
+ float var8 = 1.0F;
+ float var9 = 1.0F;
+ float var10 = 0.0F;
+ float var11 = 0.0F;
+ float var12 = 0.0F;
+ boolean var13 = var6 > 0;
+
+ if ((var6 & 2) != 0) {
+ var10 = Math.max(var10, 0.0625F);
+ var7 = 0.0F;
+ var8 = 0.0F;
+ var11 = 1.0F;
+ var9 = 0.0F;
+ var12 = 1.0F;
+ var13 = true;
+ }
+
+ if ((var6 & 8) != 0) {
+ var7 = Math.min(var7, 0.9375F);
+ var10 = 1.0F;
+ var8 = 0.0F;
+ var11 = 1.0F;
+ var9 = 0.0F;
+ var12 = 1.0F;
+ var13 = true;
+ }
+
+ if ((var6 & 4) != 0) {
+ var12 = Math.max(var12, 0.0625F);
+ var9 = 0.0F;
+ var7 = 0.0F;
+ var10 = 1.0F;
+ var8 = 0.0F;
+ var11 = 1.0F;
+ var13 = true;
+ }
+
+ if ((var6 & 1) != 0) {
+ var9 = Math.min(var9, 0.9375F);
+ var12 = 1.0F;
+ var7 = 0.0F;
+ var10 = 1.0F;
+ var8 = 0.0F;
+ var11 = 1.0F;
+ var13 = true;
+ }
+
+ if (!var13 && this.canBePlacedOn(par1IBlockAccess.getBlockId(par2, par3 + 1, par4))) {
+ var8 = Math.min(var8, 0.9375F);
+ var11 = 1.0F;
+ var7 = 0.0F;
+ var10 = 1.0F;
+ var9 = 0.0F;
+ var12 = 1.0F;
+ }
+
+ this.setBlockBounds(var7, var8, var9, var10, var11, var12);
+ }
+
+ /**
+ * Returns a bounding box from the pool of bounding boxes (this means this box
+ * can change after the pool has been cleared to be reused)
+ */
+ public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) {
+ return null;
+ }
+
+ /**
+ * checks to see if you can place this block can be placed on that side of a
+ * block: BlockLever overrides
+ */
+ public boolean canPlaceBlockOnSide(World par1World, int par2, int par3, int par4, int par5) {
+ switch (par5) {
+ case 1:
+ return this.canBePlacedOn(par1World.getBlockId(par2, par3 + 1, par4));
+
+ case 2:
+ return this.canBePlacedOn(par1World.getBlockId(par2, par3, par4 + 1));
+
+ case 3:
+ return this.canBePlacedOn(par1World.getBlockId(par2, par3, par4 - 1));
+
+ case 4:
+ return this.canBePlacedOn(par1World.getBlockId(par2 + 1, par3, par4));
+
+ case 5:
+ return this.canBePlacedOn(par1World.getBlockId(par2 - 1, par3, par4));
+
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * returns true if a vine can be placed on that block (checks for render as
+ * normal block and if it is solid)
+ */
+ private boolean canBePlacedOn(int par1) {
+ if (par1 == 0) {
+ return false;
+ } else {
+ Block var2 = Block.blocksList[par1];
+ return var2.renderAsNormalBlock() && var2.blockMaterial.blocksMovement();
+ }
+ }
+
+ /**
+ * Returns if the vine can stay in the world. It also changes the metadata
+ * according to neighboring blocks.
+ */
+ private boolean canVineStay(World par1World, int par2, int par3, int par4) {
+ int var5 = par1World.getBlockMetadata(par2, par3, par4);
+ int var6 = var5;
+
+ if (var5 > 0) {
+ for (int var7 = 0; var7 <= 3; ++var7) {
+ int var8 = 1 << var7;
+
+ if ((var5 & var8) != 0
+ && !this.canBePlacedOn(par1World.getBlockId(par2 + Direction.offsetX[var7], par3,
+ par4 + Direction.offsetZ[var7]))
+ && (par1World.getBlockId(par2, par3 + 1, par4) != this.blockID
+ || (par1World.getBlockMetadata(par2, par3 + 1, par4) & var8) == 0)) {
+ var6 &= ~var8;
+ }
+ }
+ }
+
+ if (var6 == 0 && !this.canBePlacedOn(par1World.getBlockId(par2, par3 + 1, par4))) {
+ return false;
+ } else {
+ if (var6 != var5) {
+ par1World.setBlockMetadata(par2, par3, par4, var6, 2);
+ }
+
+ return true;
+ }
+ }
+
+ /**
+ * Lets the block know when one of its neighbor changes. Doesn't know which
+ * neighbor changed (coordinates passed are their own) Args: x, y, z, neighbor
+ * blockID
+ */
+ public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
+ if (!par1World.isRemote && !this.canVineStay(par1World, par2, par3, par4)) {
+ this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
+ par1World.setBlockToAir(par2, par3, par4);
+ }
+ }
+
+ /**
+ * Ticks the block if it's been scheduled
+ */
+ public void updateTick(World par1World, int par2, int par3, int par4, EaglercraftRandom par5Random) {
+ if (!par1World.isRemote && par1World.rand.nextInt(4) == 0) {
+ byte var6 = 4;
+ int var7 = 5;
+ boolean var8 = false;
+ int var9;
+ int var10;
+ int var11;
+ label138:
+
+ for (var9 = par2 - var6; var9 <= par2 + var6; ++var9) {
+ for (var10 = par4 - var6; var10 <= par4 + var6; ++var10) {
+ for (var11 = par3 - 1; var11 <= par3 + 1; ++var11) {
+ if (par1World.getBlockId(var9, var11, var10) == this.blockID) {
+ --var7;
+
+ if (var7 <= 0) {
+ var8 = true;
+ break label138;
+ }
+ }
+ }
+ }
+ }
+
+ var9 = par1World.getBlockMetadata(par2, par3, par4);
+ var10 = par1World.rand.nextInt(6);
+ var11 = Direction.facingToDirection[var10];
+ int var12;
+ int var13;
+
+ if (var10 == 1 && par3 < 255 && par1World.isAirBlock(par2, par3 + 1, par4)) {
+ if (var8) {
+ return;
+ }
+
+ var12 = par1World.rand.nextInt(16) & var9;
+
+ if (var12 > 0) {
+ for (var13 = 0; var13 <= 3; ++var13) {
+ if (!this.canBePlacedOn(par1World.getBlockId(par2 + Direction.offsetX[var13], par3 + 1,
+ par4 + Direction.offsetZ[var13]))) {
+ var12 &= ~(1 << var13);
+ }
+ }
+
+ if (var12 > 0) {
+ par1World.setBlock(par2, par3 + 1, par4, this.blockID, var12, 2);
+ }
+ }
+ } else {
+ int var14;
+
+ if (var10 >= 2 && var10 <= 5 && (var9 & 1 << var11) == 0) {
+ if (var8) {
+ return;
+ }
+
+ var12 = par1World.getBlockId(par2 + Direction.offsetX[var11], par3,
+ par4 + Direction.offsetZ[var11]);
+
+ if (var12 != 0 && Block.blocksList[var12] != null) {
+ if (Block.blocksList[var12].blockMaterial.isOpaque()
+ && Block.blocksList[var12].renderAsNormalBlock()) {
+ par1World.setBlockMetadata(par2, par3, par4, var9 | 1 << var11, 2);
+ }
+ } else {
+ var13 = var11 + 1 & 3;
+ var14 = var11 + 3 & 3;
+
+ if ((var9 & 1 << var13) != 0 && this.canBePlacedOn(
+ par1World.getBlockId(par2 + Direction.offsetX[var11] + Direction.offsetX[var13], par3,
+ par4 + Direction.offsetZ[var11] + Direction.offsetZ[var13]))) {
+ par1World.setBlock(par2 + Direction.offsetX[var11], par3, par4 + Direction.offsetZ[var11],
+ this.blockID, 1 << var13, 2);
+ } else if ((var9 & 1 << var14) != 0 && this.canBePlacedOn(
+ par1World.getBlockId(par2 + Direction.offsetX[var11] + Direction.offsetX[var14], par3,
+ par4 + Direction.offsetZ[var11] + Direction.offsetZ[var14]))) {
+ par1World.setBlock(par2 + Direction.offsetX[var11], par3, par4 + Direction.offsetZ[var11],
+ this.blockID, 1 << var14, 2);
+ } else if ((var9 & 1 << var13) != 0
+ && par1World.isAirBlock(par2 + Direction.offsetX[var11] + Direction.offsetX[var13],
+ par3, par4 + Direction.offsetZ[var11] + Direction.offsetZ[var13])
+ && this.canBePlacedOn(par1World.getBlockId(par2 + Direction.offsetX[var13], par3,
+ par4 + Direction.offsetZ[var13]))) {
+ par1World.setBlock(par2 + Direction.offsetX[var11] + Direction.offsetX[var13], par3,
+ par4 + Direction.offsetZ[var11] + Direction.offsetZ[var13], this.blockID,
+ 1 << (var11 + 2 & 3), 2);
+ } else if ((var9 & 1 << var14) != 0
+ && par1World.isAirBlock(par2 + Direction.offsetX[var11] + Direction.offsetX[var14],
+ par3, par4 + Direction.offsetZ[var11] + Direction.offsetZ[var14])
+ && this.canBePlacedOn(par1World.getBlockId(par2 + Direction.offsetX[var14], par3,
+ par4 + Direction.offsetZ[var14]))) {
+ par1World.setBlock(par2 + Direction.offsetX[var11] + Direction.offsetX[var14], par3,
+ par4 + Direction.offsetZ[var11] + Direction.offsetZ[var14], this.blockID,
+ 1 << (var11 + 2 & 3), 2);
+ } else if (this.canBePlacedOn(par1World.getBlockId(par2 + Direction.offsetX[var11], par3 + 1,
+ par4 + Direction.offsetZ[var11]))) {
+ par1World.setBlock(par2 + Direction.offsetX[var11], par3, par4 + Direction.offsetZ[var11],
+ this.blockID, 0, 2);
+ }
+ }
+ } else if (par3 > 1) {
+ var12 = par1World.getBlockId(par2, par3 - 1, par4);
+
+ if (var12 == 0) {
+ var13 = par1World.rand.nextInt(16) & var9;
+
+ if (var13 > 0) {
+ par1World.setBlock(par2, par3 - 1, par4, this.blockID, var13, 2);
+ }
+ } else if (var12 == this.blockID) {
+ var13 = par1World.rand.nextInt(16) & var9;
+ var14 = par1World.getBlockMetadata(par2, par3 - 1, par4);
+
+ if (var14 != (var14 | var13)) {
+ par1World.setBlockMetadata(par2, par3 - 1, par4, var14 | var13, 2);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Called when a block is placed using its ItemBlock. Args: World, X, Y, Z,
+ * side, hitX, hitY, hitZ, block metadata
+ */
+ public int onBlockPlaced(World par1World, int par2, int par3, int par4, int par5, float par6, float par7,
+ float par8, int par9) {
+ byte var10 = 0;
+
+ switch (par5) {
+ case 2:
+ var10 = 1;
+ break;
+
+ case 3:
+ var10 = 4;
+ break;
+
+ case 4:
+ var10 = 8;
+ break;
+
+ case 5:
+ var10 = 2;
+ }
+
+ return var10 != 0 ? var10 : par9;
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return 0;
+ }
+
+ /**
+ * Returns the quantity of items to drop on block destruction.
+ */
+ public int quantityDropped(EaglercraftRandom par1Random) {
+ return 0;
+ }
+
+ /**
+ * Called when the player destroys a block with an item that can harvest it. (i,
+ * j, k) are the coordinates of the block and l is the block's subtype/damage.
+ */
+ public void harvestBlock(World par1World, EntityPlayer par2EntityPlayer, int par3, int par4, int par5, int par6) {
+ if (!par1World.isRemote && par2EntityPlayer.getCurrentEquippedItem() != null
+ && par2EntityPlayer.getCurrentEquippedItem().itemID == Item.shears.itemID) {
+ par2EntityPlayer.addStat(StatList.mineBlockStatArray[this.blockID], 1);
+ this.dropBlockAsItem_do(par1World, par3, par4, par5, new ItemStack(Block.vine, 1, 0));
+ } else {
+ super.harvestBlock(par1World, par2EntityPlayer, par3, par4, par5, par6);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockWall.java b/sp-server/src/main/java/net/minecraft/src/BlockWall.java
new file mode 100644
index 0000000..98a3d71
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockWall.java
@@ -0,0 +1,118 @@
+package net.minecraft.src;
+
+public class BlockWall extends Block {
+ /** The types of the wall. */
+ public static final String[] types = new String[] { "normal", "mossy" };
+
+ public BlockWall(int par1, Block par2Block) {
+ super(par1, par2Block.blockMaterial);
+ this.setHardness(par2Block.blockHardness);
+ this.setResistance(par2Block.blockResistance / 3.0F);
+ this.setStepSound(par2Block.stepSound);
+ this.setCreativeTab(CreativeTabs.tabBlock);
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 32;
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ public boolean getBlocksMovement(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ return false;
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * Updates the blocks bounds based on its current state. Args: world, x, y, z
+ */
+ public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ boolean var5 = this.canConnectWallTo(par1IBlockAccess, par2, par3, par4 - 1);
+ boolean var6 = this.canConnectWallTo(par1IBlockAccess, par2, par3, par4 + 1);
+ boolean var7 = this.canConnectWallTo(par1IBlockAccess, par2 - 1, par3, par4);
+ boolean var8 = this.canConnectWallTo(par1IBlockAccess, par2 + 1, par3, par4);
+ float var9 = 0.25F;
+ float var10 = 0.75F;
+ float var11 = 0.25F;
+ float var12 = 0.75F;
+ float var13 = 1.0F;
+
+ if (var5) {
+ var11 = 0.0F;
+ }
+
+ if (var6) {
+ var12 = 1.0F;
+ }
+
+ if (var7) {
+ var9 = 0.0F;
+ }
+
+ if (var8) {
+ var10 = 1.0F;
+ }
+
+ if (var5 && var6 && !var7 && !var8) {
+ var13 = 0.8125F;
+ var9 = 0.3125F;
+ var10 = 0.6875F;
+ } else if (!var5 && !var6 && var7 && var8) {
+ var13 = 0.8125F;
+ var11 = 0.3125F;
+ var12 = 0.6875F;
+ }
+
+ this.setBlockBounds(var9, 0.0F, var11, var10, var13, var12);
+ }
+
+ /**
+ * Returns a bounding box from the pool of bounding boxes (this means this box
+ * can change after the pool has been cleared to be reused)
+ */
+ public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) {
+ this.setBlockBoundsBasedOnState(par1World, par2, par3, par4);
+ this.maxY = 1.5D;
+ return super.getCollisionBoundingBoxFromPool(par1World, par2, par3, par4);
+ }
+
+ /**
+ * Return whether an adjacent block can connect to a wall.
+ */
+ public boolean canConnectWallTo(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) {
+ int var5 = par1IBlockAccess.getBlockId(par2, par3, par4);
+
+ if (var5 != this.blockID && var5 != Block.fenceGate.blockID) {
+ Block var6 = Block.blocksList[var5];
+ return var6 != null && var6.blockMaterial.isOpaque() && var6.renderAsNormalBlock()
+ ? var6.blockMaterial != Material.pumpkin
+ : false;
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * Determines the damage on the item the block drops. Used in cloth and wood.
+ */
+ public int damageDropped(int par1) {
+ return par1;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockWeb.java b/sp-server/src/main/java/net/minecraft/src/BlockWeb.java
new file mode 100644
index 0000000..cb66982
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockWeb.java
@@ -0,0 +1,65 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockWeb extends Block {
+ public BlockWeb(int par1) {
+ super(par1, Material.web);
+ this.setCreativeTab(CreativeTabs.tabDecorations);
+ }
+
+ /**
+ * Triggered whenever an entity collides with this block (enters into the
+ * block). Args: world, x, y, z, entity
+ */
+ public void onEntityCollidedWithBlock(World par1World, int par2, int par3, int par4, Entity par5Entity) {
+ par5Entity.setInWeb();
+ }
+
+ /**
+ * Is this block (a) opaque and (b) a full 1m cube? This determines whether or
+ * not to render the shared face of two adjacent blocks and also whether the
+ * player can attach torches, redstone wire, etc to this block.
+ */
+ public boolean isOpaqueCube() {
+ return false;
+ }
+
+ /**
+ * Returns a bounding box from the pool of bounding boxes (this means this box
+ * can change after the pool has been cleared to be reused)
+ */
+ public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) {
+ return null;
+ }
+
+ /**
+ * The type of render function that is called for this block
+ */
+ public int getRenderType() {
+ return 1;
+ }
+
+ /**
+ * If this block doesn't render as an ordinary block it will return False
+ * (examples: signs, buttons, stairs, etc)
+ */
+ public boolean renderAsNormalBlock() {
+ return false;
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return Item.silk.itemID;
+ }
+
+ /**
+ * Return true if a player with Silk Touch can harvest this block directly, and
+ * not its normal drops.
+ */
+ protected boolean canSilkHarvest() {
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockWood.java b/sp-server/src/main/java/net/minecraft/src/BlockWood.java
new file mode 100644
index 0000000..ee1b40b
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockWood.java
@@ -0,0 +1,19 @@
+package net.minecraft.src;
+
+public class BlockWood extends Block {
+ /** The type of tree this block came from. */
+ public static final String[] woodType = new String[] { "oak", "spruce", "birch", "jungle" };
+ public static final String[] woodTextureTypes = new String[] { "wood", "wood_spruce", "wood_birch", "wood_jungle" };
+
+ public BlockWood(int par1) {
+ super(par1, Material.wood);
+ this.setCreativeTab(CreativeTabs.tabBlock);
+ }
+
+ /**
+ * Determines the damage on the item the block drops. Used in cloth and wood.
+ */
+ public int damageDropped(int par1) {
+ return par1;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockWoodSlab.java b/sp-server/src/main/java/net/minecraft/src/BlockWoodSlab.java
new file mode 100644
index 0000000..bffc4e7
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockWoodSlab.java
@@ -0,0 +1,40 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class BlockWoodSlab extends BlockHalfSlab {
+ /** The type of tree this slab came from. */
+ public static final String[] woodType = new String[] { "oak", "spruce", "birch", "jungle" };
+
+ public BlockWoodSlab(int par1, boolean par2) {
+ super(par1, par2, Material.wood);
+ this.setCreativeTab(CreativeTabs.tabBlock);
+ }
+
+ /**
+ * Returns the ID of the items to drop on destruction.
+ */
+ public int idDropped(int par1, EaglercraftRandom par2Random, int par3) {
+ return Block.woodSingleSlab.blockID;
+ }
+
+ /**
+ * Returns an item stack containing a single instance of the current block type.
+ * 'i' is the block's subtype/damage and is ignored for blocks which do not
+ * support subtypes. Blocks which cannot be harvested should return null.
+ */
+ protected ItemStack createStackedBlock(int par1) {
+ return new ItemStack(Block.woodSingleSlab.blockID, 2, par1 & 7);
+ }
+
+ /**
+ * Returns the slab block name with step type.
+ */
+ public String getFullSlabName(int par1) {
+ if (par1 < 0 || par1 >= woodType.length) {
+ par1 = 0;
+ }
+
+ return super.getUnlocalizedName() + "." + woodType[par1];
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/BlockWorkbench.java b/sp-server/src/main/java/net/minecraft/src/BlockWorkbench.java
new file mode 100644
index 0000000..582da1e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/BlockWorkbench.java
@@ -0,0 +1,21 @@
+package net.minecraft.src;
+
+public class BlockWorkbench extends Block {
+ protected BlockWorkbench(int par1) {
+ super(par1, Material.wood);
+ this.setCreativeTab(CreativeTabs.tabDecorations);
+ }
+
+ /**
+ * Called upon block activation (right click on the block.)
+ */
+ public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer,
+ int par6, float par7, float par8, float par9) {
+ if (par1World.isRemote) {
+ return true;
+ } else {
+ par5EntityPlayer.displayGUIWorkbench(par2, par3, par4);
+ return true;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ChatAllowedCharacters.java b/sp-server/src/main/java/net/minecraft/src/ChatAllowedCharacters.java
new file mode 100644
index 0000000..9d016c9
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ChatAllowedCharacters.java
@@ -0,0 +1,64 @@
+package net.minecraft.src;
+
+public class ChatAllowedCharacters {
+ /**
+ * This String have the characters allowed in any text drawing of minecraft.
+ */
+ public static final String allowedCharacters = getAllowedCharacters();
+
+ /**
+ * Array of the special characters that are allowed in any text drawing of
+ * Minecraft.
+ */
+ public static final char[] allowedCharactersArray = new char[] { '/', '\n', '\r', '\t', '\u0000', '\f', '`', '?',
+ '*', '\\', '<', '>', '|', '\"', ':' };
+
+ /**
+ * Load the font.txt resource file, that is on UTF-8 format. This file contains
+ * the characters that minecraft can render Strings on screen.
+ */
+ private static String getAllowedCharacters() {
+ int[] codePoints = new int[]{
+ 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,
+ 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,
+ 64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,
+ 80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,
+ 39,97,98,99,100,101,102,103,104,105,106,107,108,
+ 109,110,111,112,113,114,115,116,117,118,119,120,
+ 121,122,123,124,125,126,8962,199,252,233,226,228,
+ 224,229,231,234,235,232,239,238,236,196,197,201,
+ 230,198,244,246,242,251,249,255,214,220,248,163,
+ 216,215,402,225,237,243,250,241,209,170,186,191,
+ 174,172,189,188,161,171,187
+ };
+ char[] chars = new char[codePoints.length];
+ for(int i = 0; i < codePoints.length; ++i) {
+ chars[i] = (char)codePoints[i];
+ }
+ return new String(chars);
+ }
+
+ public static final boolean isAllowedCharacter(char par0) {
+ return par0 != 167 && (allowedCharacters.indexOf(par0) >= 0 || par0 > 32);
+ }
+
+ /**
+ * Filter string by only keeping those characters for which isAllowedCharacter()
+ * returns true.
+ */
+ public static String filerAllowedCharacters(String par0Str) {
+ StringBuilder var1 = new StringBuilder();
+ char[] var2 = par0Str.toCharArray();
+ int var3 = var2.length;
+
+ for (int var4 = 0; var4 < var3; ++var4) {
+ char var5 = var2[var4];
+
+ if (isAllowedCharacter(var5)) {
+ var1.append(var5);
+ }
+ }
+
+ return var1.toString();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Chunk.java b/sp-server/src/main/java/net/minecraft/src/Chunk.java
new file mode 100644
index 0000000..c7b825a
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Chunk.java
@@ -0,0 +1,1133 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class Chunk {
+ /**
+ * Determines if the chunk is lit or not at a light value greater than 0.
+ */
+ public static boolean isLit;
+
+ /**
+ * Used to store block IDs, block MSBs, Sky-light maps, Block-light maps, and
+ * metadata. Each entry corresponds to a logical segment of 16x16x16 blocks,
+ * stacked vertically.
+ */
+ private ExtendedBlockStorage[] storageArrays;
+
+ /**
+ * Contains a 16x16 mapping on the X/Z plane of the biome ID to which each colum
+ * belongs.
+ */
+ private byte[] blockBiomeArray;
+
+ /**
+ * A map, similar to heightMap, that tracks how far down precipitation can fall.
+ */
+ public int[] precipitationHeightMap;
+
+ /** Which columns need their skylightMaps updated. */
+ public boolean[] updateSkylightColumns;
+
+ /** Whether or not this Chunk is currently loaded into the World */
+ public boolean isChunkLoaded;
+
+ /** Reference to the World object. */
+ public World worldObj;
+ public int[] heightMap;
+
+ /** The x coordinate of the chunk. */
+ public final int xPosition;
+
+ /** The z coordinate of the chunk. */
+ public final int zPosition;
+ private boolean isGapLightingUpdated;
+
+ /** A Map of ChunkPositions to TileEntities in this chunk */
+ public Map chunkTileEntityMap;
+
+ /**
+ * Array of Lists containing the entities in this Chunk. Each List represents a
+ * 16 block subchunk.
+ */
+ public List[] entityLists;
+
+ /** Boolean value indicating if the terrain is populated. */
+ public boolean isTerrainPopulated;
+
+ /**
+ * Set to true if the chunk has been modified and needs to be updated
+ * internally.
+ */
+ public boolean isModified;
+
+ /**
+ * Whether this Chunk has any Entities and thus requires saving on every tick
+ */
+ public boolean hasEntities;
+
+ /** The time according to World.worldTime when this chunk was last saved */
+ public long lastSaveTime;
+
+ /**
+ * Updates to this chunk will not be sent to clients if this is false. This
+ * field is set to true the first time the chunk is sent to a client, and never
+ * set to false.
+ */
+ public boolean sendUpdates;
+
+ /** Lowest value in the heightmap. */
+ public int heightMapMinimum;
+
+ /**
+ * Contains the current round-robin relight check index, and is implied as the
+ * relight check location as well.
+ */
+ private int queuedLightChecks;
+ boolean field_76653_p;
+
+ public Chunk(World par1World, int par2, int par3) {
+ this.storageArrays = new ExtendedBlockStorage[16];
+ this.blockBiomeArray = new byte[256];
+ this.precipitationHeightMap = new int[256];
+ this.updateSkylightColumns = new boolean[256];
+ this.isGapLightingUpdated = false;
+ this.chunkTileEntityMap = new HashMap();
+ this.isTerrainPopulated = false;
+ this.isModified = false;
+ this.hasEntities = false;
+ this.lastSaveTime = 0L;
+ this.sendUpdates = false;
+ this.heightMapMinimum = 0;
+ this.queuedLightChecks = 4096;
+ this.field_76653_p = false;
+ this.entityLists = new List[16];
+ this.worldObj = par1World;
+ this.xPosition = par2;
+ this.zPosition = par3;
+ this.heightMap = new int[256];
+
+ for (int var4 = 0; var4 < this.entityLists.length; ++var4) {
+ this.entityLists[var4] = new ArrayList();
+ }
+
+ Arrays.fill(this.precipitationHeightMap, -999);
+ Arrays.fill(this.blockBiomeArray, (byte) -1);
+ }
+
+ public Chunk(World par1World, byte[] par2ArrayOfByte, int par3, int par4) {
+ this(par1World, par3, par4);
+ int var5 = par2ArrayOfByte.length / 256;
+
+ for (int var6 = 0; var6 < 16; ++var6) {
+ for (int var7 = 0; var7 < 16; ++var7) {
+ for (int var8 = 0; var8 < var5; ++var8) {
+ byte var9 = par2ArrayOfByte[var6 << 11 | var7 << 7 | var8];
+
+ if (var9 != 0) {
+ int var10 = var8 >> 4;
+
+ if (this.storageArrays[var10] == null) {
+ this.storageArrays[var10] = new ExtendedBlockStorage(var10 << 4,
+ !par1World.provider.hasNoSky);
+ }
+
+ this.storageArrays[var10].setExtBlockID(var6, var8 & 15, var7, var9);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Checks whether the chunk is at the X/Z location specified
+ */
+ public boolean isAtLocation(int par1, int par2) {
+ return par1 == this.xPosition && par2 == this.zPosition;
+ }
+
+ /**
+ * Returns the value in the height map at this x, z coordinate in the chunk
+ */
+ public int getHeightValue(int par1, int par2) {
+ return this.heightMap[par2 << 4 | par1];
+ }
+
+ /**
+ * Returns the topmost ExtendedBlockStorage instance for this Chunk that
+ * actually contains a block.
+ */
+ public int getTopFilledSegment() {
+ for (int var1 = this.storageArrays.length - 1; var1 >= 0; --var1) {
+ if (this.storageArrays[var1] != null) {
+ return this.storageArrays[var1].getYLocation();
+ }
+ }
+
+ return 0;
+ }
+
+ /**
+ * Returns the ExtendedBlockStorage array for this Chunk.
+ */
+ public ExtendedBlockStorage[] getBlockStorageArray() {
+ return this.storageArrays;
+ }
+
+ /**
+ * Generates the initial skylight map for the chunk upon generation or load.
+ */
+ public void generateSkylightMap() {
+ int var1 = this.getTopFilledSegment();
+ this.heightMapMinimum = Integer.MAX_VALUE;
+ int var2;
+ int var3;
+
+ for (var2 = 0; var2 < 16; ++var2) {
+ var3 = 0;
+
+ while (var3 < 16) {
+ this.precipitationHeightMap[var2 + (var3 << 4)] = -999;
+ int var4 = var1 + 16 - 1;
+
+ while (true) {
+ if (var4 > 0) {
+ if (this.getBlockLightOpacity(var2, var4 - 1, var3) == 0) {
+ --var4;
+ continue;
+ }
+
+ this.heightMap[var3 << 4 | var2] = var4;
+
+ if (var4 < this.heightMapMinimum) {
+ this.heightMapMinimum = var4;
+ }
+ }
+
+ if (!this.worldObj.provider.hasNoSky) {
+ var4 = 15;
+ int var5 = var1 + 16 - 1;
+
+ do {
+ var4 -= this.getBlockLightOpacity(var2, var5, var3);
+
+ if (var4 > 0) {
+ ExtendedBlockStorage var6 = this.storageArrays[var5 >> 4];
+
+ if (var6 != null) {
+ var6.setExtSkylightValue(var2, var5 & 15, var3, var4);
+ this.worldObj.markBlockForRenderUpdate((this.xPosition << 4) + var2, var5,
+ (this.zPosition << 4) + var3);
+ }
+ }
+
+ --var5;
+ } while (var5 > 0 && var4 > 0);
+ }
+
+ ++var3;
+ break;
+ }
+ }
+ }
+
+ this.isModified = true;
+
+ for (var2 = 0; var2 < 16; ++var2) {
+ for (var3 = 0; var3 < 16; ++var3) {
+ this.propagateSkylightOcclusion(var2, var3);
+ }
+ }
+ }
+
+ /**
+ * Propagates a given sky-visible block's light value downward and upward to
+ * neighboring blocks as necessary.
+ */
+ private void propagateSkylightOcclusion(int par1, int par2) {
+ this.updateSkylightColumns[par1 + par2 * 16] = true;
+ this.isGapLightingUpdated = true;
+ }
+
+ /**
+ * Runs delayed skylight updates.
+ */
+ private boolean updateSkylight_do() {
+ if (this.worldObj.doChunksNearChunkExist(this.xPosition * 16 + 8, 0, this.zPosition * 16 + 8, 16)) {
+ for (int var1 = 0; var1 < 16; ++var1) {
+ for (int var2 = 0; var2 < 16; ++var2) {
+ if (this.updateSkylightColumns[var1 + var2 * 16]) {
+ this.updateSkylightColumns[var1 + var2 * 16] = false;
+ int var3 = this.getHeightValue(var1, var2);
+ int var4 = this.xPosition * 16 + var1;
+ int var5 = this.zPosition * 16 + var2;
+ int var6 = this.worldObj.getChunkHeightMapMinimum(var4 - 1, var5);
+ int var7 = this.worldObj.getChunkHeightMapMinimum(var4 + 1, var5);
+ int var8 = this.worldObj.getChunkHeightMapMinimum(var4, var5 - 1);
+ int var9 = this.worldObj.getChunkHeightMapMinimum(var4, var5 + 1);
+
+ if (var7 < var6) {
+ var6 = var7;
+ }
+
+ if (var8 < var6) {
+ var6 = var8;
+ }
+
+ if (var9 < var6) {
+ var6 = var9;
+ }
+
+ this.checkSkylightNeighborHeight(var4, var5, var6);
+ this.checkSkylightNeighborHeight(var4 - 1, var5, var3);
+ this.checkSkylightNeighborHeight(var4 + 1, var5, var3);
+ this.checkSkylightNeighborHeight(var4, var5 - 1, var3);
+ this.checkSkylightNeighborHeight(var4, var5 + 1, var3);
+ }
+ }
+ }
+
+ this.isGapLightingUpdated = false;
+ }
+
+ return !this.isGapLightingUpdated;
+ }
+
+ /**
+ * Checks the height of a block next to a sky-visible block and schedules a
+ * lighting update as necessary.
+ */
+ private void checkSkylightNeighborHeight(int par1, int par2, int par3) {
+ int var4 = this.worldObj.getHeightValue(par1, par2);
+
+ if (var4 > par3) {
+ this.updateSkylightNeighborHeight(par1, par2, par3, var4 + 1);
+ } else if (var4 < par3) {
+ this.updateSkylightNeighborHeight(par1, par2, var4, par3 + 1);
+ }
+ }
+
+ private void updateSkylightNeighborHeight(int par1, int par2, int par3, int par4) {
+ if (par4 > par3 && this.worldObj.doChunksNearChunkExist(par1, 0, par2, 16)) {
+ for (int var5 = par3; var5 < par4; ++var5) {
+ this.worldObj.updateLightByType(EnumSkyBlock.Sky, par1, var5, par2);
+ }
+
+ this.isModified = true;
+ }
+ }
+
+ public static int totalBlockLightUpdates = 0;
+
+ /**
+ * Initiates the recalculation of both the block-light and sky-light for a given
+ * block inside a chunk.
+ */
+ private void relightBlock(int par1, int par2, int par3) {
+ int var4 = this.heightMap[par3 << 4 | par1] & 255;
+ int var5 = var4;
+
+ if (par2 > var4) {
+ var5 = par2;
+ }
+
+ while (var5 > 0 && this.getBlockLightOpacity(par1, var5 - 1, par3) == 0) {
+ --var5;
+ }
+
+ if (var5 != var4) {
+ this.worldObj.markBlocksDirtyVertical(par1 + this.xPosition * 16, par3 + this.zPosition * 16, var5, var4);
+ this.heightMap[par3 << 4 | par1] = var5;
+ int var6 = this.xPosition * 16 + par1;
+ int var7 = this.zPosition * 16 + par3;
+ int var8;
+ int var12;
+
+ if (!this.worldObj.provider.hasNoSky) {
+ ExtendedBlockStorage var9;
+
+ if (var5 < var4) {
+ for (var8 = var5; var8 < var4; ++var8) {
+ var9 = this.storageArrays[var8 >> 4];
+
+ if (var9 != null) {
+ var9.setExtSkylightValue(par1, var8 & 15, par3, 15);
+ this.worldObj.markBlockForRenderUpdate((this.xPosition << 4) + par1, var8,
+ (this.zPosition << 4) + par3);
+ }
+ }
+ } else {
+ for (var8 = var4; var8 < var5; ++var8) {
+ var9 = this.storageArrays[var8 >> 4];
+
+ if (var9 != null) {
+ var9.setExtSkylightValue(par1, var8 & 15, par3, 0);
+ this.worldObj.markBlockForRenderUpdate((this.xPosition << 4) + par1, var8,
+ (this.zPosition << 4) + par3);
+ }
+ }
+ }
+
+ var8 = 15;
+
+ while (var5 > 0 && var8 > 0) {
+ --var5;
+ var12 = this.getBlockLightOpacity(par1, var5, par3);
+
+ if (var12 == 0) {
+ var12 = 1;
+ }
+
+ var8 -= var12;
+
+ if (var8 < 0) {
+ var8 = 0;
+ }
+
+ ExtendedBlockStorage var10 = this.storageArrays[var5 >> 4];
+
+ if (var10 != null) {
+ var10.setExtSkylightValue(par1, var5 & 15, par3, var8);
+ }
+ }
+ }
+
+ var8 = this.heightMap[par3 << 4 | par1];
+ var12 = var4;
+ int var13 = var8;
+
+ if (var8 < var4) {
+ var12 = var8;
+ var13 = var4;
+ }
+
+ if (var8 < this.heightMapMinimum) {
+ this.heightMapMinimum = var8;
+ }
+
+ if (!this.worldObj.provider.hasNoSky) {
+ this.updateSkylightNeighborHeight(var6 - 1, var7, var12, var13);
+ this.updateSkylightNeighborHeight(var6 + 1, var7, var12, var13);
+ this.updateSkylightNeighborHeight(var6, var7 - 1, var12, var13);
+ this.updateSkylightNeighborHeight(var6, var7 + 1, var12, var13);
+ this.updateSkylightNeighborHeight(var6, var7, var12, var13);
+ }
+
+ ++totalBlockLightUpdates;
+
+ this.isModified = true;
+ }
+ }
+
+ public int getBlockLightOpacity(int par1, int par2, int par3) {
+ return Block.lightOpacity[this.getBlockID(par1, par2, par3)];
+ }
+
+ /**
+ * Return the ID of a block in the chunk.
+ */
+ public int getBlockID(int par1, int par2, int par3) {
+ if (par2 >> 4 >= this.storageArrays.length) {
+ return 0;
+ } else {
+ ExtendedBlockStorage var4 = this.storageArrays[par2 >> 4];
+ return var4 != null ? var4.getExtBlockID(par1, par2 & 15, par3) : 0;
+ }
+ }
+
+ /**
+ * Return the metadata corresponding to the given coordinates inside a chunk.
+ */
+ public int getBlockMetadata(int par1, int par2, int par3) {
+ if (par2 >> 4 >= this.storageArrays.length) {
+ return 0;
+ } else {
+ ExtendedBlockStorage var4 = this.storageArrays[par2 >> 4];
+ return var4 != null ? var4.getExtBlockMetadata(par1, par2 & 15, par3) : 0;
+ }
+ }
+
+ /**
+ * Sets a blockID of a position within a chunk with metadata. Args: x, y, z,
+ * blockID, metadata
+ */
+ public boolean setBlockIDWithMetadata(int par1, int par2, int par3, int par4, int par5) {
+ int var6 = par3 << 4 | par1;
+
+ if (par2 >= this.precipitationHeightMap[var6] - 1) {
+ this.precipitationHeightMap[var6] = -999;
+ }
+
+ int var7 = this.heightMap[var6];
+ int var8 = this.getBlockID(par1, par2, par3);
+ int var9 = this.getBlockMetadata(par1, par2, par3);
+
+ if (var8 == par4 && var9 == par5) {
+ return false;
+ } else {
+ ExtendedBlockStorage var10 = this.storageArrays[par2 >> 4];
+ boolean var11 = false;
+
+ if (var10 == null) {
+ if (par4 == 0) {
+ return false;
+ }
+
+ var10 = this.storageArrays[par2 >> 4] = new ExtendedBlockStorage(par2 >> 4 << 4,
+ !this.worldObj.provider.hasNoSky);
+ var11 = par2 >= var7;
+ }
+
+ int var12 = this.xPosition * 16 + par1;
+ int var13 = this.zPosition * 16 + par3;
+
+ if (var8 != 0 && !this.worldObj.isRemote) {
+ Block.blocksList[var8].onSetBlockIDWithMetaData(this.worldObj, var12, par2, var13, var9);
+ }
+
+ var10.setExtBlockID(par1, par2 & 15, par3, par4);
+
+ if (var8 != 0) {
+ if (!this.worldObj.isRemote) {
+ Block.blocksList[var8].breakBlock(this.worldObj, var12, par2, var13, var8, var9);
+ } else if (Block.blocksList[var8] instanceof ITileEntityProvider && var8 != par4) {
+ this.worldObj.removeBlockTileEntity(var12, par2, var13);
+ }
+ }
+
+ if (var10.getExtBlockID(par1, par2 & 15, par3) != par4) {
+ return false;
+ } else {
+ var10.setExtBlockMetadata(par1, par2 & 15, par3, par5);
+
+ if (var11) {
+ this.generateSkylightMap();
+ } else {
+ if (Block.lightOpacity[par4 & 4095] > 0) {
+ if (par2 >= var7) {
+ this.relightBlock(par1, par2 + 1, par3);
+ }
+ } else if (par2 == var7 - 1) {
+ this.relightBlock(par1, par2, par3);
+ }
+
+ this.propagateSkylightOcclusion(par1, par3);
+ }
+
+ TileEntity var14;
+
+ if (par4 != 0) {
+ if (!this.worldObj.isRemote) {
+ Block.blocksList[par4].onBlockAdded(this.worldObj, var12, par2, var13);
+ }
+
+ if (Block.blocksList[par4] instanceof ITileEntityProvider) {
+ var14 = this.getChunkBlockTileEntity(par1, par2, par3);
+
+ if (var14 == null) {
+ var14 = ((ITileEntityProvider) Block.blocksList[par4]).createNewTileEntity(this.worldObj);
+ this.worldObj.setBlockTileEntity(var12, par2, var13, var14);
+ }
+
+ if (var14 != null) {
+ var14.updateContainingBlockInfo();
+ }
+ }
+ } else if (var8 > 0 && Block.blocksList[var8] instanceof ITileEntityProvider) {
+ var14 = this.getChunkBlockTileEntity(par1, par2, par3);
+
+ if (var14 != null) {
+ var14.updateContainingBlockInfo();
+ }
+ }
+
+ this.isModified = true;
+ return true;
+ }
+ }
+ }
+
+ /**
+ * Set the metadata of a block in the chunk
+ */
+ public boolean setBlockMetadata(int par1, int par2, int par3, int par4) {
+ ExtendedBlockStorage var5 = this.storageArrays[par2 >> 4];
+
+ if (var5 == null) {
+ return false;
+ } else {
+ int var6 = var5.getExtBlockMetadata(par1, par2 & 15, par3);
+
+ if (var6 == par4) {
+ return false;
+ } else {
+ this.isModified = true;
+ var5.setExtBlockMetadata(par1, par2 & 15, par3, par4);
+ int var7 = var5.getExtBlockID(par1, par2 & 15, par3);
+
+ if (var7 > 0 && Block.blocksList[var7] instanceof ITileEntityProvider) {
+ TileEntity var8 = this.getChunkBlockTileEntity(par1, par2, par3);
+
+ if (var8 != null) {
+ var8.updateContainingBlockInfo();
+ var8.blockMetadata = par4;
+ }
+ }
+
+ return true;
+ }
+ }
+ }
+
+ /**
+ * Gets the amount of light saved in this block (doesn't adjust for daylight)
+ */
+ public int getSavedLightValue(EnumSkyBlock par1EnumSkyBlock, int par2, int par3, int par4) {
+ ExtendedBlockStorage var5 = this.storageArrays[par3 >> 4];
+ return var5 == null ? (this.canBlockSeeTheSky(par2, par3, par4) ? par1EnumSkyBlock.defaultLightValue : 0)
+ : (par1EnumSkyBlock == EnumSkyBlock.Sky
+ ? (this.worldObj.provider.hasNoSky ? 0 : var5.getExtSkylightValue(par2, par3 & 15, par4))
+ : (par1EnumSkyBlock == EnumSkyBlock.Block ? var5.getExtBlocklightValue(par2, par3 & 15, par4)
+ : par1EnumSkyBlock.defaultLightValue));
+ }
+
+ /**
+ * Sets the light value at the coordinate. If enumskyblock is set to sky it sets
+ * it in the skylightmap and if its a block then into the blocklightmap. Args
+ * enumSkyBlock, x, y, z, lightValue
+ */
+ public void setLightValue(EnumSkyBlock par1EnumSkyBlock, int par2, int par3, int par4, int par5) {
+ ExtendedBlockStorage var6 = this.storageArrays[par3 >> 4];
+
+ if (var6 == null) {
+ var6 = this.storageArrays[par3 >> 4] = new ExtendedBlockStorage(par3 >> 4 << 4,
+ !this.worldObj.provider.hasNoSky);
+ this.generateSkylightMap();
+ }
+
+ this.isModified = true;
+
+ if (par1EnumSkyBlock == EnumSkyBlock.Sky) {
+ if (!this.worldObj.provider.hasNoSky) {
+ var6.setExtSkylightValue(par2, par3 & 15, par4, par5);
+ }
+ } else if (par1EnumSkyBlock == EnumSkyBlock.Block) {
+ var6.setExtBlocklightValue(par2, par3 & 15, par4, par5);
+ }
+ }
+
+ /**
+ * Gets the amount of light on a block taking into account sunlight
+ */
+ public int getBlockLightValue(int par1, int par2, int par3, int par4) {
+ ExtendedBlockStorage var5 = this.storageArrays[par2 >> 4];
+
+ if (var5 == null) {
+ return !this.worldObj.provider.hasNoSky && par4 < EnumSkyBlock.Sky.defaultLightValue
+ ? EnumSkyBlock.Sky.defaultLightValue - par4
+ : 0;
+ } else {
+ int var6 = this.worldObj.provider.hasNoSky ? 0 : var5.getExtSkylightValue(par1, par2 & 15, par3);
+
+ if (var6 > 0) {
+ isLit = true;
+ }
+
+ var6 -= par4;
+ int var7 = var5.getExtBlocklightValue(par1, par2 & 15, par3);
+
+ if (var7 > var6) {
+ var6 = var7;
+ }
+
+ return var6;
+ }
+ }
+
+ /**
+ * Adds an entity to the chunk. Args: entity
+ */
+ public void addEntity(Entity par1Entity) {
+ this.hasEntities = true;
+ int var2 = MathHelper.floor_double(par1Entity.posX / 16.0D);
+ int var3 = MathHelper.floor_double(par1Entity.posZ / 16.0D);
+
+ if (var2 != this.xPosition || var3 != this.zPosition) {
+ this.worldObj.getWorldLogAgent().logSevere("Wrong location! " + par1Entity);
+ //Thread.dumpStack();
+ }
+
+ int var4 = MathHelper.floor_double(par1Entity.posY / 16.0D);
+
+ if (var4 < 0) {
+ var4 = 0;
+ }
+
+ if (var4 >= this.entityLists.length) {
+ var4 = this.entityLists.length - 1;
+ }
+
+ par1Entity.addedToChunk = true;
+ par1Entity.chunkCoordX = this.xPosition;
+ par1Entity.chunkCoordY = var4;
+ par1Entity.chunkCoordZ = this.zPosition;
+ this.entityLists[var4].add(par1Entity);
+ }
+
+ /**
+ * removes entity using its y chunk coordinate as its index
+ */
+ public void removeEntity(Entity par1Entity) {
+ this.removeEntityAtIndex(par1Entity, par1Entity.chunkCoordY);
+ }
+
+ /**
+ * Removes entity at the specified index from the entity array.
+ */
+ public void removeEntityAtIndex(Entity par1Entity, int par2) {
+ if (par2 < 0) {
+ par2 = 0;
+ }
+
+ if (par2 >= this.entityLists.length) {
+ par2 = this.entityLists.length - 1;
+ }
+
+ this.entityLists[par2].remove(par1Entity);
+ }
+
+ /**
+ * Returns whether is not a block above this one blocking sight to the sky (done
+ * via checking against the heightmap)
+ */
+ public boolean canBlockSeeTheSky(int par1, int par2, int par3) {
+ return par2 >= this.heightMap[par3 << 4 | par1];
+ }
+
+ /**
+ * Gets the TileEntity for a given block in this chunk
+ */
+ public TileEntity getChunkBlockTileEntity(int par1, int par2, int par3) {
+ ChunkPosition var4 = new ChunkPosition(par1, par2, par3);
+ TileEntity var5 = (TileEntity) this.chunkTileEntityMap.get(var4);
+
+ if (var5 == null) {
+ int var6 = this.getBlockID(par1, par2, par3);
+
+ if (var6 <= 0 || !Block.blocksList[var6].hasTileEntity()) {
+ return null;
+ }
+
+ if (var5 == null) {
+ var5 = ((ITileEntityProvider) Block.blocksList[var6]).createNewTileEntity(this.worldObj);
+ this.worldObj.setBlockTileEntity(this.xPosition * 16 + par1, par2, this.zPosition * 16 + par3, var5);
+ }
+
+ var5 = (TileEntity) this.chunkTileEntityMap.get(var4);
+ }
+
+ if (var5 != null && var5.isInvalid()) {
+ this.chunkTileEntityMap.remove(var4);
+ return null;
+ } else {
+ return var5;
+ }
+ }
+
+ /**
+ * Adds a TileEntity to a chunk
+ */
+ public void addTileEntity(TileEntity par1TileEntity) {
+ int var2 = par1TileEntity.xCoord - this.xPosition * 16;
+ int var3 = par1TileEntity.yCoord;
+ int var4 = par1TileEntity.zCoord - this.zPosition * 16;
+ this.setChunkBlockTileEntity(var2, var3, var4, par1TileEntity);
+
+ if (this.isChunkLoaded) {
+ this.worldObj.loadedTileEntityList.add(par1TileEntity);
+ }
+ }
+
+ /**
+ * Sets the TileEntity for a given block in this chunk
+ */
+ public void setChunkBlockTileEntity(int par1, int par2, int par3, TileEntity par4TileEntity) {
+ ChunkPosition var5 = new ChunkPosition(par1, par2, par3);
+ par4TileEntity.setWorldObj(this.worldObj);
+ par4TileEntity.xCoord = this.xPosition * 16 + par1;
+ par4TileEntity.yCoord = par2;
+ par4TileEntity.zCoord = this.zPosition * 16 + par3;
+
+ if (this.getBlockID(par1, par2, par3) != 0
+ && Block.blocksList[this.getBlockID(par1, par2, par3)] instanceof ITileEntityProvider) {
+ if (this.chunkTileEntityMap.containsKey(var5)) {
+ ((TileEntity) this.chunkTileEntityMap.get(var5)).invalidate();
+ }
+
+ par4TileEntity.validate();
+ this.chunkTileEntityMap.put(var5, par4TileEntity);
+ }
+ }
+
+ /**
+ * Removes the TileEntity for a given block in this chunk
+ */
+ public void removeChunkBlockTileEntity(int par1, int par2, int par3) {
+ ChunkPosition var4 = new ChunkPosition(par1, par2, par3);
+
+ if (this.isChunkLoaded) {
+ TileEntity var5 = (TileEntity) this.chunkTileEntityMap.remove(var4);
+
+ if (var5 != null) {
+ var5.invalidate();
+ }
+ }
+ }
+
+ /**
+ * Called when this Chunk is loaded by the ChunkProvider
+ */
+ public void onChunkLoad() {
+ this.isChunkLoaded = true;
+ this.worldObj.addTileEntity(this.chunkTileEntityMap.values());
+
+ for (int var1 = 0; var1 < this.entityLists.length; ++var1) {
+ this.worldObj.addLoadedEntities(this.entityLists[var1]);
+ }
+ }
+
+ /**
+ * Called when this Chunk is unloaded by the ChunkProvider
+ */
+ public void onChunkUnload() {
+ this.isChunkLoaded = false;
+ Iterator var1 = this.chunkTileEntityMap.values().iterator();
+
+ while (var1.hasNext()) {
+ TileEntity var2 = (TileEntity) var1.next();
+ this.worldObj.markTileEntityForDespawn(var2);
+ }
+
+ for (int var3 = 0; var3 < this.entityLists.length; ++var3) {
+ this.worldObj.unloadEntities(this.entityLists[var3]);
+ }
+ }
+
+ /**
+ * Sets the isModified flag for this Chunk
+ */
+ public void setChunkModified() {
+ this.isModified = true;
+ }
+
+ /**
+ * Fills the given list of all entities that intersect within the given bounding
+ * box that aren't the passed entity Args: entity, aabb, listToFill
+ */
+ public void getEntitiesWithinAABBForEntity(Entity par1Entity, AxisAlignedBB par2AxisAlignedBB, List par3List,
+ IEntitySelector par4IEntitySelector) {
+ int var5 = MathHelper.floor_double((par2AxisAlignedBB.minY - 2.0D) / 16.0D);
+ int var6 = MathHelper.floor_double((par2AxisAlignedBB.maxY + 2.0D) / 16.0D);
+
+ if (var5 < 0) {
+ var5 = 0;
+ var6 = Math.max(var5, var6);
+ }
+
+ if (var6 >= this.entityLists.length) {
+ var6 = this.entityLists.length - 1;
+ var5 = Math.min(var5, var6);
+ }
+
+ for (int var7 = var5; var7 <= var6; ++var7) {
+ List var8 = this.entityLists[var7];
+
+ for (int var9 = 0; var9 < var8.size(); ++var9) {
+ Entity var10 = (Entity) var8.get(var9);
+
+ if (var10 != par1Entity && var10.boundingBox.intersectsWith(par2AxisAlignedBB)
+ && (par4IEntitySelector == null || par4IEntitySelector.isEntityApplicable(var10))) {
+ par3List.add(var10);
+ Entity[] var11 = var10.getParts();
+
+ if (var11 != null) {
+ for (int var12 = 0; var12 < var11.length; ++var12) {
+ var10 = var11[var12];
+
+ if (var10 != par1Entity && var10.boundingBox.intersectsWith(par2AxisAlignedBB)
+ && (par4IEntitySelector == null || par4IEntitySelector.isEntityApplicable(var10))) {
+ par3List.add(var10);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Gets all entities that can be assigned to the specified class. Args:
+ * entityClass, aabb, listToFill
+ */
+ public void getEntitiesOfTypeWithinAAAB(Class par1Class, AxisAlignedBB par2AxisAlignedBB, List par3List,
+ IEntitySelector par4IEntitySelector) {
+ int var5 = MathHelper.floor_double((par2AxisAlignedBB.minY - 2.0D) / 16.0D);
+ int var6 = MathHelper.floor_double((par2AxisAlignedBB.maxY + 2.0D) / 16.0D);
+
+ if (var5 < 0) {
+ var5 = 0;
+ } else if (var5 >= this.entityLists.length) {
+ var5 = this.entityLists.length - 1;
+ }
+
+ if (var6 >= this.entityLists.length) {
+ var6 = this.entityLists.length - 1;
+ } else if (var6 < 0) {
+ var6 = 0;
+ }
+
+ for (int var7 = var5; var7 <= var6; ++var7) {
+ List var8 = this.entityLists[var7];
+
+ for (int var9 = 0; var9 < var8.size(); ++var9) {
+ Entity var10 = (Entity) var8.get(var9);
+
+ if (par1Class.isAssignableFrom(var10.getClass()) && var10.boundingBox.intersectsWith(par2AxisAlignedBB)
+ && (par4IEntitySelector == null || par4IEntitySelector.isEntityApplicable(var10))) {
+ par3List.add(var10);
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns true if this Chunk needs to be saved
+ */
+ public boolean needsSaving(boolean par1) {
+ if (par1) {
+ if (this.hasEntities && this.worldObj.getTotalWorldTime() != this.lastSaveTime || this.isModified) {
+ return true;
+ }
+ } else if (this.hasEntities && this.worldObj.getTotalWorldTime() >= this.lastSaveTime + 600L) {
+ return true;
+ }
+
+ return this.isModified;
+ }
+
+ public EaglercraftRandom getRandomWithSeed(long par1) {
+ return new EaglercraftRandom(this.worldObj.getSeed() + (long) (this.xPosition * this.xPosition * 4987142)
+ + (long) (this.xPosition * 5947611) + (long) (this.zPosition * this.zPosition) * 4392871L
+ + (long) (this.zPosition * 389711) ^ par1);
+ }
+
+ public boolean isEmpty() {
+ return false;
+ }
+
+ public void populateChunk(IChunkProvider par1IChunkProvider, IChunkProvider par2IChunkProvider, int par3,
+ int par4) {
+ if (!this.isTerrainPopulated && par1IChunkProvider.chunkExists(par3 + 1, par4 + 1)
+ && par1IChunkProvider.chunkExists(par3, par4 + 1) && par1IChunkProvider.chunkExists(par3 + 1, par4)) {
+ par1IChunkProvider.populate(par2IChunkProvider, par3, par4);
+ }
+
+ if (par1IChunkProvider.chunkExists(par3 - 1, par4)
+ && !par1IChunkProvider.provideChunk(par3 - 1, par4).isTerrainPopulated
+ && par1IChunkProvider.chunkExists(par3 - 1, par4 + 1) && par1IChunkProvider.chunkExists(par3, par4 + 1)
+ && par1IChunkProvider.chunkExists(par3 - 1, par4 + 1)) {
+ par1IChunkProvider.populate(par2IChunkProvider, par3 - 1, par4);
+ }
+
+ if (par1IChunkProvider.chunkExists(par3, par4 - 1)
+ && !par1IChunkProvider.provideChunk(par3, par4 - 1).isTerrainPopulated
+ && par1IChunkProvider.chunkExists(par3 + 1, par4 - 1)
+ && par1IChunkProvider.chunkExists(par3 + 1, par4 - 1)
+ && par1IChunkProvider.chunkExists(par3 + 1, par4)) {
+ par1IChunkProvider.populate(par2IChunkProvider, par3, par4 - 1);
+ }
+
+ if (par1IChunkProvider.chunkExists(par3 - 1, par4 - 1)
+ && !par1IChunkProvider.provideChunk(par3 - 1, par4 - 1).isTerrainPopulated
+ && par1IChunkProvider.chunkExists(par3, par4 - 1) && par1IChunkProvider.chunkExists(par3 - 1, par4)) {
+ par1IChunkProvider.populate(par2IChunkProvider, par3 - 1, par4 - 1);
+ }
+ }
+
+ /**
+ * Gets the height to which rain/snow will fall. Calculates it if not already
+ * stored.
+ */
+ public int getPrecipitationHeight(int par1, int par2) {
+ int var3 = par1 | par2 << 4;
+ int var4 = this.precipitationHeightMap[var3];
+
+ if (var4 == -999) {
+ int var5 = this.getTopFilledSegment() + 15;
+ var4 = -1;
+
+ while (var5 > 0 && var4 == -1) {
+ int var6 = this.getBlockID(par1, var5, par2);
+ Material var7 = var6 == 0 ? Material.air : Block.blocksList[var6].blockMaterial;
+
+ if (!var7.blocksMovement() && !var7.isLiquid()) {
+ --var5;
+ } else {
+ var4 = var5 + 1;
+ }
+ }
+
+ this.precipitationHeightMap[var3] = var4;
+ }
+
+ return var4;
+ }
+
+ /**
+ * Checks whether skylight needs updated; if it does, calls updateSkylight_do
+ */
+ public boolean updateSkylight() {
+ if (this.isGapLightingUpdated && !this.worldObj.provider.hasNoSky) {
+ return this.updateSkylight_do();
+ }
+ return false;
+ }
+
+ /**
+ * Gets a ChunkCoordIntPair representing the Chunk's position.
+ */
+ public ChunkCoordIntPair getChunkCoordIntPair() {
+ return new ChunkCoordIntPair(this.xPosition, this.zPosition);
+ }
+
+ /**
+ * Returns whether the ExtendedBlockStorages containing levels (in blocks) from
+ * arg 1 to arg 2 are fully empty (true) or not (false).
+ */
+ public boolean getAreLevelsEmpty(int par1, int par2) {
+ if (par1 < 0) {
+ par1 = 0;
+ }
+
+ if (par2 >= 256) {
+ par2 = 255;
+ }
+
+ for (int var3 = par1; var3 <= par2; var3 += 16) {
+ ExtendedBlockStorage var4 = this.storageArrays[var3 >> 4];
+
+ if (var4 != null && !var4.isEmpty()) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public void setStorageArrays(ExtendedBlockStorage[] par1ArrayOfExtendedBlockStorage) {
+ this.storageArrays = par1ArrayOfExtendedBlockStorage;
+ }
+
+ /**
+ * This method retrieves the biome at a set of coordinates
+ */
+ public BiomeGenBase getBiomeGenForWorldCoords(int par1, int par2, WorldChunkManager par3WorldChunkManager) {
+ int var4 = this.blockBiomeArray[par2 << 4 | par1] & 255;
+
+ if (var4 == 255) {
+ BiomeGenBase var5 = par3WorldChunkManager.getBiomeGenAt((this.xPosition << 4) + par1,
+ (this.zPosition << 4) + par2);
+ var4 = var5.biomeID;
+ this.blockBiomeArray[par2 << 4 | par1] = (byte) (var4 & 255);
+ }
+
+ return BiomeGenBase.biomeList[var4] == null ? BiomeGenBase.plains : BiomeGenBase.biomeList[var4];
+ }
+
+ /**
+ * Returns an array containing a 16x16 mapping on the X/Z of block positions in
+ * this Chunk to biome IDs.
+ */
+ public byte[] getBiomeArray() {
+ return this.blockBiomeArray;
+ }
+
+ /**
+ * Accepts a 256-entry array that contains a 16x16 mapping on the X/Z plane of
+ * block positions in this Chunk to biome IDs.
+ */
+ public void setBiomeArray(byte[] par1ArrayOfByte) {
+ this.blockBiomeArray = par1ArrayOfByte;
+ }
+
+ /**
+ * Resets the relight check index to 0 for this Chunk.
+ */
+ public void resetRelightChecks() {
+ this.queuedLightChecks = 0;
+ }
+
+ /**
+ * Called once-per-chunk-per-tick, and advances the round-robin relight check
+ * index by up to 8 blocks at a time. In a worst-case scenario, can potentially
+ * take up to 25.6 seconds, calculated via (4096/8)/20, to re-check all blocks
+ * in a chunk, which may explain lagging light updates on initial world
+ * generation.
+ */
+ public void enqueueRelightChecks() {
+ for (int var1 = 0; var1 < 8; ++var1) {
+ if (this.queuedLightChecks >= 4096) {
+ return;
+ }
+
+ int var2 = this.queuedLightChecks % 16;
+ int var3 = this.queuedLightChecks / 16 % 16;
+ int var4 = this.queuedLightChecks / 256;
+ ++this.queuedLightChecks;
+ int var5 = (this.xPosition << 4) + var3;
+ int var6 = (this.zPosition << 4) + var4;
+
+ for (int var7 = 0; var7 < 16; ++var7) {
+ int var8 = (var2 << 4) + var7;
+
+ if (this.storageArrays[var2] == null
+ && (var7 == 0 || var7 == 15 || var3 == 0 || var3 == 15 || var4 == 0 || var4 == 15)
+ || this.storageArrays[var2] != null
+ && this.storageArrays[var2].getExtBlockID(var3, var7, var4) == 0) {
+ if (Block.lightValue[this.worldObj.getBlockId(var5, var8 - 1, var6)] > 0) {
+ this.worldObj.updateAllLightTypes(var5, var8 - 1, var6);
+ }
+
+ if (Block.lightValue[this.worldObj.getBlockId(var5, var8 + 1, var6)] > 0) {
+ this.worldObj.updateAllLightTypes(var5, var8 + 1, var6);
+ }
+
+ if (Block.lightValue[this.worldObj.getBlockId(var5 - 1, var8, var6)] > 0) {
+ this.worldObj.updateAllLightTypes(var5 - 1, var8, var6);
+ }
+
+ if (Block.lightValue[this.worldObj.getBlockId(var5 + 1, var8, var6)] > 0) {
+ this.worldObj.updateAllLightTypes(var5 + 1, var8, var6);
+ }
+
+ if (Block.lightValue[this.worldObj.getBlockId(var5, var8, var6 - 1)] > 0) {
+ this.worldObj.updateAllLightTypes(var5, var8, var6 - 1);
+ }
+
+ if (Block.lightValue[this.worldObj.getBlockId(var5, var8, var6 + 1)] > 0) {
+ this.worldObj.updateAllLightTypes(var5, var8, var6 + 1);
+ }
+
+ this.worldObj.updateAllLightTypes(var5, var8, var6);
+ }
+ }
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ChunkCache.java b/sp-server/src/main/java/net/minecraft/src/ChunkCache.java
new file mode 100644
index 0000000..0cfe973
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ChunkCache.java
@@ -0,0 +1,124 @@
+package net.minecraft.src;
+
+public class ChunkCache implements IBlockAccess {
+ private int chunkX;
+ private int chunkZ;
+ private Chunk[][] chunkArray;
+
+ /** set by !chunk.getAreLevelsEmpty */
+ private boolean hasExtendedLevels;
+
+ /** Reference to the World object. */
+ private World worldObj;
+
+ public ChunkCache(World par1World, int par2, int par3, int par4, int par5, int par6, int par7, int par8) {
+ this.worldObj = par1World;
+ this.chunkX = par2 - par8 >> 4;
+ this.chunkZ = par4 - par8 >> 4;
+ int var9 = par5 + par8 >> 4;
+ int var10 = par7 + par8 >> 4;
+ this.chunkArray = new Chunk[var9 - this.chunkX + 1][var10 - this.chunkZ + 1];
+ this.hasExtendedLevels = true;
+ int var11;
+ int var12;
+ Chunk var13;
+
+ for (var11 = this.chunkX; var11 <= var9; ++var11) {
+ for (var12 = this.chunkZ; var12 <= var10; ++var12) {
+ var13 = par1World.getChunkFromChunkCoords(var11, var12);
+
+ if (var13 != null) {
+ this.chunkArray[var11 - this.chunkX][var12 - this.chunkZ] = var13;
+ }
+ }
+ }
+
+ for (var11 = par2 >> 4; var11 <= par5 >> 4; ++var11) {
+ for (var12 = par4 >> 4; var12 <= par7 >> 4; ++var12) {
+ var13 = this.chunkArray[var11 - this.chunkX][var12 - this.chunkZ];
+
+ if (var13 != null && !var13.getAreLevelsEmpty(par3, par6)) {
+ this.hasExtendedLevels = false;
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the block ID at coords x,y,z
+ */
+ public int getBlockId(int par1, int par2, int par3) {
+ if (par2 < 0) {
+ return 0;
+ } else if (par2 >= 256) {
+ return 0;
+ } else {
+ int var4 = (par1 >> 4) - this.chunkX;
+ int var5 = (par3 >> 4) - this.chunkZ;
+
+ if (var4 >= 0 && var4 < this.chunkArray.length && var5 >= 0 && var5 < this.chunkArray[var4].length) {
+ Chunk var6 = this.chunkArray[var4][var5];
+ return var6 == null ? 0 : var6.getBlockID(par1 & 15, par2, par3 & 15);
+ } else {
+ return 0;
+ }
+ }
+ }
+
+ /**
+ * Returns the TileEntity associated with a given block in X,Y,Z coordinates, or
+ * null if no TileEntity exists
+ */
+ public TileEntity getBlockTileEntity(int par1, int par2, int par3) {
+ int var4 = (par1 >> 4) - this.chunkX;
+ int var5 = (par3 >> 4) - this.chunkZ;
+ return this.chunkArray[var4][var5].getChunkBlockTileEntity(par1 & 15, par2, par3 & 15);
+ }
+
+ /**
+ * Returns the block metadata at coords x,y,z
+ */
+ public int getBlockMetadata(int par1, int par2, int par3) {
+ if (par2 < 0) {
+ return 0;
+ } else if (par2 >= 256) {
+ return 0;
+ } else {
+ int var4 = (par1 >> 4) - this.chunkX;
+ int var5 = (par3 >> 4) - this.chunkZ;
+ return this.chunkArray[var4][var5].getBlockMetadata(par1 & 15, par2, par3 & 15);
+ }
+ }
+
+ /**
+ * Returns the block's material.
+ */
+ public Material getBlockMaterial(int par1, int par2, int par3) {
+ int var4 = this.getBlockId(par1, par2, par3);
+ return var4 == 0 ? Material.air : Block.blocksList[var4].blockMaterial;
+ }
+
+ /**
+ * Returns true if the block at the specified coordinates is an opaque cube.
+ * Args: x, y, z
+ */
+ public boolean isBlockNormalCube(int par1, int par2, int par3) {
+ Block var4 = Block.blocksList[this.getBlockId(par1, par2, par3)];
+ return var4 == null ? false : var4.blockMaterial.blocksMovement() && var4.renderAsNormalBlock();
+ }
+
+ /**
+ * Return the Vec3Pool object for this world.
+ */
+ public Vec3Pool getWorldVec3Pool() {
+ return this.worldObj.getWorldVec3Pool();
+ }
+
+ /**
+ * Is this block powering in the specified direction Args: x, y, z, direction
+ */
+ public int isBlockProvidingPowerTo(int par1, int par2, int par3, int par4) {
+ int var5 = this.getBlockId(par1, par2, par3);
+ return var5 == 0 ? 0 : Block.blocksList[var5].isProvidingStrongPower(this, par1, par2, par3, par4);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ChunkCoordIntPair.java b/sp-server/src/main/java/net/minecraft/src/ChunkCoordIntPair.java
new file mode 100644
index 0000000..1efaa0e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ChunkCoordIntPair.java
@@ -0,0 +1,49 @@
+package net.minecraft.src;
+
+public class ChunkCoordIntPair {
+ /** The X position of this Chunk Coordinate Pair */
+ public final int chunkXPos;
+
+ /** The Z position of this Chunk Coordinate Pair */
+ public final int chunkZPos;
+
+ public ChunkCoordIntPair(int par1, int par2) {
+ this.chunkXPos = par1;
+ this.chunkZPos = par2;
+ }
+
+ /**
+ * converts a chunk coordinate pair to an integer (suitable for hashing)
+ */
+ public static long chunkXZ2Int(int par0, int par1) {
+ return (long) par0 & 4294967295L | ((long) par1 & 4294967295L) << 32;
+ }
+
+ public int hashCode() {
+ long var1 = chunkXZ2Int(this.chunkXPos, this.chunkZPos);
+ int var3 = (int) var1;
+ int var4 = (int) (var1 >> 32);
+ return var3 ^ var4;
+ }
+
+ public boolean equals(Object par1Obj) {
+ ChunkCoordIntPair var2 = (ChunkCoordIntPair) par1Obj;
+ return var2.chunkXPos == this.chunkXPos && var2.chunkZPos == this.chunkZPos;
+ }
+
+ public int getCenterXPos() {
+ return (this.chunkXPos << 4) + 8;
+ }
+
+ public int getCenterZPosition() {
+ return (this.chunkZPos << 4) + 8;
+ }
+
+ public ChunkPosition getChunkPosition(int par1) {
+ return new ChunkPosition(this.getCenterXPos(), par1, this.getCenterZPosition());
+ }
+
+ public String toString() {
+ return "[" + this.chunkXPos + ", " + this.chunkZPos + "]";
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ChunkCoordinates.java b/sp-server/src/main/java/net/minecraft/src/ChunkCoordinates.java
new file mode 100644
index 0000000..3eaf8e7
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ChunkCoordinates.java
@@ -0,0 +1,78 @@
+package net.minecraft.src;
+
+public class ChunkCoordinates implements Comparable {
+ public int posX;
+
+ /** the y coordinate */
+ public int posY;
+
+ /** the z coordinate */
+ public int posZ;
+
+ public ChunkCoordinates() {
+ }
+
+ public ChunkCoordinates(int par1, int par2, int par3) {
+ this.posX = par1;
+ this.posY = par2;
+ this.posZ = par3;
+ }
+
+ public ChunkCoordinates(ChunkCoordinates par1ChunkCoordinates) {
+ this.posX = par1ChunkCoordinates.posX;
+ this.posY = par1ChunkCoordinates.posY;
+ this.posZ = par1ChunkCoordinates.posZ;
+ }
+
+ public boolean equals(Object par1Obj) {
+ if (!(par1Obj instanceof ChunkCoordinates)) {
+ return false;
+ } else {
+ ChunkCoordinates var2 = (ChunkCoordinates) par1Obj;
+ return this.posX == var2.posX && this.posY == var2.posY && this.posZ == var2.posZ;
+ }
+ }
+
+ public int hashCode() {
+ return this.posX + this.posZ << 8 + this.posY << 16;
+ }
+
+ /**
+ * Compare the coordinate with another coordinate
+ */
+ public int compareChunkCoordinate(ChunkCoordinates par1ChunkCoordinates) {
+ return this.posY == par1ChunkCoordinates.posY
+ ? (this.posZ == par1ChunkCoordinates.posZ ? this.posX - par1ChunkCoordinates.posX
+ : this.posZ - par1ChunkCoordinates.posZ)
+ : this.posY - par1ChunkCoordinates.posY;
+ }
+
+ public void set(int par1, int par2, int par3) {
+ this.posX = par1;
+ this.posY = par2;
+ this.posZ = par3;
+ }
+
+ /**
+ * Returns the squared distance between this coordinates and the coordinates
+ * given as argument.
+ */
+ public float getDistanceSquared(int par1, int par2, int par3) {
+ int var4 = this.posX - par1;
+ int var5 = this.posY - par2;
+ int var6 = this.posZ - par3;
+ return (float) (var4 * var4 + var5 * var5 + var6 * var6);
+ }
+
+ /**
+ * Return the squared distance between this coordinates and the ChunkCoordinates
+ * given as argument.
+ */
+ public float getDistanceSquaredToChunkCoordinates(ChunkCoordinates par1ChunkCoordinates) {
+ return this.getDistanceSquared(par1ChunkCoordinates.posX, par1ChunkCoordinates.posY, par1ChunkCoordinates.posZ);
+ }
+
+ public int compareTo(Object par1Obj) {
+ return this.compareChunkCoordinate((ChunkCoordinates) par1Obj);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ChunkPosition.java b/sp-server/src/main/java/net/minecraft/src/ChunkPosition.java
new file mode 100644
index 0000000..8ac7d4d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ChunkPosition.java
@@ -0,0 +1,36 @@
+package net.minecraft.src;
+
+public class ChunkPosition {
+ /** The x coordinate of this ChunkPosition */
+ public final int x;
+
+ /** The y coordinate of this ChunkPosition */
+ public final int y;
+
+ /** The z coordinate of this ChunkPosition */
+ public final int z;
+
+ public ChunkPosition(int par1, int par2, int par3) {
+ this.x = par1;
+ this.y = par2;
+ this.z = par3;
+ }
+
+ public ChunkPosition(Vec3 par1Vec3) {
+ this(MathHelper.floor_double(par1Vec3.xCoord), MathHelper.floor_double(par1Vec3.yCoord),
+ MathHelper.floor_double(par1Vec3.zCoord));
+ }
+
+ public boolean equals(Object par1Obj) {
+ if (!(par1Obj instanceof ChunkPosition)) {
+ return false;
+ } else {
+ ChunkPosition var2 = (ChunkPosition) par1Obj;
+ return var2.x == this.x && var2.y == this.y && var2.z == this.z;
+ }
+ }
+
+ public int hashCode() {
+ return this.x * 8976890 + this.y * 981131 + this.z;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ChunkProviderEnd.java b/sp-server/src/main/java/net/minecraft/src/ChunkProviderEnd.java
new file mode 100644
index 0000000..33a544f
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ChunkProviderEnd.java
@@ -0,0 +1,364 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ChunkProviderEnd implements IChunkProvider {
+ private EaglercraftRandom endRNG;
+ private NoiseGeneratorOctaves noiseGen1;
+ private NoiseGeneratorOctaves noiseGen2;
+ private NoiseGeneratorOctaves noiseGen3;
+ public NoiseGeneratorOctaves noiseGen4;
+ public NoiseGeneratorOctaves noiseGen5;
+ private World endWorld;
+ private double[] densities;
+
+ /** The biomes that are used to generate the chunk */
+ private BiomeGenBase[] biomesForGeneration;
+ double[] noiseData1;
+ double[] noiseData2;
+ double[] noiseData3;
+ double[] noiseData4;
+ double[] noiseData5;
+ int[][] field_73203_h = new int[32][32];
+
+ public ChunkProviderEnd(World par1World, long par2) {
+ this.endWorld = par1World;
+ this.endRNG = new EaglercraftRandom(par2);
+ this.noiseGen1 = new NoiseGeneratorOctaves(this.endRNG, 16);
+ this.noiseGen2 = new NoiseGeneratorOctaves(this.endRNG, 16);
+ this.noiseGen3 = new NoiseGeneratorOctaves(this.endRNG, 8);
+ this.noiseGen4 = new NoiseGeneratorOctaves(this.endRNG, 10);
+ this.noiseGen5 = new NoiseGeneratorOctaves(this.endRNG, 16);
+ }
+
+ public void generateTerrain(int par1, int par2, byte[] par3ArrayOfByte, BiomeGenBase[] par4ArrayOfBiomeGenBase) {
+ byte var5 = 2;
+ int var6 = var5 + 1;
+ byte var7 = 33;
+ int var8 = var5 + 1;
+ this.densities = this.initializeNoiseField(this.densities, par1 * var5, 0, par2 * var5, var6, var7, var8);
+
+ for (int var9 = 0; var9 < var5; ++var9) {
+ for (int var10 = 0; var10 < var5; ++var10) {
+ for (int var11 = 0; var11 < 32; ++var11) {
+ double var12 = 0.25D;
+ double var14 = this.densities[((var9 + 0) * var8 + var10 + 0) * var7 + var11 + 0];
+ double var16 = this.densities[((var9 + 0) * var8 + var10 + 1) * var7 + var11 + 0];
+ double var18 = this.densities[((var9 + 1) * var8 + var10 + 0) * var7 + var11 + 0];
+ double var20 = this.densities[((var9 + 1) * var8 + var10 + 1) * var7 + var11 + 0];
+ double var22 = (this.densities[((var9 + 0) * var8 + var10 + 0) * var7 + var11 + 1] - var14) * var12;
+ double var24 = (this.densities[((var9 + 0) * var8 + var10 + 1) * var7 + var11 + 1] - var16) * var12;
+ double var26 = (this.densities[((var9 + 1) * var8 + var10 + 0) * var7 + var11 + 1] - var18) * var12;
+ double var28 = (this.densities[((var9 + 1) * var8 + var10 + 1) * var7 + var11 + 1] - var20) * var12;
+
+ for (int var30 = 0; var30 < 4; ++var30) {
+ double var31 = 0.125D;
+ double var33 = var14;
+ double var35 = var16;
+ double var37 = (var18 - var14) * var31;
+ double var39 = (var20 - var16) * var31;
+
+ for (int var41 = 0; var41 < 8; ++var41) {
+ int var42 = var41 + var9 * 8 << 11 | 0 + var10 * 8 << 7 | var11 * 4 + var30;
+ short var43 = 128;
+ double var44 = 0.125D;
+ double var46 = var33;
+ double var48 = (var35 - var33) * var44;
+
+ for (int var50 = 0; var50 < 8; ++var50) {
+ int var51 = 0;
+
+ if (var46 > 0.0D) {
+ var51 = Block.whiteStone.blockID;
+ }
+
+ par3ArrayOfByte[var42] = (byte) var51;
+ var42 += var43;
+ var46 += var48;
+ }
+
+ var33 += var37;
+ var35 += var39;
+ }
+
+ var14 += var22;
+ var16 += var24;
+ var18 += var26;
+ var20 += var28;
+ }
+ }
+ }
+ }
+ }
+
+ public void replaceBlocksForBiome(int par1, int par2, byte[] par3ArrayOfByte,
+ BiomeGenBase[] par4ArrayOfBiomeGenBase) {
+ for (int var5 = 0; var5 < 16; ++var5) {
+ for (int var6 = 0; var6 < 16; ++var6) {
+ byte var7 = 1;
+ int var8 = -1;
+ byte var9 = (byte) Block.whiteStone.blockID;
+ byte var10 = (byte) Block.whiteStone.blockID;
+
+ for (int var11 = 127; var11 >= 0; --var11) {
+ int var12 = (var6 * 16 + var5) * 128 + var11;
+ byte var13 = par3ArrayOfByte[var12];
+
+ if (var13 == 0) {
+ var8 = -1;
+ } else if (var13 == Block.stone.blockID) {
+ if (var8 == -1) {
+ if (var7 <= 0) {
+ var9 = 0;
+ var10 = (byte) Block.whiteStone.blockID;
+ }
+
+ var8 = var7;
+
+ if (var11 >= 0) {
+ par3ArrayOfByte[var12] = var9;
+ } else {
+ par3ArrayOfByte[var12] = var10;
+ }
+ } else if (var8 > 0) {
+ --var8;
+ par3ArrayOfByte[var12] = var10;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * loads or generates the chunk at the chunk location specified
+ */
+ public Chunk loadChunk(int par1, int par2) {
+ return this.provideChunk(par1, par2);
+ }
+
+ /**
+ * Will return back a chunk, if it doesn't exist and its not a MP client it will
+ * generates all the blocks for the specified chunk from the map seed and chunk
+ * seed
+ */
+ public Chunk provideChunk(int par1, int par2) {
+ this.endRNG.setSeed((long) par1 * 341873128712L + (long) par2 * 132897987541L);
+ byte[] var3 = new byte[32768];
+ this.biomesForGeneration = this.endWorld.getWorldChunkManager().loadBlockGeneratorData(this.biomesForGeneration,
+ par1 * 16, par2 * 16, 16, 16);
+ this.generateTerrain(par1, par2, var3, this.biomesForGeneration);
+ this.replaceBlocksForBiome(par1, par2, var3, this.biomesForGeneration);
+ Chunk var4 = new Chunk(this.endWorld, var3, par1, par2);
+ byte[] var5 = var4.getBiomeArray();
+
+ for (int var6 = 0; var6 < var5.length; ++var6) {
+ var5[var6] = (byte) this.biomesForGeneration[var6].biomeID;
+ }
+
+ var4.generateSkylightMap();
+ return var4;
+ }
+
+ /**
+ * generates a subset of the level's terrain data. Takes 7 arguments: the
+ * [empty] noise array, the position, and the size.
+ */
+ private double[] initializeNoiseField(double[] par1ArrayOfDouble, int par2, int par3, int par4, int par5, int par6,
+ int par7) {
+ if (par1ArrayOfDouble == null) {
+ par1ArrayOfDouble = new double[par5 * par6 * par7];
+ }
+
+ double var8 = 684.412D;
+ double var10 = 684.412D;
+ this.noiseData4 = this.noiseGen4.generateNoiseOctaves(this.noiseData4, par2, par4, par5, par7, 1.121D, 1.121D,
+ 0.5D);
+ this.noiseData5 = this.noiseGen5.generateNoiseOctaves(this.noiseData5, par2, par4, par5, par7, 200.0D, 200.0D,
+ 0.5D);
+ var8 *= 2.0D;
+ this.noiseData1 = this.noiseGen3.generateNoiseOctaves(this.noiseData1, par2, par3, par4, par5, par6, par7,
+ var8 / 80.0D, var10 / 160.0D, var8 / 80.0D);
+ this.noiseData2 = this.noiseGen1.generateNoiseOctaves(this.noiseData2, par2, par3, par4, par5, par6, par7, var8,
+ var10, var8);
+ this.noiseData3 = this.noiseGen2.generateNoiseOctaves(this.noiseData3, par2, par3, par4, par5, par6, par7, var8,
+ var10, var8);
+ int var12 = 0;
+ int var13 = 0;
+
+ for (int var14 = 0; var14 < par5; ++var14) {
+ for (int var15 = 0; var15 < par7; ++var15) {
+ double var16 = (this.noiseData4[var13] + 256.0D) / 512.0D;
+
+ if (var16 > 1.0D) {
+ var16 = 1.0D;
+ }
+
+ double var18 = this.noiseData5[var13] / 8000.0D;
+
+ if (var18 < 0.0D) {
+ var18 = -var18 * 0.3D;
+ }
+
+ var18 = var18 * 3.0D - 2.0D;
+ float var20 = (float) (var14 + par2 - 0) / 1.0F;
+ float var21 = (float) (var15 + par4 - 0) / 1.0F;
+ float var22 = 100.0F - MathHelper.sqrt_float(var20 * var20 + var21 * var21) * 8.0F;
+
+ if (var22 > 80.0F) {
+ var22 = 80.0F;
+ }
+
+ if (var22 < -100.0F) {
+ var22 = -100.0F;
+ }
+
+ if (var18 > 1.0D) {
+ var18 = 1.0D;
+ }
+
+ var18 /= 8.0D;
+ var18 = 0.0D;
+
+ if (var16 < 0.0D) {
+ var16 = 0.0D;
+ }
+
+ var16 += 0.5D;
+ var18 = var18 * (double) par6 / 16.0D;
+ ++var13;
+ double var23 = (double) par6 / 2.0D;
+
+ for (int var25 = 0; var25 < par6; ++var25) {
+ double var26 = 0.0D;
+ double var28 = ((double) var25 - var23) * 8.0D / var16;
+
+ if (var28 < 0.0D) {
+ var28 *= -1.0D;
+ }
+
+ double var30 = this.noiseData2[var12] / 512.0D;
+ double var32 = this.noiseData3[var12] / 512.0D;
+ double var34 = (this.noiseData1[var12] / 10.0D + 1.0D) / 2.0D;
+
+ if (var34 < 0.0D) {
+ var26 = var30;
+ } else if (var34 > 1.0D) {
+ var26 = var32;
+ } else {
+ var26 = var30 + (var32 - var30) * var34;
+ }
+
+ var26 -= 8.0D;
+ var26 += (double) var22;
+ byte var36 = 2;
+ double var37;
+
+ if (var25 > par6 / 2 - var36) {
+ var37 = (double) ((float) (var25 - (par6 / 2 - var36)) / 64.0F);
+
+ if (var37 < 0.0D) {
+ var37 = 0.0D;
+ }
+
+ if (var37 > 1.0D) {
+ var37 = 1.0D;
+ }
+
+ var26 = var26 * (1.0D - var37) + -3000.0D * var37;
+ }
+
+ var36 = 8;
+
+ if (var25 < var36) {
+ var37 = (double) ((float) (var36 - var25) / ((float) var36 - 1.0F));
+ var26 = var26 * (1.0D - var37) + -30.0D * var37;
+ }
+
+ par1ArrayOfDouble[var12] = var26;
+ ++var12;
+ }
+ }
+ }
+
+ return par1ArrayOfDouble;
+ }
+
+ /**
+ * Checks to see if a chunk exists at x, y
+ */
+ public boolean chunkExists(int par1, int par2) {
+ return true;
+ }
+
+ /**
+ * Populates chunk with ores etc etc
+ */
+ public void populate(IChunkProvider par1IChunkProvider, int par2, int par3) {
+ BlockSand.fallInstantly = true;
+ int var4 = par2 * 16;
+ int var5 = par3 * 16;
+ BiomeGenBase var6 = this.endWorld.getBiomeGenForCoords(var4 + 16, var5 + 16);
+ var6.decorate(this.endWorld, this.endWorld.rand, var4, var5);
+ BlockSand.fallInstantly = false;
+ }
+
+ /**
+ * Two modes of operation: if passed true, save all Chunks in one go. If passed
+ * false, save up to two chunks. Return true if all chunks have been saved.
+ */
+ public boolean saveChunks(boolean par1, IProgressUpdate par2IProgressUpdate) {
+ return true;
+ }
+
+ public void func_104112_b() {
+ }
+
+ /**
+ * Unloads chunks that are marked to be unloaded. This is not guaranteed to
+ * unload every such chunk.
+ */
+ public boolean unloadQueuedChunks() {
+ return false;
+ }
+
+ /**
+ * Returns if the IChunkProvider supports saving.
+ */
+ public boolean canSave() {
+ return true;
+ }
+
+ /**
+ * Converts the instance data to a readable string.
+ */
+ public String makeString() {
+ return "RandomLevelSource";
+ }
+
+ /**
+ * Returns a list of creatures of the specified type that can spawn at the given
+ * location.
+ */
+ public List getPossibleCreatures(EnumCreatureType par1EnumCreatureType, int par2, int par3, int par4) {
+ BiomeGenBase var5 = this.endWorld.getBiomeGenForCoords(par2, par4);
+ return var5 == null ? null : var5.getSpawnableList(par1EnumCreatureType);
+ }
+
+ /**
+ * Returns the location of the closest structure of the specified type. If not
+ * found returns null.
+ */
+ public ChunkPosition findClosestStructure(World par1World, String par2Str, int par3, int par4, int par5) {
+ return null;
+ }
+
+ public int getLoadedChunkCount() {
+ return 0;
+ }
+
+ public void recreateStructures(int par1, int par2) {
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ChunkProviderFlat.java b/sp-server/src/main/java/net/minecraft/src/ChunkProviderFlat.java
new file mode 100644
index 0000000..9bd6a40
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ChunkProviderFlat.java
@@ -0,0 +1,267 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ChunkProviderFlat implements IChunkProvider {
+ private World worldObj;
+ private EaglercraftRandom random;
+ private final byte[] field_82700_c = new byte[256];
+ private final byte[] field_82698_d = new byte[256];
+ private final FlatGeneratorInfo field_82699_e;
+ private final List structureGenerators = new ArrayList();
+ private final boolean field_82697_g;
+ private final boolean field_82702_h;
+ private WorldGenLakes waterLakeGenerator;
+ private WorldGenLakes lavaLakeGenerator;
+
+ public ChunkProviderFlat(World par1World, long par2, boolean par4, String par5Str) {
+ this.worldObj = par1World;
+ this.random = new EaglercraftRandom(par2);
+ this.field_82699_e = FlatGeneratorInfo.createFlatGeneratorFromString(par5Str);
+
+ if (par4) {
+ Map var6 = this.field_82699_e.getWorldFeatures();
+
+ if (var6.containsKey("village")) {
+ Map var7 = (Map) var6.get("village");
+
+ if (!var7.containsKey("size")) {
+ var7.put("size", "1");
+ }
+
+ this.structureGenerators.add(new MapGenVillage(var7));
+ }
+
+ if (var6.containsKey("biome_1")) {
+ this.structureGenerators.add(new MapGenScatteredFeature((Map) var6.get("biome_1")));
+ }
+
+ if (var6.containsKey("mineshaft")) {
+ this.structureGenerators.add(new MapGenMineshaft((Map) var6.get("mineshaft")));
+ }
+
+ if (var6.containsKey("stronghold")) {
+ this.structureGenerators.add(new MapGenStronghold((Map) var6.get("stronghold")));
+ }
+ }
+
+ this.field_82697_g = this.field_82699_e.getWorldFeatures().containsKey("decoration");
+
+ if (this.field_82699_e.getWorldFeatures().containsKey("lake")) {
+ this.waterLakeGenerator = new WorldGenLakes(Block.waterStill.blockID);
+ }
+
+ if (this.field_82699_e.getWorldFeatures().containsKey("lava_lake")) {
+ this.lavaLakeGenerator = new WorldGenLakes(Block.lavaStill.blockID);
+ }
+
+ this.field_82702_h = this.field_82699_e.getWorldFeatures().containsKey("dungeon");
+ Iterator var9 = this.field_82699_e.getFlatLayers().iterator();
+
+ while (var9.hasNext()) {
+ FlatLayerInfo var10 = (FlatLayerInfo) var9.next();
+
+ for (int var8 = var10.getMinY(); var8 < var10.getMinY() + var10.getLayerCount(); ++var8) {
+ this.field_82700_c[var8] = (byte) (var10.getFillBlock() & 255);
+ this.field_82698_d[var8] = (byte) var10.getFillBlockMeta();
+ }
+ }
+ }
+
+ /**
+ * loads or generates the chunk at the chunk location specified
+ */
+ public Chunk loadChunk(int par1, int par2) {
+ return this.provideChunk(par1, par2);
+ }
+
+ /**
+ * Will return back a chunk, if it doesn't exist and its not a MP client it will
+ * generates all the blocks for the specified chunk from the map seed and chunk
+ * seed
+ */
+ public Chunk provideChunk(int par1, int par2) {
+ Chunk var3 = new Chunk(this.worldObj, par1, par2);
+
+ for (int var4 = 0; var4 < this.field_82700_c.length; ++var4) {
+ int var5 = var4 >> 4;
+ ExtendedBlockStorage var6 = var3.getBlockStorageArray()[var5];
+
+ if (var6 == null) {
+ var6 = new ExtendedBlockStorage(var4, !this.worldObj.provider.hasNoSky);
+ var3.getBlockStorageArray()[var5] = var6;
+ }
+
+ for (int var7 = 0; var7 < 16; ++var7) {
+ for (int var8 = 0; var8 < 16; ++var8) {
+ var6.setExtBlockID(var7, var4 & 15, var8, this.field_82700_c[var4] & 255);
+ var6.setExtBlockMetadata(var7, var4 & 15, var8, this.field_82698_d[var4]);
+ }
+ }
+ }
+
+ var3.generateSkylightMap();
+ BiomeGenBase[] var9 = this.worldObj.getWorldChunkManager().loadBlockGeneratorData((BiomeGenBase[]) null,
+ par1 * 16, par2 * 16, 16, 16);
+ byte[] var10 = var3.getBiomeArray();
+
+ for (int var11 = 0; var11 < var10.length; ++var11) {
+ var10[var11] = (byte) var9[var11].biomeID;
+ }
+
+ Iterator var12 = this.structureGenerators.iterator();
+
+ while (var12.hasNext()) {
+ MapGenStructure var13 = (MapGenStructure) var12.next();
+ var13.generate(this, this.worldObj, par1, par2, (byte[]) null);
+ }
+
+ var3.generateSkylightMap();
+ return var3;
+ }
+
+ /**
+ * Checks to see if a chunk exists at x, y
+ */
+ public boolean chunkExists(int par1, int par2) {
+ return true;
+ }
+
+ /**
+ * Populates chunk with ores etc etc
+ */
+ public void populate(IChunkProvider par1IChunkProvider, int par2, int par3) {
+ int var4 = par2 * 16;
+ int var5 = par3 * 16;
+ BiomeGenBase var6 = this.worldObj.getBiomeGenForCoords(var4 + 16, var5 + 16);
+ boolean var7 = false;
+ this.random.setSeed(this.worldObj.getSeed());
+ long var8 = this.random.nextLong() / 2L * 2L + 1L;
+ long var10 = this.random.nextLong() / 2L * 2L + 1L;
+ this.random.setSeed((long) par2 * var8 + (long) par3 * var10 ^ this.worldObj.getSeed());
+ Iterator var12 = this.structureGenerators.iterator();
+
+ while (var12.hasNext()) {
+ MapGenStructure var13 = (MapGenStructure) var12.next();
+ boolean var14 = var13.generateStructuresInChunk(this.worldObj, this.random, par2, par3);
+
+ if (var13 instanceof MapGenVillage) {
+ var7 |= var14;
+ }
+ }
+
+ int var16;
+ int var17;
+ int var18;
+
+ if (this.waterLakeGenerator != null && !var7 && this.random.nextInt(4) == 0) {
+ var16 = var4 + this.random.nextInt(16) + 8;
+ var17 = this.random.nextInt(128);
+ var18 = var5 + this.random.nextInt(16) + 8;
+ this.waterLakeGenerator.generate(this.worldObj, this.random, var16, var17, var18);
+ }
+
+ if (this.lavaLakeGenerator != null && !var7 && this.random.nextInt(8) == 0) {
+ var16 = var4 + this.random.nextInt(16) + 8;
+ var17 = this.random.nextInt(this.random.nextInt(120) + 8);
+ var18 = var5 + this.random.nextInt(16) + 8;
+
+ if (var17 < 63 || this.random.nextInt(10) == 0) {
+ this.lavaLakeGenerator.generate(this.worldObj, this.random, var16, var17, var18);
+ }
+ }
+
+ if (this.field_82702_h) {
+ for (var16 = 0; var16 < 8; ++var16) {
+ var17 = var4 + this.random.nextInt(16) + 8;
+ var18 = this.random.nextInt(128);
+ int var15 = var5 + this.random.nextInt(16) + 8;
+ (new WorldGenDungeons()).generate(this.worldObj, this.random, var17, var18, var15);
+ }
+ }
+
+ if (this.field_82697_g) {
+ var6.decorate(this.worldObj, this.random, var4, var5);
+ }
+ }
+
+ /**
+ * Two modes of operation: if passed true, save all Chunks in one go. If passed
+ * false, save up to two chunks. Return true if all chunks have been saved.
+ */
+ public boolean saveChunks(boolean par1, IProgressUpdate par2IProgressUpdate) {
+ return true;
+ }
+
+ public void func_104112_b() {
+ }
+
+ /**
+ * Unloads chunks that are marked to be unloaded. This is not guaranteed to
+ * unload every such chunk.
+ */
+ public boolean unloadQueuedChunks() {
+ return false;
+ }
+
+ /**
+ * Returns if the IChunkProvider supports saving.
+ */
+ public boolean canSave() {
+ return true;
+ }
+
+ /**
+ * Converts the instance data to a readable string.
+ */
+ public String makeString() {
+ return "FlatLevelSource";
+ }
+
+ /**
+ * Returns a list of creatures of the specified type that can spawn at the given
+ * location.
+ */
+ public List getPossibleCreatures(EnumCreatureType par1EnumCreatureType, int par2, int par3, int par4) {
+ BiomeGenBase var5 = this.worldObj.getBiomeGenForCoords(par2, par4);
+ return var5 == null ? null : var5.getSpawnableList(par1EnumCreatureType);
+ }
+
+ /**
+ * Returns the location of the closest structure of the specified type. If not
+ * found returns null.
+ */
+ public ChunkPosition findClosestStructure(World par1World, String par2Str, int par3, int par4, int par5) {
+ if ("Stronghold".equals(par2Str)) {
+ Iterator var6 = this.structureGenerators.iterator();
+
+ while (var6.hasNext()) {
+ MapGenStructure var7 = (MapGenStructure) var6.next();
+
+ if (var7 instanceof MapGenStronghold) {
+ return var7.getNearestInstance(par1World, par3, par4, par5);
+ }
+ }
+ }
+
+ return null;
+ }
+
+ public int getLoadedChunkCount() {
+ return 0;
+ }
+
+ public void recreateStructures(int par1, int par2) {
+ Iterator var3 = this.structureGenerators.iterator();
+
+ while (var3.hasNext()) {
+ MapGenStructure var4 = (MapGenStructure) var3.next();
+ var4.generate(this, this.worldObj, par1, par2, (byte[]) null);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ChunkProviderGenerate.java b/sp-server/src/main/java/net/minecraft/src/ChunkProviderGenerate.java
new file mode 100644
index 0000000..afb480e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ChunkProviderGenerate.java
@@ -0,0 +1,553 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ChunkProviderGenerate implements IChunkProvider {
+ /** RNG. */
+ private EaglercraftRandom rand;
+
+ /** A NoiseGeneratorOctaves used in generating terrain */
+ private NoiseGeneratorOctaves noiseGen1;
+
+ /** A NoiseGeneratorOctaves used in generating terrain */
+ private NoiseGeneratorOctaves noiseGen2;
+
+ /** A NoiseGeneratorOctaves used in generating terrain */
+ private NoiseGeneratorOctaves noiseGen3;
+
+ /** A NoiseGeneratorOctaves used in generating terrain */
+ private NoiseGeneratorOctaves noiseGen4;
+
+ /** A NoiseGeneratorOctaves used in generating terrain */
+ public NoiseGeneratorOctaves noiseGen5;
+
+ /** A NoiseGeneratorOctaves used in generating terrain */
+ public NoiseGeneratorOctaves noiseGen6;
+ public NoiseGeneratorOctaves mobSpawnerNoise;
+
+ /** Reference to the World object. */
+ private World worldObj;
+
+ /** are map structures going to be generated (e.g. strongholds) */
+ private final boolean mapFeaturesEnabled;
+
+ /** Holds the overall noise array used in chunk generation */
+ private double[] noiseArray;
+ private double[] stoneNoise = new double[256];
+ private MapGenBase caveGenerator = new MapGenCaves();
+
+ /** Holds Stronghold Generator */
+ private MapGenStronghold strongholdGenerator = new MapGenStronghold();
+
+ /** Holds Village Generator */
+ private MapGenVillage villageGenerator = new MapGenVillage();
+
+ /** Holds Mineshaft Generator */
+ private MapGenMineshaft mineshaftGenerator = new MapGenMineshaft();
+ private MapGenScatteredFeature scatteredFeatureGenerator = new MapGenScatteredFeature();
+
+ /** Holds ravine generator */
+ private MapGenBase ravineGenerator = new MapGenRavine();
+
+ /** The biomes that are used to generate the chunk */
+ private BiomeGenBase[] biomesForGeneration;
+
+ /** A double array that hold terrain noise from noiseGen3 */
+ double[] noise3;
+
+ /** A double array that hold terrain noise */
+ double[] noise1;
+
+ /** A double array that hold terrain noise from noiseGen2 */
+ double[] noise2;
+
+ /** A double array that hold terrain noise from noiseGen5 */
+ double[] noise5;
+
+ /** A double array that holds terrain noise from noiseGen6 */
+ double[] noise6;
+
+ /**
+ * Used to store the 5x5 parabolic field that is used during terrain generation.
+ */
+ float[] parabolicField;
+ int[][] field_73219_j = new int[32][32];
+
+ public ChunkProviderGenerate(World par1World, long par2, boolean par4) {
+ this.worldObj = par1World;
+ this.mapFeaturesEnabled = par4;
+ this.rand = new EaglercraftRandom(par2);
+ this.noiseGen1 = new NoiseGeneratorOctaves(this.rand, 16);
+ this.noiseGen2 = new NoiseGeneratorOctaves(this.rand, 16);
+ this.noiseGen3 = new NoiseGeneratorOctaves(this.rand, 8);
+ this.noiseGen4 = new NoiseGeneratorOctaves(this.rand, 4);
+ this.noiseGen5 = new NoiseGeneratorOctaves(this.rand, 10);
+ this.noiseGen6 = new NoiseGeneratorOctaves(this.rand, 16);
+ this.mobSpawnerNoise = new NoiseGeneratorOctaves(this.rand, 8);
+ }
+
+ /**
+ * Generates the shape of the terrain for the chunk though its all stone though
+ * the water is frozen if the temperature is low enough
+ */
+ public void generateTerrain(int par1, int par2, byte[] par3ArrayOfByte) {
+ byte var4 = 4;
+ byte var5 = 16;
+ byte var6 = 63;
+ int var7 = var4 + 1;
+ byte var8 = 17;
+ int var9 = var4 + 1;
+ this.biomesForGeneration = this.worldObj.getWorldChunkManager().getBiomesForGeneration(this.biomesForGeneration,
+ par1 * 4 - 2, par2 * 4 - 2, var7 + 5, var9 + 5);
+ this.noiseArray = this.initializeNoiseField(this.noiseArray, par1 * var4, 0, par2 * var4, var7, var8, var9);
+
+ for (int var10 = 0; var10 < var4; ++var10) {
+ for (int var11 = 0; var11 < var4; ++var11) {
+ for (int var12 = 0; var12 < var5; ++var12) {
+ double var13 = 0.125D;
+ double var15 = this.noiseArray[((var10 + 0) * var9 + var11 + 0) * var8 + var12 + 0];
+ double var17 = this.noiseArray[((var10 + 0) * var9 + var11 + 1) * var8 + var12 + 0];
+ double var19 = this.noiseArray[((var10 + 1) * var9 + var11 + 0) * var8 + var12 + 0];
+ double var21 = this.noiseArray[((var10 + 1) * var9 + var11 + 1) * var8 + var12 + 0];
+ double var23 = (this.noiseArray[((var10 + 0) * var9 + var11 + 0) * var8 + var12 + 1] - var15)
+ * var13;
+ double var25 = (this.noiseArray[((var10 + 0) * var9 + var11 + 1) * var8 + var12 + 1] - var17)
+ * var13;
+ double var27 = (this.noiseArray[((var10 + 1) * var9 + var11 + 0) * var8 + var12 + 1] - var19)
+ * var13;
+ double var29 = (this.noiseArray[((var10 + 1) * var9 + var11 + 1) * var8 + var12 + 1] - var21)
+ * var13;
+
+ for (int var31 = 0; var31 < 8; ++var31) {
+ double var32 = 0.25D;
+ double var34 = var15;
+ double var36 = var17;
+ double var38 = (var19 - var15) * var32;
+ double var40 = (var21 - var17) * var32;
+
+ for (int var42 = 0; var42 < 4; ++var42) {
+ int var43 = var42 + var10 * 4 << 11 | 0 + var11 * 4 << 7 | var12 * 8 + var31;
+ short var44 = 128;
+ var43 -= var44;
+ double var45 = 0.25D;
+ double var49 = (var36 - var34) * var45;
+ double var47 = var34 - var49;
+
+ for (int var51 = 0; var51 < 4; ++var51) {
+ if ((var47 += var49) > 0.0D) {
+ par3ArrayOfByte[var43 += var44] = (byte) Block.stone.blockID;
+ } else if (var12 * 8 + var31 < var6) {
+ par3ArrayOfByte[var43 += var44] = (byte) Block.waterStill.blockID;
+ } else {
+ par3ArrayOfByte[var43 += var44] = 0;
+ }
+ }
+
+ var34 += var38;
+ var36 += var40;
+ }
+
+ var15 += var23;
+ var17 += var25;
+ var19 += var27;
+ var21 += var29;
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Replaces the stone that was placed in with blocks that match the biome
+ */
+ public void replaceBlocksForBiome(int par1, int par2, byte[] par3ArrayOfByte,
+ BiomeGenBase[] par4ArrayOfBiomeGenBase) {
+ byte var5 = 63;
+ double var6 = 0.03125D;
+ this.stoneNoise = this.noiseGen4.generateNoiseOctaves(this.stoneNoise, par1 * 16, par2 * 16, 0, 16, 16, 1,
+ var6 * 2.0D, var6 * 2.0D, var6 * 2.0D);
+
+ for (int var8 = 0; var8 < 16; ++var8) {
+ for (int var9 = 0; var9 < 16; ++var9) {
+ BiomeGenBase var10 = par4ArrayOfBiomeGenBase[var9 + var8 * 16];
+ float var11 = var10.getFloatTemperature();
+ int var12 = (int) (this.stoneNoise[var8 + var9 * 16] / 3.0D + 3.0D + this.rand.nextDouble() * 0.25D);
+ int var13 = -1;
+ byte var14 = var10.topBlock;
+ byte var15 = var10.fillerBlock;
+
+ for (int var16 = 127; var16 >= 0; --var16) {
+ int var17 = (var9 * 16 + var8) * 128 + var16;
+
+ if (var16 <= 0 + this.rand.nextInt(5)) {
+ par3ArrayOfByte[var17] = (byte) Block.bedrock.blockID;
+ } else {
+ byte var18 = par3ArrayOfByte[var17];
+
+ if (var18 == 0) {
+ var13 = -1;
+ } else if (var18 == Block.stone.blockID) {
+ if (var13 == -1) {
+ if (var12 <= 0) {
+ var14 = 0;
+ var15 = (byte) Block.stone.blockID;
+ } else if (var16 >= var5 - 4 && var16 <= var5 + 1) {
+ var14 = var10.topBlock;
+ var15 = var10.fillerBlock;
+ }
+
+ if (var16 < var5 && var14 == 0) {
+ if (var11 < 0.15F) {
+ var14 = (byte) Block.ice.blockID;
+ } else {
+ var14 = (byte) Block.waterStill.blockID;
+ }
+ }
+
+ var13 = var12;
+
+ if (var16 >= var5 - 1) {
+ par3ArrayOfByte[var17] = var14;
+ } else {
+ par3ArrayOfByte[var17] = var15;
+ }
+ } else if (var13 > 0) {
+ --var13;
+ par3ArrayOfByte[var17] = var15;
+
+ if (var13 == 0 && var15 == Block.sand.blockID) {
+ var13 = this.rand.nextInt(4);
+ var15 = (byte) Block.sandStone.blockID;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * loads or generates the chunk at the chunk location specified
+ */
+ public Chunk loadChunk(int par1, int par2) {
+ return this.provideChunk(par1, par2);
+ }
+
+ /**
+ * Will return back a chunk, if it doesn't exist and its not a MP client it will
+ * generates all the blocks for the specified chunk from the map seed and chunk
+ * seed
+ */
+ public Chunk provideChunk(int par1, int par2) {
+ this.rand.setSeed((long) par1 * 341873128712L + (long) par2 * 132897987541L);
+ byte[] var3 = new byte[32768];
+ this.generateTerrain(par1, par2, var3);
+ this.biomesForGeneration = this.worldObj.getWorldChunkManager().loadBlockGeneratorData(this.biomesForGeneration,
+ par1 * 16, par2 * 16, 16, 16);
+ this.replaceBlocksForBiome(par1, par2, var3, this.biomesForGeneration);
+ this.caveGenerator.generate(this, this.worldObj, par1, par2, var3);
+ this.ravineGenerator.generate(this, this.worldObj, par1, par2, var3);
+
+ if (this.mapFeaturesEnabled) {
+ this.mineshaftGenerator.generate(this, this.worldObj, par1, par2, var3);
+ this.villageGenerator.generate(this, this.worldObj, par1, par2, var3);
+ this.strongholdGenerator.generate(this, this.worldObj, par1, par2, var3);
+ this.scatteredFeatureGenerator.generate(this, this.worldObj, par1, par2, var3);
+ }
+
+ Chunk var4 = new Chunk(this.worldObj, var3, par1, par2);
+ byte[] var5 = var4.getBiomeArray();
+
+ for (int var6 = 0; var6 < var5.length; ++var6) {
+ var5[var6] = (byte) this.biomesForGeneration[var6].biomeID;
+ }
+
+ var4.generateSkylightMap();
+ return var4;
+ }
+
+ /**
+ * generates a subset of the level's terrain data. Takes 7 arguments: the
+ * [empty] noise array, the position, and the size.
+ */
+ private double[] initializeNoiseField(double[] par1ArrayOfDouble, int par2, int par3, int par4, int par5, int par6,
+ int par7) {
+ if (par1ArrayOfDouble == null) {
+ par1ArrayOfDouble = new double[par5 * par6 * par7];
+ }
+
+ if (this.parabolicField == null) {
+ this.parabolicField = new float[25];
+
+ for (int var8 = -2; var8 <= 2; ++var8) {
+ for (int var9 = -2; var9 <= 2; ++var9) {
+ float var10 = 10.0F / MathHelper.sqrt_float((float) (var8 * var8 + var9 * var9) + 0.2F);
+ this.parabolicField[var8 + 2 + (var9 + 2) * 5] = var10;
+ }
+ }
+ }
+
+ double var44 = 684.412D;
+ double var45 = 684.412D;
+ this.noise5 = this.noiseGen5.generateNoiseOctaves(this.noise5, par2, par4, par5, par7, 1.121D, 1.121D, 0.5D);
+ this.noise6 = this.noiseGen6.generateNoiseOctaves(this.noise6, par2, par4, par5, par7, 200.0D, 200.0D, 0.5D);
+ this.noise3 = this.noiseGen3.generateNoiseOctaves(this.noise3, par2, par3, par4, par5, par6, par7,
+ var44 / 80.0D, var45 / 160.0D, var44 / 80.0D);
+ this.noise1 = this.noiseGen1.generateNoiseOctaves(this.noise1, par2, par3, par4, par5, par6, par7, var44, var45,
+ var44);
+ this.noise2 = this.noiseGen2.generateNoiseOctaves(this.noise2, par2, par3, par4, par5, par6, par7, var44, var45,
+ var44);
+ boolean var43 = false;
+ boolean var42 = false;
+ int var12 = 0;
+ int var13 = 0;
+
+ for (int var14 = 0; var14 < par5; ++var14) {
+ for (int var15 = 0; var15 < par7; ++var15) {
+ float var16 = 0.0F;
+ float var17 = 0.0F;
+ float var18 = 0.0F;
+ byte var19 = 2;
+ BiomeGenBase var20 = this.biomesForGeneration[var14 + 2 + (var15 + 2) * (par5 + 5)];
+
+ for (int var21 = -var19; var21 <= var19; ++var21) {
+ for (int var22 = -var19; var22 <= var19; ++var22) {
+ BiomeGenBase var23 = this.biomesForGeneration[var14 + var21 + 2
+ + (var15 + var22 + 2) * (par5 + 5)];
+ float var24 = this.parabolicField[var21 + 2 + (var22 + 2) * 5] / (var23.minHeight + 2.0F);
+
+ if (var23.minHeight > var20.minHeight) {
+ var24 /= 2.0F;
+ }
+
+ var16 += var23.maxHeight * var24;
+ var17 += var23.minHeight * var24;
+ var18 += var24;
+ }
+ }
+
+ var16 /= var18;
+ var17 /= var18;
+ var16 = var16 * 0.9F + 0.1F;
+ var17 = (var17 * 4.0F - 1.0F) / 8.0F;
+ double var46 = this.noise6[var13] / 8000.0D;
+
+ if (var46 < 0.0D) {
+ var46 = -var46 * 0.3D;
+ }
+
+ var46 = var46 * 3.0D - 2.0D;
+
+ if (var46 < 0.0D) {
+ var46 /= 2.0D;
+
+ if (var46 < -1.0D) {
+ var46 = -1.0D;
+ }
+
+ var46 /= 1.4D;
+ var46 /= 2.0D;
+ } else {
+ if (var46 > 1.0D) {
+ var46 = 1.0D;
+ }
+
+ var46 /= 8.0D;
+ }
+
+ ++var13;
+
+ for (int var47 = 0; var47 < par6; ++var47) {
+ double var48 = (double) var17;
+ double var26 = (double) var16;
+ var48 += var46 * 0.2D;
+ var48 = var48 * (double) par6 / 16.0D;
+ double var28 = (double) par6 / 2.0D + var48 * 4.0D;
+ double var30 = 0.0D;
+ double var32 = ((double) var47 - var28) * 12.0D * 128.0D / 128.0D / var26;
+
+ if (var32 < 0.0D) {
+ var32 *= 4.0D;
+ }
+
+ double var34 = this.noise1[var12] / 512.0D;
+ double var36 = this.noise2[var12] / 512.0D;
+ double var38 = (this.noise3[var12] / 10.0D + 1.0D) / 2.0D;
+
+ if (var38 < 0.0D) {
+ var30 = var34;
+ } else if (var38 > 1.0D) {
+ var30 = var36;
+ } else {
+ var30 = var34 + (var36 - var34) * var38;
+ }
+
+ var30 -= var32;
+
+ if (var47 > par6 - 4) {
+ double var40 = (double) ((float) (var47 - (par6 - 4)) / 3.0F);
+ var30 = var30 * (1.0D - var40) + -10.0D * var40;
+ }
+
+ par1ArrayOfDouble[var12] = var30;
+ ++var12;
+ }
+ }
+ }
+
+ return par1ArrayOfDouble;
+ }
+
+ /**
+ * Checks to see if a chunk exists at x, y
+ */
+ public boolean chunkExists(int par1, int par2) {
+ return true;
+ }
+
+ /**
+ * Populates chunk with ores etc etc
+ */
+ public void populate(IChunkProvider par1IChunkProvider, int par2, int par3) {
+ BlockSand.fallInstantly = true;
+ int var4 = par2 * 16;
+ int var5 = par3 * 16;
+ BiomeGenBase var6 = this.worldObj.getBiomeGenForCoords(var4 + 16, var5 + 16);
+ this.rand.setSeed(this.worldObj.getSeed());
+ long var7 = this.rand.nextLong() / 2L * 2L + 1L;
+ long var9 = this.rand.nextLong() / 2L * 2L + 1L;
+ this.rand.setSeed((long) par2 * var7 + (long) par3 * var9 ^ this.worldObj.getSeed());
+ boolean var11 = false;
+
+ if (this.mapFeaturesEnabled) {
+ this.mineshaftGenerator.generateStructuresInChunk(this.worldObj, this.rand, par2, par3);
+ var11 = this.villageGenerator.generateStructuresInChunk(this.worldObj, this.rand, par2, par3);
+ this.strongholdGenerator.generateStructuresInChunk(this.worldObj, this.rand, par2, par3);
+ this.scatteredFeatureGenerator.generateStructuresInChunk(this.worldObj, this.rand, par2, par3);
+ }
+
+ int var12;
+ int var13;
+ int var14;
+
+ if (!var11 && this.rand.nextInt(4) == 0) {
+ var12 = var4 + this.rand.nextInt(16) + 8;
+ var13 = this.rand.nextInt(128);
+ var14 = var5 + this.rand.nextInt(16) + 8;
+ (new WorldGenLakes(Block.waterStill.blockID)).generate(this.worldObj, this.rand, var12, var13, var14);
+ }
+
+ if (!var11 && this.rand.nextInt(8) == 0) {
+ var12 = var4 + this.rand.nextInt(16) + 8;
+ var13 = this.rand.nextInt(this.rand.nextInt(120) + 8);
+ var14 = var5 + this.rand.nextInt(16) + 8;
+
+ if (var13 < 63 || this.rand.nextInt(10) == 0) {
+ (new WorldGenLakes(Block.lavaStill.blockID)).generate(this.worldObj, this.rand, var12, var13, var14);
+ }
+ }
+
+ for (var12 = 0; var12 < 8; ++var12) {
+ var13 = var4 + this.rand.nextInt(16) + 8;
+ var14 = this.rand.nextInt(128);
+ int var15 = var5 + this.rand.nextInt(16) + 8;
+
+ if ((new WorldGenDungeons()).generate(this.worldObj, this.rand, var13, var14, var15)) {
+ ;
+ }
+ }
+
+ var6.decorate(this.worldObj, this.rand, var4, var5);
+ SpawnerAnimals.performWorldGenSpawning(this.worldObj, var6, var4 + 8, var5 + 8, 16, 16, this.rand);
+ var4 += 8;
+ var5 += 8;
+
+ for (var12 = 0; var12 < 16; ++var12) {
+ for (var13 = 0; var13 < 16; ++var13) {
+ var14 = this.worldObj.getPrecipitationHeight(var4 + var12, var5 + var13);
+
+ if (this.worldObj.isBlockFreezable(var12 + var4, var14 - 1, var13 + var5)) {
+ this.worldObj.setBlock(var12 + var4, var14 - 1, var13 + var5, Block.ice.blockID, 0, 2);
+ }
+
+ if (this.worldObj.canSnowAt(var12 + var4, var14, var13 + var5)) {
+ this.worldObj.setBlock(var12 + var4, var14, var13 + var5, Block.snow.blockID, 0, 2);
+ }
+ }
+ }
+
+ BlockSand.fallInstantly = false;
+ }
+
+ /**
+ * Two modes of operation: if passed true, save all Chunks in one go. If passed
+ * false, save up to two chunks. Return true if all chunks have been saved.
+ */
+ public boolean saveChunks(boolean par1, IProgressUpdate par2IProgressUpdate) {
+ return true;
+ }
+
+ public void func_104112_b() {
+ }
+
+ /**
+ * Unloads chunks that are marked to be unloaded. This is not guaranteed to
+ * unload every such chunk.
+ */
+ public boolean unloadQueuedChunks() {
+ return false;
+ }
+
+ /**
+ * Returns if the IChunkProvider supports saving.
+ */
+ public boolean canSave() {
+ return true;
+ }
+
+ /**
+ * Converts the instance data to a readable string.
+ */
+ public String makeString() {
+ return "RandomLevelSource";
+ }
+
+ /**
+ * Returns a list of creatures of the specified type that can spawn at the given
+ * location.
+ */
+ public List getPossibleCreatures(EnumCreatureType par1EnumCreatureType, int par2, int par3, int par4) {
+ BiomeGenBase var5 = this.worldObj.getBiomeGenForCoords(par2, par4);
+ return var5 == null ? null
+ : (var5 == BiomeGenBase.swampland && par1EnumCreatureType == EnumCreatureType.monster
+ && this.scatteredFeatureGenerator.hasStructureAt(par2, par3, par4)
+ ? this.scatteredFeatureGenerator.getScatteredFeatureSpawnList()
+ : var5.getSpawnableList(par1EnumCreatureType));
+ }
+
+ /**
+ * Returns the location of the closest structure of the specified type. If not
+ * found returns null.
+ */
+ public ChunkPosition findClosestStructure(World par1World, String par2Str, int par3, int par4, int par5) {
+ return "Stronghold".equals(par2Str) && this.strongholdGenerator != null
+ ? this.strongholdGenerator.getNearestInstance(par1World, par3, par4, par5)
+ : null;
+ }
+
+ public int getLoadedChunkCount() {
+ return 0;
+ }
+
+ public void recreateStructures(int par1, int par2) {
+ if (this.mapFeaturesEnabled) {
+ this.mineshaftGenerator.generate(this, this.worldObj, par1, par2, (byte[]) null);
+ this.villageGenerator.generate(this, this.worldObj, par1, par2, (byte[]) null);
+ this.strongholdGenerator.generate(this, this.worldObj, par1, par2, (byte[]) null);
+ this.scatteredFeatureGenerator.generate(this, this.worldObj, par1, par2, (byte[]) null);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ChunkProviderHell.java b/sp-server/src/main/java/net/minecraft/src/ChunkProviderHell.java
new file mode 100644
index 0000000..d5c5290
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ChunkProviderHell.java
@@ -0,0 +1,524 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ChunkProviderHell implements IChunkProvider {
+ private EaglercraftRandom hellRNG;
+
+ /** A NoiseGeneratorOctaves used in generating nether terrain */
+ private NoiseGeneratorOctaves netherNoiseGen1;
+ private NoiseGeneratorOctaves netherNoiseGen2;
+ private NoiseGeneratorOctaves netherNoiseGen3;
+
+ /** Determines whether slowsand or gravel can be generated at a location */
+ private NoiseGeneratorOctaves slowsandGravelNoiseGen;
+
+ /**
+ * Determines whether something other than nettherack can be generated at a
+ * location
+ */
+ private NoiseGeneratorOctaves netherrackExculsivityNoiseGen;
+ public NoiseGeneratorOctaves netherNoiseGen6;
+ public NoiseGeneratorOctaves netherNoiseGen7;
+
+ /** Is the world that the nether is getting generated. */
+ private World worldObj;
+ private double[] noiseField;
+ public MapGenNetherBridge genNetherBridge = new MapGenNetherBridge();
+
+ /**
+ * Holds the noise used to determine whether slowsand can be generated at a
+ * location
+ */
+ private double[] slowsandNoise = new double[256];
+ private double[] gravelNoise = new double[256];
+
+ /**
+ * Holds the noise used to determine whether something other than netherrack can
+ * be generated at a location
+ */
+ private double[] netherrackExclusivityNoise = new double[256];
+ private MapGenBase netherCaveGenerator = new MapGenCavesHell();
+ double[] noiseData1;
+ double[] noiseData2;
+ double[] noiseData3;
+ double[] noiseData4;
+ double[] noiseData5;
+
+ public ChunkProviderHell(World par1World, long par2) {
+ this.worldObj = par1World;
+ this.hellRNG = new EaglercraftRandom(par2);
+ this.netherNoiseGen1 = new NoiseGeneratorOctaves(this.hellRNG, 16);
+ this.netherNoiseGen2 = new NoiseGeneratorOctaves(this.hellRNG, 16);
+ this.netherNoiseGen3 = new NoiseGeneratorOctaves(this.hellRNG, 8);
+ this.slowsandGravelNoiseGen = new NoiseGeneratorOctaves(this.hellRNG, 4);
+ this.netherrackExculsivityNoiseGen = new NoiseGeneratorOctaves(this.hellRNG, 4);
+ this.netherNoiseGen6 = new NoiseGeneratorOctaves(this.hellRNG, 10);
+ this.netherNoiseGen7 = new NoiseGeneratorOctaves(this.hellRNG, 16);
+ }
+
+ /**
+ * Generates the shape of the terrain in the nether.
+ */
+ public void generateNetherTerrain(int par1, int par2, byte[] par3ArrayOfByte) {
+ byte var4 = 4;
+ byte var5 = 32;
+ int var6 = var4 + 1;
+ byte var7 = 17;
+ int var8 = var4 + 1;
+ this.noiseField = this.initializeNoiseField(this.noiseField, par1 * var4, 0, par2 * var4, var6, var7, var8);
+
+ for (int var9 = 0; var9 < var4; ++var9) {
+ for (int var10 = 0; var10 < var4; ++var10) {
+ for (int var11 = 0; var11 < 16; ++var11) {
+ double var12 = 0.125D;
+ double var14 = this.noiseField[((var9 + 0) * var8 + var10 + 0) * var7 + var11 + 0];
+ double var16 = this.noiseField[((var9 + 0) * var8 + var10 + 1) * var7 + var11 + 0];
+ double var18 = this.noiseField[((var9 + 1) * var8 + var10 + 0) * var7 + var11 + 0];
+ double var20 = this.noiseField[((var9 + 1) * var8 + var10 + 1) * var7 + var11 + 0];
+ double var22 = (this.noiseField[((var9 + 0) * var8 + var10 + 0) * var7 + var11 + 1] - var14)
+ * var12;
+ double var24 = (this.noiseField[((var9 + 0) * var8 + var10 + 1) * var7 + var11 + 1] - var16)
+ * var12;
+ double var26 = (this.noiseField[((var9 + 1) * var8 + var10 + 0) * var7 + var11 + 1] - var18)
+ * var12;
+ double var28 = (this.noiseField[((var9 + 1) * var8 + var10 + 1) * var7 + var11 + 1] - var20)
+ * var12;
+
+ for (int var30 = 0; var30 < 8; ++var30) {
+ double var31 = 0.25D;
+ double var33 = var14;
+ double var35 = var16;
+ double var37 = (var18 - var14) * var31;
+ double var39 = (var20 - var16) * var31;
+
+ for (int var41 = 0; var41 < 4; ++var41) {
+ int var42 = var41 + var9 * 4 << 11 | 0 + var10 * 4 << 7 | var11 * 8 + var30;
+ short var43 = 128;
+ double var44 = 0.25D;
+ double var46 = var33;
+ double var48 = (var35 - var33) * var44;
+
+ for (int var50 = 0; var50 < 4; ++var50) {
+ int var51 = 0;
+
+ if (var11 * 8 + var30 < var5) {
+ var51 = Block.lavaStill.blockID;
+ }
+
+ if (var46 > 0.0D) {
+ var51 = Block.netherrack.blockID;
+ }
+
+ par3ArrayOfByte[var42] = (byte) var51;
+ var42 += var43;
+ var46 += var48;
+ }
+
+ var33 += var37;
+ var35 += var39;
+ }
+
+ var14 += var22;
+ var16 += var24;
+ var18 += var26;
+ var20 += var28;
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * name based on ChunkProviderGenerate
+ */
+ public void replaceBlocksForBiome(int par1, int par2, byte[] par3ArrayOfByte) {
+ byte var4 = 64;
+ double var5 = 0.03125D;
+ this.slowsandNoise = this.slowsandGravelNoiseGen.generateNoiseOctaves(this.slowsandNoise, par1 * 16, par2 * 16,
+ 0, 16, 16, 1, var5, var5, 1.0D);
+ this.gravelNoise = this.slowsandGravelNoiseGen.generateNoiseOctaves(this.gravelNoise, par1 * 16, 109, par2 * 16,
+ 16, 1, 16, var5, 1.0D, var5);
+ this.netherrackExclusivityNoise = this.netherrackExculsivityNoiseGen.generateNoiseOctaves(
+ this.netherrackExclusivityNoise, par1 * 16, par2 * 16, 0, 16, 16, 1, var5 * 2.0D, var5 * 2.0D,
+ var5 * 2.0D);
+
+ for (int var7 = 0; var7 < 16; ++var7) {
+ for (int var8 = 0; var8 < 16; ++var8) {
+ boolean var9 = this.slowsandNoise[var7 + var8 * 16] + this.hellRNG.nextDouble() * 0.2D > 0.0D;
+ boolean var10 = this.gravelNoise[var7 + var8 * 16] + this.hellRNG.nextDouble() * 0.2D > 0.0D;
+ int var11 = (int) (this.netherrackExclusivityNoise[var7 + var8 * 16] / 3.0D + 3.0D
+ + this.hellRNG.nextDouble() * 0.25D);
+ int var12 = -1;
+ byte var13 = (byte) Block.netherrack.blockID;
+ byte var14 = (byte) Block.netherrack.blockID;
+
+ for (int var15 = 127; var15 >= 0; --var15) {
+ int var16 = (var8 * 16 + var7) * 128 + var15;
+
+ if (var15 < 127 - this.hellRNG.nextInt(5) && var15 > 0 + this.hellRNG.nextInt(5)) {
+ byte var17 = par3ArrayOfByte[var16];
+
+ if (var17 == 0) {
+ var12 = -1;
+ } else if (var17 == Block.netherrack.blockID) {
+ if (var12 == -1) {
+ if (var11 <= 0) {
+ var13 = 0;
+ var14 = (byte) Block.netherrack.blockID;
+ } else if (var15 >= var4 - 4 && var15 <= var4 + 1) {
+ var13 = (byte) Block.netherrack.blockID;
+ var14 = (byte) Block.netherrack.blockID;
+
+ if (var10) {
+ var13 = (byte) Block.gravel.blockID;
+ }
+
+ if (var10) {
+ var14 = (byte) Block.netherrack.blockID;
+ }
+
+ if (var9) {
+ var13 = (byte) Block.slowSand.blockID;
+ }
+
+ if (var9) {
+ var14 = (byte) Block.slowSand.blockID;
+ }
+ }
+
+ if (var15 < var4 && var13 == 0) {
+ var13 = (byte) Block.lavaStill.blockID;
+ }
+
+ var12 = var11;
+
+ if (var15 >= var4 - 1) {
+ par3ArrayOfByte[var16] = var13;
+ } else {
+ par3ArrayOfByte[var16] = var14;
+ }
+ } else if (var12 > 0) {
+ --var12;
+ par3ArrayOfByte[var16] = var14;
+ }
+ }
+ } else {
+ par3ArrayOfByte[var16] = (byte) Block.bedrock.blockID;
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * loads or generates the chunk at the chunk location specified
+ */
+ public Chunk loadChunk(int par1, int par2) {
+ return this.provideChunk(par1, par2);
+ }
+
+ /**
+ * Will return back a chunk, if it doesn't exist and its not a MP client it will
+ * generates all the blocks for the specified chunk from the map seed and chunk
+ * seed
+ */
+ public Chunk provideChunk(int par1, int par2) {
+ this.hellRNG.setSeed((long) par1 * 341873128712L + (long) par2 * 132897987541L);
+ byte[] var3 = new byte[32768];
+ this.generateNetherTerrain(par1, par2, var3);
+ this.replaceBlocksForBiome(par1, par2, var3);
+ this.netherCaveGenerator.generate(this, this.worldObj, par1, par2, var3);
+ this.genNetherBridge.generate(this, this.worldObj, par1, par2, var3);
+ Chunk var4 = new Chunk(this.worldObj, var3, par1, par2);
+ BiomeGenBase[] var5 = this.worldObj.getWorldChunkManager().loadBlockGeneratorData((BiomeGenBase[]) null,
+ par1 * 16, par2 * 16, 16, 16);
+ byte[] var6 = var4.getBiomeArray();
+
+ for (int var7 = 0; var7 < var6.length; ++var7) {
+ var6[var7] = (byte) var5[var7].biomeID;
+ }
+
+ var4.resetRelightChecks();
+ return var4;
+ }
+
+ /**
+ * generates a subset of the level's terrain data. Takes 7 arguments: the
+ * [empty] noise array, the position, and the size.
+ */
+ private double[] initializeNoiseField(double[] par1ArrayOfDouble, int par2, int par3, int par4, int par5, int par6,
+ int par7) {
+ if (par1ArrayOfDouble == null) {
+ par1ArrayOfDouble = new double[par5 * par6 * par7];
+ }
+
+ double var8 = 684.412D;
+ double var10 = 2053.236D;
+ this.noiseData4 = this.netherNoiseGen6.generateNoiseOctaves(this.noiseData4, par2, par3, par4, par5, 1, par7,
+ 1.0D, 0.0D, 1.0D);
+ this.noiseData5 = this.netherNoiseGen7.generateNoiseOctaves(this.noiseData5, par2, par3, par4, par5, 1, par7,
+ 100.0D, 0.0D, 100.0D);
+ this.noiseData1 = this.netherNoiseGen3.generateNoiseOctaves(this.noiseData1, par2, par3, par4, par5, par6, par7,
+ var8 / 80.0D, var10 / 60.0D, var8 / 80.0D);
+ this.noiseData2 = this.netherNoiseGen1.generateNoiseOctaves(this.noiseData2, par2, par3, par4, par5, par6, par7,
+ var8, var10, var8);
+ this.noiseData3 = this.netherNoiseGen2.generateNoiseOctaves(this.noiseData3, par2, par3, par4, par5, par6, par7,
+ var8, var10, var8);
+ int var12 = 0;
+ int var13 = 0;
+ double[] var14 = new double[par6];
+ int var15;
+
+ for (var15 = 0; var15 < par6; ++var15) {
+ var14[var15] = Math.cos((double) var15 * Math.PI * 6.0D / (double) par6) * 2.0D;
+ double var16 = (double) var15;
+
+ if (var15 > par6 / 2) {
+ var16 = (double) (par6 - 1 - var15);
+ }
+
+ if (var16 < 4.0D) {
+ var16 = 4.0D - var16;
+ var14[var15] -= var16 * var16 * var16 * 10.0D;
+ }
+ }
+
+ for (var15 = 0; var15 < par5; ++var15) {
+ for (int var36 = 0; var36 < par7; ++var36) {
+ double var17 = (this.noiseData4[var13] + 256.0D) / 512.0D;
+
+ if (var17 > 1.0D) {
+ var17 = 1.0D;
+ }
+
+ double var19 = 0.0D;
+ double var21 = this.noiseData5[var13] / 8000.0D;
+
+ if (var21 < 0.0D) {
+ var21 = -var21;
+ }
+
+ var21 = var21 * 3.0D - 3.0D;
+
+ if (var21 < 0.0D) {
+ var21 /= 2.0D;
+
+ if (var21 < -1.0D) {
+ var21 = -1.0D;
+ }
+
+ var21 /= 1.4D;
+ var21 /= 2.0D;
+ var17 = 0.0D;
+ } else {
+ if (var21 > 1.0D) {
+ var21 = 1.0D;
+ }
+
+ var21 /= 6.0D;
+ }
+
+ var17 += 0.5D;
+ var21 = var21 * (double) par6 / 16.0D;
+ ++var13;
+
+ for (int var23 = 0; var23 < par6; ++var23) {
+ double var24 = 0.0D;
+ double var26 = var14[var23];
+ double var28 = this.noiseData2[var12] / 512.0D;
+ double var30 = this.noiseData3[var12] / 512.0D;
+ double var32 = (this.noiseData1[var12] / 10.0D + 1.0D) / 2.0D;
+
+ if (var32 < 0.0D) {
+ var24 = var28;
+ } else if (var32 > 1.0D) {
+ var24 = var30;
+ } else {
+ var24 = var28 + (var30 - var28) * var32;
+ }
+
+ var24 -= var26;
+ double var34;
+
+ if (var23 > par6 - 4) {
+ var34 = (double) ((float) (var23 - (par6 - 4)) / 3.0F);
+ var24 = var24 * (1.0D - var34) + -10.0D * var34;
+ }
+
+ if ((double) var23 < var19) {
+ var34 = (var19 - (double) var23) / 4.0D;
+
+ if (var34 < 0.0D) {
+ var34 = 0.0D;
+ }
+
+ if (var34 > 1.0D) {
+ var34 = 1.0D;
+ }
+
+ var24 = var24 * (1.0D - var34) + -10.0D * var34;
+ }
+
+ par1ArrayOfDouble[var12] = var24;
+ ++var12;
+ }
+ }
+ }
+
+ return par1ArrayOfDouble;
+ }
+
+ /**
+ * Checks to see if a chunk exists at x, y
+ */
+ public boolean chunkExists(int par1, int par2) {
+ return true;
+ }
+
+ /**
+ * Populates chunk with ores etc etc
+ */
+ public void populate(IChunkProvider par1IChunkProvider, int par2, int par3) {
+ BlockSand.fallInstantly = true;
+ int var4 = par2 * 16;
+ int var5 = par3 * 16;
+ this.genNetherBridge.generateStructuresInChunk(this.worldObj, this.hellRNG, par2, par3);
+ int var6;
+ int var7;
+ int var8;
+ int var9;
+
+ for (var6 = 0; var6 < 8; ++var6) {
+ var7 = var4 + this.hellRNG.nextInt(16) + 8;
+ var8 = this.hellRNG.nextInt(120) + 4;
+ var9 = var5 + this.hellRNG.nextInt(16) + 8;
+ (new WorldGenHellLava(Block.lavaMoving.blockID, false)).generate(this.worldObj, this.hellRNG, var7, var8,
+ var9);
+ }
+
+ var6 = this.hellRNG.nextInt(this.hellRNG.nextInt(10) + 1) + 1;
+ int var10;
+
+ for (var7 = 0; var7 < var6; ++var7) {
+ var8 = var4 + this.hellRNG.nextInt(16) + 8;
+ var9 = this.hellRNG.nextInt(120) + 4;
+ var10 = var5 + this.hellRNG.nextInt(16) + 8;
+ (new WorldGenFire()).generate(this.worldObj, this.hellRNG, var8, var9, var10);
+ }
+
+ var6 = this.hellRNG.nextInt(this.hellRNG.nextInt(10) + 1);
+
+ for (var7 = 0; var7 < var6; ++var7) {
+ var8 = var4 + this.hellRNG.nextInt(16) + 8;
+ var9 = this.hellRNG.nextInt(120) + 4;
+ var10 = var5 + this.hellRNG.nextInt(16) + 8;
+ (new WorldGenGlowStone1()).generate(this.worldObj, this.hellRNG, var8, var9, var10);
+ }
+
+ for (var7 = 0; var7 < 10; ++var7) {
+ var8 = var4 + this.hellRNG.nextInt(16) + 8;
+ var9 = this.hellRNG.nextInt(128);
+ var10 = var5 + this.hellRNG.nextInt(16) + 8;
+ (new WorldGenGlowStone2()).generate(this.worldObj, this.hellRNG, var8, var9, var10);
+ }
+
+ if (this.hellRNG.nextInt(1) == 0) {
+ var7 = var4 + this.hellRNG.nextInt(16) + 8;
+ var8 = this.hellRNG.nextInt(128);
+ var9 = var5 + this.hellRNG.nextInt(16) + 8;
+ (new WorldGenFlowers(Block.mushroomBrown.blockID)).generate(this.worldObj, this.hellRNG, var7, var8, var9);
+ }
+
+ if (this.hellRNG.nextInt(1) == 0) {
+ var7 = var4 + this.hellRNG.nextInt(16) + 8;
+ var8 = this.hellRNG.nextInt(128);
+ var9 = var5 + this.hellRNG.nextInt(16) + 8;
+ (new WorldGenFlowers(Block.mushroomRed.blockID)).generate(this.worldObj, this.hellRNG, var7, var8, var9);
+ }
+
+ WorldGenMinable var12 = new WorldGenMinable(Block.oreNetherQuartz.blockID, 13, Block.netherrack.blockID);
+ int var11;
+
+ for (var8 = 0; var8 < 16; ++var8) {
+ var9 = var4 + this.hellRNG.nextInt(16);
+ var10 = this.hellRNG.nextInt(108) + 10;
+ var11 = var5 + this.hellRNG.nextInt(16);
+ var12.generate(this.worldObj, this.hellRNG, var9, var10, var11);
+ }
+
+ for (var8 = 0; var8 < 16; ++var8) {
+ var9 = var4 + this.hellRNG.nextInt(16);
+ var10 = this.hellRNG.nextInt(108) + 10;
+ var11 = var5 + this.hellRNG.nextInt(16);
+ (new WorldGenHellLava(Block.lavaMoving.blockID, true)).generate(this.worldObj, this.hellRNG, var9, var10,
+ var11);
+ }
+
+ BlockSand.fallInstantly = false;
+ }
+
+ /**
+ * Two modes of operation: if passed true, save all Chunks in one go. If passed
+ * false, save up to two chunks. Return true if all chunks have been saved.
+ */
+ public boolean saveChunks(boolean par1, IProgressUpdate par2IProgressUpdate) {
+ return true;
+ }
+
+ public void func_104112_b() {
+ }
+
+ /**
+ * Unloads chunks that are marked to be unloaded. This is not guaranteed to
+ * unload every such chunk.
+ */
+ public boolean unloadQueuedChunks() {
+ return false;
+ }
+
+ /**
+ * Returns if the IChunkProvider supports saving.
+ */
+ public boolean canSave() {
+ return true;
+ }
+
+ /**
+ * Converts the instance data to a readable string.
+ */
+ public String makeString() {
+ return "HellRandomLevelSource";
+ }
+
+ /**
+ * Returns a list of creatures of the specified type that can spawn at the given
+ * location.
+ */
+ public List getPossibleCreatures(EnumCreatureType par1EnumCreatureType, int par2, int par3, int par4) {
+ if (par1EnumCreatureType == EnumCreatureType.monster && this.genNetherBridge.hasStructureAt(par2, par3, par4)) {
+ return this.genNetherBridge.getSpawnList();
+ } else {
+ BiomeGenBase var5 = this.worldObj.getBiomeGenForCoords(par2, par4);
+ return var5 == null ? null : var5.getSpawnableList(par1EnumCreatureType);
+ }
+ }
+
+ /**
+ * Returns the location of the closest structure of the specified type. If not
+ * found returns null.
+ */
+ public ChunkPosition findClosestStructure(World par1World, String par2Str, int par3, int par4, int par5) {
+ return null;
+ }
+
+ public int getLoadedChunkCount() {
+ return 0;
+ }
+
+ public void recreateStructures(int par1, int par2) {
+ this.genNetherBridge.generate(this, this.worldObj, par1, par2, (byte[]) null);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ChunkProviderServer.java b/sp-server/src/main/java/net/minecraft/src/ChunkProviderServer.java
new file mode 100644
index 0000000..f9b54c3
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ChunkProviderServer.java
@@ -0,0 +1,326 @@
+package net.minecraft.src;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import net.lax1dude.eaglercraft.sp.SysUtil;
+
+public class ChunkProviderServer implements IChunkProvider {
+ private Set droppedChunksSet = new HashSet();
+
+ /** a dummy chunk, returned in place of an actual chunk. */
+ private Chunk dummyChunk;
+
+ /**
+ * chunk generator object. Calls to load nonexistent chunks are forwarded to
+ * this object.
+ */
+ private IChunkProvider serverChunkGenerator;
+ private IChunkLoader chunkLoader;
+
+ /**
+ * if set, this flag forces a request to load a chunk to load the chunk rather
+ * than defaulting to the dummy if possible
+ */
+ public boolean chunkLoadOverride = true;
+
+ /** map of chunk Id's to Chunk instances */
+ private LongHashMap id2ChunkMap = new LongHashMap();
+ private List loadedChunks = new ArrayList();
+ private WorldServer worldObj;
+
+ public ChunkProviderServer(WorldServer par1WorldServer, IChunkLoader par2IChunkLoader,
+ IChunkProvider par3IChunkProvider) {
+ this.dummyChunk = new EmptyChunk(par1WorldServer, 0, 0);
+ this.worldObj = par1WorldServer;
+ this.chunkLoader = par2IChunkLoader;
+ this.serverChunkGenerator = par3IChunkProvider;
+ }
+
+ /**
+ * Checks to see if a chunk exists at x, y
+ */
+ public boolean chunkExists(int par1, int par2) {
+ return this.id2ChunkMap.containsItem(ChunkCoordIntPair.chunkXZ2Int(par1, par2));
+ }
+
+ public void dropChunk(int par1, int par2) {
+ /*
+ if (this.worldObj.provider.canRespawnHere()) {
+ ChunkCoordinates var3 = this.worldObj.getSpawnPoint();
+ int var4 = par1 * 16 + 8 - var3.posX;
+ int var5 = par2 * 16 + 8 - var3.posZ;
+ short var6 = 128;
+
+ if (var4 < -var6 || var4 > var6 || var5 < -var6 || var5 > var6) {
+ this.droppedChunksSet.add(Long.valueOf(ChunkCoordIntPair.chunkXZ2Int(par1, par2)));
+ }
+ } else {
+ */
+ this.droppedChunksSet.add(Long.valueOf(ChunkCoordIntPair.chunkXZ2Int(par1, par2)));
+ //}
+ }
+
+ /**
+ * marks all chunks for unload, ignoring those near the spawn
+ */
+ public void unloadAllChunks() {
+ Iterator var1 = this.loadedChunks.iterator();
+
+ while (var1.hasNext()) {
+ Chunk var2 = (Chunk) var1.next();
+ this.dropChunk(var2.xPosition, var2.zPosition);
+ }
+ }
+
+ /**
+ * loads or generates the chunk at the chunk location specified
+ */
+ public Chunk loadChunk(int par1, int par2) {
+ long var3 = ChunkCoordIntPair.chunkXZ2Int(par1, par2);
+ this.droppedChunksSet.remove(Long.valueOf(var3));
+ Chunk var5 = (Chunk) this.id2ChunkMap.getValueByKey(var3);
+
+ if (var5 == null) {
+ var5 = this.loadChunkFromFile(par1, par2);
+
+ if (var5 == null) {
+ if (this.serverChunkGenerator == null) {
+ var5 = this.dummyChunk;
+ } else {
+ ++_g;
+ var5 = this.serverChunkGenerator.provideChunk(par1, par2);
+ }
+ }else {
+ ++_r;
+ }
+
+ this.id2ChunkMap.add(var3, var5);
+ this.loadedChunks.add(var5);
+
+ if (var5 != null) {
+ var5.onChunkLoad();
+ }
+
+ var5.populateChunk(this, this, par1, par2);
+ }
+
+ return var5;
+ }
+
+ /**
+ * Will return back a chunk, if it doesn't exist and its not a MP client it will
+ * generates all the blocks for the specified chunk from the map seed and chunk
+ * seed
+ */
+ public Chunk provideChunk(int par1, int par2) {
+ Chunk var3 = (Chunk) this.id2ChunkMap.getValueByKey(ChunkCoordIntPair.chunkXZ2Int(par1, par2));
+ return var3 == null ? (!this.worldObj.findingSpawnPoint && !this.chunkLoadOverride ? this.dummyChunk
+ : this.loadChunk(par1, par2)) : var3;
+ }
+
+ private Chunk loadChunkFromFile(int par1, int par2) {
+ if (this.chunkLoader == null) {
+ return null;
+ } else {
+ try {
+ Chunk var3 = this.chunkLoader.loadChunk(this.worldObj, par1, par2);
+
+ if (var3 != null) {
+ var3.lastSaveTime = this.worldObj.getTotalWorldTime();
+
+ if (this.serverChunkGenerator != null) {
+ this.serverChunkGenerator.recreateStructures(par1, par2);
+ }
+ }
+
+ return var3;
+ } catch (Exception var4) {
+ var4.printStackTrace();
+ return null;
+ }
+ }
+ }
+
+ private void saveChunkExtraData(Chunk par1Chunk) {
+ if (this.chunkLoader != null) {
+ try {
+ this.chunkLoader.saveExtraChunkData(this.worldObj, par1Chunk);
+ } catch (Exception var3) {
+ var3.printStackTrace();
+ }
+ }
+ }
+
+ private void saveChunkData(Chunk par1Chunk) {
+ if (this.chunkLoader != null) {
+ ++_w;
+ try {
+ par1Chunk.lastSaveTime = this.worldObj.getTotalWorldTime();
+ this.chunkLoader.saveChunk(this.worldObj, par1Chunk);
+ } catch (IOException var3) {
+ var3.printStackTrace();
+ } catch (MinecraftException var4) {
+ var4.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * Populates chunk with ores etc etc
+ */
+ public void populate(IChunkProvider par1IChunkProvider, int par2, int par3) {
+ Chunk var4 = this.provideChunk(par2, par3);
+
+ if (!var4.isTerrainPopulated) {
+ var4.isTerrainPopulated = true;
+
+ if (this.serverChunkGenerator != null) {
+ this.serverChunkGenerator.populate(par1IChunkProvider, par2, par3);
+ var4.setChunkModified();
+ }
+ }
+ }
+
+ /**
+ * Two modes of operation: if passed true, save all Chunks in one go. If passed
+ * false, save up to two chunks. Return true if all chunks have been saved.
+ */
+ public boolean saveChunks(boolean par1, IProgressUpdate par2IProgressUpdate) {
+ int var3 = 0;
+
+ for (int var4 = 0; var4 < this.loadedChunks.size(); ++var4) {
+ Chunk var5 = (Chunk) this.loadedChunks.get(var4);
+
+ if (par1) {
+ this.saveChunkExtraData(var5);
+ }
+
+ if (var5.needsSaving(par1)) {
+ this.saveChunkData(var5);
+ var5.isModified = false;
+ ++var3;
+
+ if (var3 == 24 && !par1) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ public void func_104112_b() {
+ if (this.chunkLoader != null) {
+ this.chunkLoader.saveExtraData();
+ }
+ }
+
+ private long fixTheFuckingMemoryLeak = 0l;
+
+ /**
+ * Unloads chunks that are marked to be unloaded. This is not guaranteed to
+ * unload every such chunk.
+ */
+ public boolean unloadQueuedChunks() {
+ if (!this.worldObj.levelSaving) {
+
+ long millis = SysUtil.steadyTimeMillis();
+ if(millis - fixTheFuckingMemoryLeak > 10000l) { // FUCK OFF SUCK MY FUCKING COCK
+ fixTheFuckingMemoryLeak = millis;
+ this.id2ChunkMap.iterate((l,o) -> {
+ Chunk id = (Chunk) o;
+ PlayerInstance ii = this.worldObj.getPlayerManager().getPlayerInstance(id.xPosition, id.zPosition, false);
+ if((ii == null || ii.isEmpty()) && !droppedChunksSet.contains(l)) {
+ this.droppedChunksSet.add(l);
+ //System.out.println("Leaked: " + id);
+ }
+ });
+ }
+
+ for (int var1 = 0; var1 < 100; ++var1) {
+ if (!this.droppedChunksSet.isEmpty()) {
+ Long var2 = (Long) this.droppedChunksSet.iterator().next();
+ Chunk var3 = (Chunk) this.id2ChunkMap.getValueByKey(var2.longValue());
+ var3.onChunkUnload();
+ this.saveChunkData(var3);
+ this.saveChunkExtraData(var3);
+ this.worldObj.getPlayerManager().freePlayerInstance(var2);
+ this.droppedChunksSet.remove(var2);
+ this.id2ChunkMap.remove(var2.longValue());
+ this.loadedChunks.remove(var3);
+ //System.out.println("" + this.droppedChunksSet.size() + ", " + this.id2ChunkMap.getNumHashElements());
+ }
+ }
+
+ if (this.chunkLoader != null) {
+ this.chunkLoader.chunkTick();
+ }
+ }
+
+ return this.serverChunkGenerator.unloadQueuedChunks();
+ }
+
+ /**
+ * Returns if the IChunkProvider supports saving.
+ */
+ public boolean canSave() {
+ return !this.worldObj.levelSaving;
+ }
+
+ /**
+ * Converts the instance data to a readable string.
+ */
+ public String makeString() {
+ return "ServerChunkCache: " + this.id2ChunkMap.getNumHashElements() + " Drop: " + this.droppedChunksSet.size();
+ }
+
+ /**
+ * Returns a list of creatures of the specified type that can spawn at the given
+ * location.
+ */
+ public List getPossibleCreatures(EnumCreatureType par1EnumCreatureType, int par2, int par3, int par4) {
+ return this.serverChunkGenerator.getPossibleCreatures(par1EnumCreatureType, par2, par3, par4);
+ }
+
+ /**
+ * Returns the location of the closest structure of the specified type. If not
+ * found returns null.
+ */
+ public ChunkPosition findClosestStructure(World par1World, String par2Str, int par3, int par4, int par5) {
+ return this.serverChunkGenerator.findClosestStructure(par1World, par2Str, par3, par4, par5);
+ }
+
+ public int getLoadedChunkCount() {
+ return this.id2ChunkMap.getNumHashElements();
+ }
+
+ public void recreateStructures(int par1, int par2) {
+ }
+
+ private int _r = 0;
+ private int _w = 0;
+ private int _g = 0;
+
+ public int statR() {
+ int r = _r;
+ _r = 0;
+ return r;
+ }
+
+ public int statW() {
+ int w = _w;
+ _w = 0;
+ return w;
+ }
+
+ public int statG() {
+ int g = _g;
+ _g = 0;
+ return g;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/CombatEntry.java b/sp-server/src/main/java/net/minecraft/src/CombatEntry.java
new file mode 100644
index 0000000..b0535f9
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/CombatEntry.java
@@ -0,0 +1,44 @@
+package net.minecraft.src;
+
+public class CombatEntry {
+ private final DamageSource field_94569_a;
+ private final int field_94567_b;
+ private final int field_94568_c;
+ private final int field_94565_d;
+ private final String field_94566_e;
+ private final float field_94564_f;
+
+ public CombatEntry(DamageSource par1DamageSource, int par2, int par3, int par4, String par5Str, float par6) {
+ this.field_94569_a = par1DamageSource;
+ this.field_94567_b = par2;
+ this.field_94568_c = par4;
+ this.field_94565_d = par3;
+ this.field_94566_e = par5Str;
+ this.field_94564_f = par6;
+ }
+
+ public DamageSource func_94560_a() {
+ return this.field_94569_a;
+ }
+
+ public int func_94563_c() {
+ return this.field_94568_c;
+ }
+
+ public boolean func_94559_f() {
+ return this.field_94569_a.getEntity() instanceof EntityLiving;
+ }
+
+ public String func_94562_g() {
+ return this.field_94566_e;
+ }
+
+ public String func_94558_h() {
+ return this.func_94560_a().getEntity() == null ? null
+ : this.func_94560_a().getEntity().getTranslatedEntityName();
+ }
+
+ public float func_94561_i() {
+ return this.field_94569_a == DamageSource.outOfWorld ? Float.MAX_VALUE : this.field_94564_f;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/CombatTracker.java b/sp-server/src/main/java/net/minecraft/src/CombatTracker.java
new file mode 100644
index 0000000..6ea9ac0
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/CombatTracker.java
@@ -0,0 +1,181 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+public class CombatTracker {
+ private final List field_94556_a = new ArrayList();
+ private final EntityLiving field_94554_b;
+ private int field_94555_c = 0;
+ private boolean field_94552_d = false;
+ private boolean field_94553_e = false;
+ private String field_94551_f;
+
+ public CombatTracker(EntityLiving par1EntityLiving) {
+ this.field_94554_b = par1EntityLiving;
+ }
+
+ public void func_94545_a() {
+ this.func_94542_g();
+
+ if (this.field_94554_b.isOnLadder()) {
+ int var1 = this.field_94554_b.worldObj.getBlockId(MathHelper.floor_double(this.field_94554_b.posX),
+ MathHelper.floor_double(this.field_94554_b.boundingBox.minY),
+ MathHelper.floor_double(this.field_94554_b.posZ));
+
+ if (var1 == Block.ladder.blockID) {
+ this.field_94551_f = "ladder";
+ } else if (var1 == Block.vine.blockID) {
+ this.field_94551_f = "vines";
+ }
+ } else if (this.field_94554_b.isInWater()) {
+ this.field_94551_f = "water";
+ }
+ }
+
+ public void func_94547_a(DamageSource par1DamageSource, int par2, int par3) {
+ this.func_94549_h();
+ this.func_94545_a();
+ CombatEntry var4 = new CombatEntry(par1DamageSource, this.field_94554_b.ticksExisted, par2, par3,
+ this.field_94551_f, this.field_94554_b.fallDistance);
+ this.field_94556_a.add(var4);
+ this.field_94555_c = this.field_94554_b.ticksExisted;
+ this.field_94553_e = true;
+ this.field_94552_d |= var4.func_94559_f();
+ }
+
+ public String func_94546_b() {
+ if (this.field_94556_a.size() == 0) {
+ return this.field_94554_b.getTranslatedEntityName() + " died";
+ } else {
+ CombatEntry var1 = this.func_94544_f();
+ CombatEntry var2 = (CombatEntry) this.field_94556_a.get(this.field_94556_a.size() - 1);
+ String var3 = "";
+ String var4 = var2.func_94558_h();
+ Entity var5 = var2.func_94560_a().getEntity();
+
+ if (var1 != null && var2.func_94560_a() == DamageSource.fall) {
+ String var6 = var1.func_94558_h();
+
+ if (var1.func_94560_a() != DamageSource.fall && var1.func_94560_a() != DamageSource.outOfWorld) {
+ if (var6 != null && (var4 == null || !var6.equals(var4))) {
+ Entity var9 = var1.func_94560_a().getEntity();
+ ItemStack var8 = var9 instanceof EntityLiving ? ((EntityLiving) var9).getHeldItem() : null;
+
+ if (var8 != null && var8.hasDisplayName()) {
+ var3 = StatCollector.translateToLocalFormatted("death.fell.assist.item", new Object[] {
+ this.field_94554_b.getTranslatedEntityName(), var4, var8.getDisplayName() });
+ } else {
+ var3 = StatCollector.translateToLocalFormatted("death.fell.assist",
+ new Object[] { this.field_94554_b.getTranslatedEntityName(), var6 });
+ }
+ } else if (var4 != null) {
+ ItemStack var7 = var5 instanceof EntityLiving ? ((EntityLiving) var5).getHeldItem() : null;
+
+ if (var7 != null && var7.hasDisplayName()) {
+ var3 = StatCollector.translateToLocalFormatted("death.fell.finish.item", new Object[] {
+ this.field_94554_b.getTranslatedEntityName(), var4, var7.getDisplayName() });
+ } else {
+ var3 = StatCollector.translateToLocalFormatted("death.fell.finish",
+ new Object[] { this.field_94554_b.getTranslatedEntityName(), var4 });
+ }
+ } else {
+ var3 = StatCollector.translateToLocalFormatted("death.fell.killer",
+ new Object[] { this.field_94554_b.getTranslatedEntityName() });
+ }
+ } else {
+ var3 = StatCollector.translateToLocalFormatted("death.fell.accident." + this.func_94548_b(var1),
+ new Object[] { this.field_94554_b.getTranslatedEntityName() });
+ }
+ } else {
+ var3 = var2.func_94560_a().getDeathMessage(this.field_94554_b);
+ }
+
+ return var3;
+ }
+ }
+
+ public EntityLiving func_94550_c() {
+ EntityLiving var1 = null;
+ EntityPlayer var2 = null;
+ int var3 = 0;
+ int var4 = 0;
+ Iterator var5 = this.field_94556_a.iterator();
+
+ while (var5.hasNext()) {
+ CombatEntry var6 = (CombatEntry) var5.next();
+
+ if (var6.func_94560_a().getEntity() instanceof EntityPlayer
+ && (var2 == null || var6.func_94563_c() > var4)) {
+ var4 = var6.func_94563_c();
+ var2 = (EntityPlayer) var6.func_94560_a().getEntity();
+ }
+
+ if (var6.func_94560_a().getEntity() instanceof EntityLiving
+ && (var1 == null || var6.func_94563_c() > var3)) {
+ var3 = var6.func_94563_c();
+ var1 = (EntityLiving) var6.func_94560_a().getEntity();
+ }
+ }
+
+ if (var2 != null && var4 >= var3 / 3) {
+ return var2;
+ } else {
+ return var1;
+ }
+ }
+
+ private CombatEntry func_94544_f() {
+ CombatEntry var1 = null;
+ CombatEntry var2 = null;
+ byte var3 = 0;
+ float var4 = 0.0F;
+
+ for (int var5 = 0; var5 < this.field_94556_a.size(); ++var5) {
+ CombatEntry var6 = (CombatEntry) this.field_94556_a.get(var5);
+ CombatEntry var7 = var5 > 0 ? (CombatEntry) this.field_94556_a.get(var5 - 1) : null;
+
+ if ((var6.func_94560_a() == DamageSource.fall || var6.func_94560_a() == DamageSource.outOfWorld)
+ && var6.func_94561_i() > 0.0F && (var1 == null || var6.func_94561_i() > var4)) {
+ if (var5 > 0) {
+ var1 = var7;
+ } else {
+ var1 = var6;
+ }
+
+ var4 = var6.func_94561_i();
+ }
+
+ if (var6.func_94562_g() != null && (var2 == null || var6.func_94563_c() > var3)) {
+ var2 = var6;
+ }
+ }
+
+ if (var4 > 5.0F && var1 != null) {
+ return var1;
+ } else if (var3 > 5 && var2 != null) {
+ return var2;
+ } else {
+ return null;
+ }
+ }
+
+ private String func_94548_b(CombatEntry par1CombatEntry) {
+ return par1CombatEntry.func_94562_g() == null ? "generic" : par1CombatEntry.func_94562_g();
+ }
+
+ private void func_94542_g() {
+ this.field_94551_f = null;
+ }
+
+ private void func_94549_h() {
+ int var1 = this.field_94552_d ? 300 : 100;
+
+ if (this.field_94553_e && this.field_94554_b.ticksExisted - this.field_94555_c > var1) {
+ this.field_94556_a.clear();
+ this.field_94553_e = false;
+ this.field_94552_d = false;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/CommandBase.java b/sp-server/src/main/java/net/minecraft/src/CommandBase.java
new file mode 100644
index 0000000..25a77c2
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/CommandBase.java
@@ -0,0 +1,273 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import net.minecraft.server.MinecraftServer;
+
+public abstract class CommandBase implements ICommand {
+ private static IAdminCommand theAdmin = null;
+
+ /**
+ * Return the required permission level for this command.
+ */
+ public int getRequiredPermissionLevel() {
+ return 4;
+ }
+
+ public String getCommandUsage(ICommandSender par1ICommandSender) {
+ return "/" + this.getCommandName();
+ }
+
+ public List getCommandAliases() {
+ return null;
+ }
+
+ /**
+ * Returns true if the given command sender is allowed to use this command.
+ */
+ public boolean canCommandSenderUseCommand(ICommandSender par1ICommandSender) {
+ return par1ICommandSender.canCommandSenderUseCommand(this.getRequiredPermissionLevel(), this.getCommandName());
+ }
+
+ /**
+ * Adds the strings available in this command to the given list of tab
+ * completion options.
+ */
+ public List addTabCompletionOptions(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) {
+ return null;
+ }
+
+ /**
+ * Parses an int from the given string.
+ */
+ public static int parseInt(ICommandSender par0ICommandSender, String par1Str) {
+ try {
+ return Integer.parseInt(par1Str);
+ } catch (NumberFormatException var3) {
+ throw new NumberInvalidException("commands.generic.num.invalid", new Object[] { par1Str });
+ }
+ }
+
+ /**
+ * Parses an int from the given sring with a specified minimum.
+ */
+ public static int parseIntWithMin(ICommandSender par0ICommandSender, String par1Str, int par2) {
+ return parseIntBounded(par0ICommandSender, par1Str, par2, Integer.MAX_VALUE);
+ }
+
+ /**
+ * Parses an int from the given string within a specified bound.
+ */
+ public static int parseIntBounded(ICommandSender par0ICommandSender, String par1Str, int par2, int par3) {
+ int var4 = parseInt(par0ICommandSender, par1Str);
+
+ if (var4 < par2) {
+ throw new NumberInvalidException("commands.generic.num.tooSmall",
+ new Object[] { Integer.valueOf(var4), Integer.valueOf(par2) });
+ } else if (var4 > par3) {
+ throw new NumberInvalidException("commands.generic.num.tooBig",
+ new Object[] { Integer.valueOf(var4), Integer.valueOf(par3) });
+ } else {
+ return var4;
+ }
+ }
+
+ /**
+ * Parses a double from the given string or throws an exception if it's not a
+ * double.
+ */
+ public static double parseDouble(ICommandSender par0ICommandSender, String par1Str) {
+ try {
+ return Double.parseDouble(par1Str);
+ } catch (NumberFormatException var3) {
+ throw new NumberInvalidException("commands.generic.double.invalid", new Object[] { par1Str });
+ }
+ }
+
+ /**
+ * Returns the given ICommandSender as a EntityPlayer or throw an exception.
+ */
+ public static EntityPlayerMP getCommandSenderAsPlayer(ICommandSender par0ICommandSender) {
+ if (par0ICommandSender instanceof EntityPlayerMP) {
+ return (EntityPlayerMP) par0ICommandSender;
+ } else {
+ throw new PlayerNotFoundException("You must specify which player you wish to perform this action on.",
+ new Object[0]);
+ }
+ }
+
+ public static EntityPlayerMP func_82359_c(ICommandSender par0ICommandSender, String par1Str) {
+ EntityPlayerMP var2 = PlayerSelector.matchOnePlayer(par0ICommandSender, par1Str);
+
+ if (var2 != null) {
+ return var2;
+ } else {
+ var2 = MinecraftServer.getServer().getConfigurationManager().getPlayerEntity(par1Str);
+
+ if (var2 == null) {
+ throw new PlayerNotFoundException();
+ } else {
+ return var2;
+ }
+ }
+ }
+
+ public static String func_96332_d(ICommandSender par0ICommandSender, String par1Str) {
+ EntityPlayerMP var2 = PlayerSelector.matchOnePlayer(par0ICommandSender, par1Str);
+
+ if (var2 != null) {
+ return var2.getEntityName();
+ } else if (PlayerSelector.hasArguments(par1Str)) {
+ throw new PlayerNotFoundException();
+ } else {
+ return par1Str;
+ }
+ }
+
+ public static String func_82360_a(ICommandSender par0ICommandSender, String[] par1ArrayOfStr, int par2) {
+ return func_82361_a(par0ICommandSender, par1ArrayOfStr, par2, false);
+ }
+
+ public static String func_82361_a(ICommandSender par0ICommandSender, String[] par1ArrayOfStr, int par2,
+ boolean par3) {
+ StringBuilder var4 = new StringBuilder();
+
+ for (int var5 = par2; var5 < par1ArrayOfStr.length; ++var5) {
+ if (var5 > par2) {
+ var4.append(" ");
+ }
+
+ String var6 = par1ArrayOfStr[var5];
+
+ if (par3) {
+ String var7 = PlayerSelector.matchPlayersAsString(par0ICommandSender, var6);
+
+ if (var7 != null) {
+ var6 = var7;
+ } else if (PlayerSelector.hasArguments(var6)) {
+ throw new PlayerNotFoundException();
+ }
+ }
+
+ var4.append(var6);
+ }
+
+ return var4.toString();
+ }
+
+ /**
+ * Joins the given string array into a "x, y, and z" seperated string.
+ */
+ public static String joinNiceString(Object[] par0ArrayOfObj) {
+ StringBuilder var1 = new StringBuilder();
+
+ for (int var2 = 0; var2 < par0ArrayOfObj.length; ++var2) {
+ String var3 = par0ArrayOfObj[var2].toString();
+
+ if (var2 > 0) {
+ if (var2 == par0ArrayOfObj.length - 1) {
+ var1.append(" and ");
+ } else {
+ var1.append(", ");
+ }
+ }
+
+ var1.append(var3);
+ }
+
+ return var1.toString();
+ }
+
+ public static String func_96333_a(Collection par0Collection) {
+ return joinNiceString(par0Collection.toArray(new String[0]));
+ }
+
+ /**
+ * Returns true if the given substring is exactly equal to the start of the
+ * given string (case insensitive).
+ */
+ public static boolean doesStringStartWith(String par0Str, String par1Str) {
+ return par1Str.regionMatches(true, 0, par0Str, 0, par0Str.length());
+ }
+
+ /**
+ * Returns a List of strings (chosen from the given strings) which the last word
+ * in the given string array is a beginning-match for. (Tab completion).
+ */
+ public static List getListOfStringsMatchingLastWord(String[] par0ArrayOfStr, String... par1ArrayOfStr) {
+ String var2 = par0ArrayOfStr[par0ArrayOfStr.length - 1];
+ ArrayList var3 = new ArrayList();
+ String[] var4 = par1ArrayOfStr;
+ int var5 = par1ArrayOfStr.length;
+
+ for (int var6 = 0; var6 < var5; ++var6) {
+ String var7 = var4[var6];
+
+ if (doesStringStartWith(var2, var7)) {
+ var3.add(var7);
+ }
+ }
+
+ return var3;
+ }
+
+ /**
+ * Returns a List of strings (chosen from the given string iterable) which the
+ * last word in the given string array is a beginning-match for. (Tab
+ * completion).
+ */
+ public static List getListOfStringsFromIterableMatchingLastWord(String[] par0ArrayOfStr, Iterable par1Iterable) {
+ String var2 = par0ArrayOfStr[par0ArrayOfStr.length - 1];
+ ArrayList var3 = new ArrayList();
+ Iterator var4 = par1Iterable.iterator();
+
+ while (var4.hasNext()) {
+ String var5 = (String) var4.next();
+
+ if (doesStringStartWith(var2, var5)) {
+ var3.add(var5);
+ }
+ }
+
+ return var3;
+ }
+
+ /**
+ * Return whether the specified command parameter index is a username parameter.
+ */
+ public boolean isUsernameIndex(String[] par1ArrayOfStr, int par2) {
+ return false;
+ }
+
+ public static void notifyAdmins(ICommandSender par0ICommandSender, String par1Str, Object... par2ArrayOfObj) {
+ notifyAdmins(par0ICommandSender, 0, par1Str, par2ArrayOfObj);
+ }
+
+ public static void notifyAdmins(ICommandSender par0ICommandSender, int par1, String par2Str,
+ Object... par3ArrayOfObj) {
+ if (theAdmin != null) {
+ theAdmin.notifyAdmins(par0ICommandSender, par1, par2Str, par3ArrayOfObj);
+ }
+ }
+
+ /**
+ * Sets the static IAdminCommander.
+ */
+ public static void setAdminCommander(IAdminCommand par0IAdminCommand) {
+ theAdmin = par0IAdminCommand;
+ }
+
+ /**
+ * Compares the name of this command to the name of the given command.
+ */
+ public int compareTo(ICommand par1ICommand) {
+ return this.getCommandName().compareTo(par1ICommand.getCommandName());
+ }
+
+ public int compareTo(Object par1Obj) {
+ return this.compareTo((ICommand) par1Obj);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/CommandClearInventory.java b/sp-server/src/main/java/net/minecraft/src/CommandClearInventory.java
new file mode 100644
index 0000000..cee247a
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/CommandClearInventory.java
@@ -0,0 +1,62 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.minecraft.server.MinecraftServer;
+
+public class CommandClearInventory extends CommandBase {
+ public String getCommandName() {
+ return "clear";
+ }
+
+ public String getCommandUsage(ICommandSender par1ICommandSender) {
+ return par1ICommandSender.translateString("commands.clear.usage", new Object[0]);
+ }
+
+ /**
+ * Return the required permission level for this command.
+ */
+ public int getRequiredPermissionLevel() {
+ return 2;
+ }
+
+ public void processCommand(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) {
+ EntityPlayerMP var3 = par2ArrayOfStr.length == 0 ? getCommandSenderAsPlayer(par1ICommandSender)
+ : func_82359_c(par1ICommandSender, par2ArrayOfStr[0]);
+ int var4 = par2ArrayOfStr.length >= 2 ? parseIntWithMin(par1ICommandSender, par2ArrayOfStr[1], 1) : -1;
+ int var5 = par2ArrayOfStr.length >= 3 ? parseIntWithMin(par1ICommandSender, par2ArrayOfStr[2], 0) : -1;
+ int var6 = var3.inventory.clearInventory(var4, var5);
+ var3.inventoryContainer.detectAndSendChanges();
+
+ if (var6 == 0) {
+ throw new CommandException("commands.clear.failure", new Object[] { var3.getEntityName() });
+ } else {
+ notifyAdmins(par1ICommandSender, "commands.clear.success",
+ new Object[] { var3.getEntityName(), Integer.valueOf(var6) });
+ }
+ }
+
+ /**
+ * Adds the strings available in this command to the given list of tab
+ * completion options.
+ */
+ public List addTabCompletionOptions(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) {
+ return par2ArrayOfStr.length == 1
+ ? getListOfStringsMatchingLastWord(par2ArrayOfStr, this.getAllOnlineUsernames())
+ : null;
+ }
+
+ /**
+ * Return all usernames currently connected to the server.
+ */
+ protected String[] getAllOnlineUsernames() {
+ return MinecraftServer.getServer().getAllUsernames();
+ }
+
+ /**
+ * Return whether the specified command parameter index is a username parameter.
+ */
+ public boolean isUsernameIndex(String[] par1ArrayOfStr, int par2) {
+ return par2 == 0;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/CommandDefaultGameMode.java b/sp-server/src/main/java/net/minecraft/src/CommandDefaultGameMode.java
new file mode 100644
index 0000000..ae889a8
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/CommandDefaultGameMode.java
@@ -0,0 +1,28 @@
+package net.minecraft.src;
+
+import net.minecraft.server.MinecraftServer;
+
+public class CommandDefaultGameMode extends CommandGameMode {
+ public String getCommandName() {
+ return "defaultgamemode";
+ }
+
+ public String getCommandUsage(ICommandSender par1ICommandSender) {
+ return par1ICommandSender.translateString("commands.defaultgamemode.usage", new Object[0]);
+ }
+
+ public void processCommand(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) {
+ if (par2ArrayOfStr.length > 0) {
+ EnumGameType var3 = this.getGameModeFromCommand(par1ICommandSender, par2ArrayOfStr[0]);
+ this.setGameType(var3);
+ String var4 = StatCollector.translateToLocal("gameMode." + var3.getName());
+ notifyAdmins(par1ICommandSender, "commands.defaultgamemode.success", new Object[] { var4 });
+ } else {
+ throw new WrongUsageException("commands.defaultgamemode.usage", new Object[0]);
+ }
+ }
+
+ protected void setGameType(EnumGameType par1EnumGameType) {
+ MinecraftServer.getServer().setGameType(par1EnumGameType);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/CommandDifficulty.java b/sp-server/src/main/java/net/minecraft/src/CommandDifficulty.java
new file mode 100644
index 0000000..44501a3
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/CommandDifficulty.java
@@ -0,0 +1,64 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.minecraft.server.MinecraftServer;
+
+public class CommandDifficulty extends CommandBase {
+ private static final String[] difficulties = new String[] { "options.difficulty.peaceful",
+ "options.difficulty.easy", "options.difficulty.normal", "options.difficulty.hard" };
+
+ public String getCommandName() {
+ return "difficulty";
+ }
+
+ /**
+ * Return the required permission level for this command.
+ */
+ public int getRequiredPermissionLevel() {
+ return 2;
+ }
+
+ public String getCommandUsage(ICommandSender par1ICommandSender) {
+ return par1ICommandSender.translateString("commands.difficulty.usage", new Object[0]);
+ }
+
+ public void processCommand(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) {
+ if (par2ArrayOfStr.length > 0) {
+ int var3 = this.getDifficultyForName(par1ICommandSender, par2ArrayOfStr[0]);
+ MinecraftServer.getServer().setDifficultyForAllWorlds(var3);
+ String var4 = StatCollector.translateToLocal(difficulties[var3]);
+ notifyAdmins(par1ICommandSender, "commands.difficulty.success", new Object[] { var4 });
+ } else {
+ throw new WrongUsageException("commands.difficulty.usage", new Object[0]);
+ }
+ }
+
+ /**
+ * Return the difficulty value for the specified string.
+ */
+ protected int getDifficultyForName(ICommandSender par1ICommandSender, String par2Str) {
+ return !par2Str.equalsIgnoreCase("peaceful")
+ && !par2Str.equalsIgnoreCase("p")
+ ? (!par2Str.equalsIgnoreCase("easy")
+ && !par2Str.equalsIgnoreCase("e")
+ ? (!par2Str.equalsIgnoreCase("normal") && !par2Str.equalsIgnoreCase("n")
+ ? (!par2Str.equalsIgnoreCase("hard") && !par2Str.equalsIgnoreCase("h")
+ ? parseIntBounded(par1ICommandSender, par2Str, 0, 3)
+ : 3)
+ : 2)
+ : 1)
+ : 0;
+ }
+
+ /**
+ * Adds the strings available in this command to the given list of tab
+ * completion options.
+ */
+ public List addTabCompletionOptions(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) {
+ return par2ArrayOfStr.length == 1
+ ? getListOfStringsMatchingLastWord(par2ArrayOfStr,
+ new String[] { "peaceful", "easy", "normal", "hard" })
+ : null;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/CommandEffect.java b/sp-server/src/main/java/net/minecraft/src/CommandEffect.java
new file mode 100644
index 0000000..2edf601
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/CommandEffect.java
@@ -0,0 +1,92 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.minecraft.server.MinecraftServer;
+
+public class CommandEffect extends CommandBase {
+ public String getCommandName() {
+ return "effect";
+ }
+
+ /**
+ * Return the required permission level for this command.
+ */
+ public int getRequiredPermissionLevel() {
+ return 2;
+ }
+
+ public String getCommandUsage(ICommandSender par1ICommandSender) {
+ return par1ICommandSender.translateString("commands.effect.usage", new Object[0]);
+ }
+
+ public void processCommand(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) {
+ if (par2ArrayOfStr.length >= 2) {
+ EntityPlayerMP var3 = func_82359_c(par1ICommandSender, par2ArrayOfStr[0]);
+ int var4 = parseIntWithMin(par1ICommandSender, par2ArrayOfStr[1], 1);
+ int var5 = 600;
+ int var6 = 30;
+ int var7 = 0;
+
+ if (var4 >= 0 && var4 < Potion.potionTypes.length && Potion.potionTypes[var4] != null) {
+ if (par2ArrayOfStr.length >= 3) {
+ var6 = parseIntBounded(par1ICommandSender, par2ArrayOfStr[2], 0, 1000000);
+
+ if (Potion.potionTypes[var4].isInstant()) {
+ var5 = var6;
+ } else {
+ var5 = var6 * 20;
+ }
+ } else if (Potion.potionTypes[var4].isInstant()) {
+ var5 = 1;
+ }
+
+ if (par2ArrayOfStr.length >= 4) {
+ var7 = parseIntBounded(par1ICommandSender, par2ArrayOfStr[3], 0, 255);
+ }
+
+ if (var6 == 0) {
+ if (!var3.isPotionActive(var4)) {
+ throw new CommandException("commands.effect.failure.notActive",
+ new Object[] { StatCollector.translateToLocal(Potion.potionTypes[var4].getName()),
+ var3.getEntityName() });
+ }
+
+ var3.removePotionEffect(var4);
+ notifyAdmins(par1ICommandSender, "commands.effect.success.removed", new Object[] {
+ StatCollector.translateToLocal(Potion.potionTypes[var4].getName()), var3.getEntityName() });
+ } else {
+ PotionEffect var8 = new PotionEffect(var4, var5, var7);
+ var3.addPotionEffect(var8);
+ notifyAdmins(par1ICommandSender, "commands.effect.success",
+ new Object[] { StatCollector.translateToLocal(var8.getEffectName()), Integer.valueOf(var4),
+ Integer.valueOf(var7), var3.getEntityName(), Integer.valueOf(var6) });
+ }
+ } else {
+ throw new NumberInvalidException("commands.effect.notFound", new Object[] { Integer.valueOf(var4) });
+ }
+ } else {
+ throw new WrongUsageException("commands.effect.usage", new Object[0]);
+ }
+ }
+
+ /**
+ * Adds the strings available in this command to the given list of tab
+ * completion options.
+ */
+ public List addTabCompletionOptions(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) {
+ return par2ArrayOfStr.length == 1 ? getListOfStringsMatchingLastWord(par2ArrayOfStr, this.getAllUsernames())
+ : null;
+ }
+
+ protected String[] getAllUsernames() {
+ return MinecraftServer.getServer().getAllUsernames();
+ }
+
+ /**
+ * Return whether the specified command parameter index is a username parameter.
+ */
+ public boolean isUsernameIndex(String[] par1ArrayOfStr, int par2) {
+ return par2 == 0;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/CommandEnchant.java b/sp-server/src/main/java/net/minecraft/src/CommandEnchant.java
new file mode 100644
index 0000000..f4dc016
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/CommandEnchant.java
@@ -0,0 +1,96 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.minecraft.server.MinecraftServer;
+
+public class CommandEnchant extends CommandBase {
+ public String getCommandName() {
+ return "enchant";
+ }
+
+ /**
+ * Return the required permission level for this command.
+ */
+ public int getRequiredPermissionLevel() {
+ return 2;
+ }
+
+ public String getCommandUsage(ICommandSender par1ICommandSender) {
+ return par1ICommandSender.translateString("commands.enchant.usage", new Object[0]);
+ }
+
+ public void processCommand(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) {
+ if (par2ArrayOfStr.length < 2) {
+ throw new WrongUsageException("commands.enchant.usage", new Object[0]);
+ } else {
+ EntityPlayerMP var3 = func_82359_c(par1ICommandSender, par2ArrayOfStr[0]);
+ int var4 = parseIntBounded(par1ICommandSender, par2ArrayOfStr[1], 0,
+ Enchantment.enchantmentsList.length - 1);
+ int var5 = 1;
+ ItemStack var6 = var3.getCurrentEquippedItem();
+
+ if (var6 == null) {
+ notifyAdmins(par1ICommandSender, "commands.enchant.noItem", new Object[0]);
+ } else {
+ Enchantment var7 = Enchantment.enchantmentsList[var4];
+
+ if (var7 == null) {
+ throw new NumberInvalidException("commands.enchant.notFound",
+ new Object[] { Integer.valueOf(var4) });
+ } else if (!var7.func_92089_a(var6)) {
+ notifyAdmins(par1ICommandSender, "commands.enchant.cantEnchant", new Object[0]);
+ } else {
+ if (par2ArrayOfStr.length >= 3) {
+ var5 = parseIntBounded(par1ICommandSender, par2ArrayOfStr[2], var7.getMinLevel(),
+ var7.getMaxLevel());
+ }
+
+ if (var6.hasTagCompound()) {
+ NBTTagList var8 = var6.getEnchantmentTagList();
+
+ if (var8 != null) {
+ for (int var9 = 0; var9 < var8.tagCount(); ++var9) {
+ short var10 = ((NBTTagCompound) var8.tagAt(var9)).getShort("id");
+
+ if (Enchantment.enchantmentsList[var10] != null) {
+ Enchantment var11 = Enchantment.enchantmentsList[var10];
+
+ if (!var11.canApplyTogether(var7)) {
+ notifyAdmins(par1ICommandSender, "commands.enchant.cantCombine",
+ new Object[] { var7.getTranslatedName(var5), var11.getTranslatedName(
+ ((NBTTagCompound) var8.tagAt(var9)).getShort("lvl")) });
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ var6.addEnchantment(var7, var5);
+ notifyAdmins(par1ICommandSender, "commands.enchant.success", new Object[0]);
+ }
+ }
+ }
+ }
+
+ /**
+ * Adds the strings available in this command to the given list of tab
+ * completion options.
+ */
+ public List addTabCompletionOptions(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) {
+ return par2ArrayOfStr.length == 1 ? getListOfStringsMatchingLastWord(par2ArrayOfStr, this.getListOfPlayers())
+ : null;
+ }
+
+ protected String[] getListOfPlayers() {
+ return MinecraftServer.getServer().getAllUsernames();
+ }
+
+ /**
+ * Return whether the specified command parameter index is a username parameter.
+ */
+ public boolean isUsernameIndex(String[] par1ArrayOfStr, int par2) {
+ return par2 == 0;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/CommandException.java b/sp-server/src/main/java/net/minecraft/src/CommandException.java
new file mode 100644
index 0000000..3e6b25a
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/CommandException.java
@@ -0,0 +1,14 @@
+package net.minecraft.src;
+
+public class CommandException extends RuntimeException {
+ private Object[] errorObjects;
+
+ public CommandException(String par1Str, Object... par2ArrayOfObj) {
+ super(par1Str);
+ this.errorObjects = par2ArrayOfObj;
+ }
+
+ public Object[] getErrorOjbects() {
+ return this.errorObjects;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/CommandGameMode.java b/sp-server/src/main/java/net/minecraft/src/CommandGameMode.java
new file mode 100644
index 0000000..c6a6a6d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/CommandGameMode.java
@@ -0,0 +1,82 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.minecraft.server.MinecraftServer;
+
+public class CommandGameMode extends CommandBase {
+ public String getCommandName() {
+ return "gamemode";
+ }
+
+ /**
+ * Return the required permission level for this command.
+ */
+ public int getRequiredPermissionLevel() {
+ return 2;
+ }
+
+ public String getCommandUsage(ICommandSender par1ICommandSender) {
+ return par1ICommandSender.translateString("commands.gamemode.usage", new Object[0]);
+ }
+
+ public void processCommand(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) {
+ if (par2ArrayOfStr.length > 0) {
+ EnumGameType var3 = this.getGameModeFromCommand(par1ICommandSender, par2ArrayOfStr[0]);
+ EntityPlayerMP var4 = par2ArrayOfStr.length >= 2 ? func_82359_c(par1ICommandSender, par2ArrayOfStr[1])
+ : getCommandSenderAsPlayer(par1ICommandSender);
+ var4.setGameType(var3);
+ var4.fallDistance = 0.0F;
+ String var5 = StatCollector.translateToLocal("gameMode." + var3.getName());
+
+ if (var4 != par1ICommandSender) {
+ notifyAdmins(par1ICommandSender, 1, "commands.gamemode.success.other",
+ new Object[] { var4.getEntityName(), var5 });
+ } else {
+ notifyAdmins(par1ICommandSender, 1, "commands.gamemode.success.self", new Object[] { var5 });
+ }
+ } else {
+ throw new WrongUsageException("commands.gamemode.usage", new Object[0]);
+ }
+ }
+
+ /**
+ * Gets the Game Mode specified in the command.
+ */
+ protected EnumGameType getGameModeFromCommand(ICommandSender par1ICommandSender, String par2Str) {
+ return !par2Str.equalsIgnoreCase(EnumGameType.SURVIVAL.getName()) && !par2Str.equalsIgnoreCase("s")
+ ? (!par2Str.equalsIgnoreCase(EnumGameType.CREATIVE.getName()) && !par2Str.equalsIgnoreCase("c")
+ ? (!par2Str.equalsIgnoreCase(EnumGameType.ADVENTURE.getName()) && !par2Str.equalsIgnoreCase("a")
+ ? WorldSettings.getGameTypeById(parseIntBounded(par1ICommandSender, par2Str, 0,
+ EnumGameType.values().length - 2))
+ : EnumGameType.ADVENTURE)
+ : EnumGameType.CREATIVE)
+ : EnumGameType.SURVIVAL;
+ }
+
+ /**
+ * Adds the strings available in this command to the given list of tab
+ * completion options.
+ */
+ public List addTabCompletionOptions(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) {
+ return par2ArrayOfStr.length == 1
+ ? getListOfStringsMatchingLastWord(par2ArrayOfStr, new String[] { "survival", "creative", "adventure" })
+ : (par2ArrayOfStr.length == 2
+ ? getListOfStringsMatchingLastWord(par2ArrayOfStr, this.getListOfPlayerUsernames())
+ : null);
+ }
+
+ /**
+ * Returns String array containing all player usernames in the server.
+ */
+ protected String[] getListOfPlayerUsernames() {
+ return MinecraftServer.getServer().getAllUsernames();
+ }
+
+ /**
+ * Return whether the specified command parameter index is a username parameter.
+ */
+ public boolean isUsernameIndex(String[] par1ArrayOfStr, int par2) {
+ return par2 == 1;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/CommandGameRule.java b/sp-server/src/main/java/net/minecraft/src/CommandGameRule.java
new file mode 100644
index 0000000..36cece6
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/CommandGameRule.java
@@ -0,0 +1,73 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.minecraft.server.MinecraftServer;
+
+public class CommandGameRule extends CommandBase {
+ public String getCommandName() {
+ return "gamerule";
+ }
+
+ /**
+ * Return the required permission level for this command.
+ */
+ public int getRequiredPermissionLevel() {
+ return 2;
+ }
+
+ public String getCommandUsage(ICommandSender par1ICommandSender) {
+ return par1ICommandSender.translateString("commands.gamerule.usage", new Object[0]);
+ }
+
+ public void processCommand(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) {
+ String var6;
+
+ if (par2ArrayOfStr.length == 2) {
+ var6 = par2ArrayOfStr[0];
+ String var7 = par2ArrayOfStr[1];
+ GameRules var8 = this.getGameRules();
+
+ if (var8.hasRule(var6)) {
+ var8.setOrCreateGameRule(var6, var7);
+ notifyAdmins(par1ICommandSender, "commands.gamerule.success", new Object[0]);
+ } else {
+ notifyAdmins(par1ICommandSender, "commands.gamerule.norule", new Object[] { var6 });
+ }
+ } else if (par2ArrayOfStr.length == 1) {
+ var6 = par2ArrayOfStr[0];
+ GameRules var4 = this.getGameRules();
+
+ if (var4.hasRule(var6)) {
+ String var5 = var4.getGameRuleStringValue(var6);
+ par1ICommandSender.sendChatToPlayer(var6 + " = " + var5);
+ } else {
+ notifyAdmins(par1ICommandSender, "commands.gamerule.norule", new Object[] { var6 });
+ }
+ } else if (par2ArrayOfStr.length == 0) {
+ GameRules var3 = this.getGameRules();
+ par1ICommandSender.sendChatToPlayer(joinNiceString(var3.getRules()));
+ } else {
+ throw new WrongUsageException("commands.gamerule.usage", new Object[0]);
+ }
+ }
+
+ /**
+ * Adds the strings available in this command to the given list of tab
+ * completion options.
+ */
+ public List addTabCompletionOptions(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) {
+ return par2ArrayOfStr.length == 1
+ ? getListOfStringsMatchingLastWord(par2ArrayOfStr, this.getGameRules().getRules())
+ : (par2ArrayOfStr.length == 2
+ ? getListOfStringsMatchingLastWord(par2ArrayOfStr, new String[] { "true", "false" })
+ : null);
+ }
+
+ /**
+ * Return the game rule set this command should be able to manipulate.
+ */
+ private GameRules getGameRules() {
+ return MinecraftServer.getServer().worldServerForDimension(0).getGameRules();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/CommandGive.java b/sp-server/src/main/java/net/minecraft/src/CommandGive.java
new file mode 100644
index 0000000..4da55ca
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/CommandGive.java
@@ -0,0 +1,71 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.minecraft.server.MinecraftServer;
+
+public class CommandGive extends CommandBase {
+ public String getCommandName() {
+ return "give";
+ }
+
+ /**
+ * Return the required permission level for this command.
+ */
+ public int getRequiredPermissionLevel() {
+ return 2;
+ }
+
+ public String getCommandUsage(ICommandSender par1ICommandSender) {
+ return par1ICommandSender.translateString("commands.give.usage", new Object[0]);
+ }
+
+ public void processCommand(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) {
+ if (par2ArrayOfStr.length >= 2) {
+ EntityPlayerMP var3 = func_82359_c(par1ICommandSender, par2ArrayOfStr[0]);
+ int var4 = parseIntWithMin(par1ICommandSender, par2ArrayOfStr[1], 1);
+ int var5 = 1;
+ int var6 = 0;
+
+ if (Item.itemsList[var4] == null) {
+ throw new NumberInvalidException("commands.give.notFound", new Object[] { Integer.valueOf(var4) });
+ } else {
+ if (par2ArrayOfStr.length >= 3) {
+ var5 = parseIntBounded(par1ICommandSender, par2ArrayOfStr[2], 1, 64);
+ }
+
+ if (par2ArrayOfStr.length >= 4) {
+ var6 = parseInt(par1ICommandSender, par2ArrayOfStr[3]);
+ }
+
+ ItemStack var7 = new ItemStack(var4, var5, var6);
+ EntityItem var8 = var3.dropPlayerItem(var7);
+ var8.delayBeforeCanPickup = 0;
+ notifyAdmins(par1ICommandSender, "commands.give.success",
+ new Object[] { Item.itemsList[var4].func_77653_i(var7), Integer.valueOf(var4),
+ Integer.valueOf(var5), var3.getEntityName() });
+ }
+ } else {
+ throw new WrongUsageException("commands.give.usage", new Object[0]);
+ }
+ }
+
+ /**
+ * Adds the strings available in this command to the given list of tab
+ * completion options.
+ */
+ public List addTabCompletionOptions(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) {
+ return par2ArrayOfStr.length == 1 ? getListOfStringsMatchingLastWord(par2ArrayOfStr, this.getPlayers()) : null;
+ }
+
+ protected String[] getPlayers() {
+ return MinecraftServer.getServer().getAllUsernames();
+ }
+
+ /**
+ * Return whether the specified command parameter index is a username parameter.
+ */
+ public boolean isUsernameIndex(String[] par1ArrayOfStr, int par2) {
+ return par2 == 0;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/CommandHandler.java b/sp-server/src/main/java/net/minecraft/src/CommandHandler.java
new file mode 100644
index 0000000..38ea583
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/CommandHandler.java
@@ -0,0 +1,200 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+public class CommandHandler implements ICommandManager {
+ /** Map of Strings to the ICommand objects they represent */
+ private final Map commandMap = new HashMap();
+
+ /** The set of ICommand objects currently loaded. */
+ private final Set commandSet = new HashSet();
+
+ public int executeCommand(ICommandSender par1ICommandSender, String par2Str) {
+ par2Str = par2Str.trim();
+
+ if (par2Str.startsWith("/")) {
+ par2Str = par2Str.substring(1);
+ }
+
+ String[] var3 = par2Str.split(" ");
+ String var4 = var3[0];
+ var3 = dropFirstString(var3);
+ ICommand var5 = (ICommand) this.commandMap.get(var4);
+ int var6 = this.getUsernameIndex(var5, var3);
+ int var7 = 0;
+
+ try {
+ if (var5 == null) {
+ throw new CommandNotFoundException();
+ }
+
+ if (var5.canCommandSenderUseCommand(par1ICommandSender)) {
+ if (var6 > -1) {
+ EntityPlayerMP[] var8 = PlayerSelector.matchPlayers(par1ICommandSender, var3[var6]);
+ String var9 = var3[var6];
+ EntityPlayerMP[] var10 = var8;
+ int var11 = var8.length;
+
+ for (int var12 = 0; var12 < var11; ++var12) {
+ EntityPlayerMP var13 = var10[var12];
+ var3[var6] = var13.getEntityName();
+
+ try {
+ var5.processCommand(par1ICommandSender, var3);
+ ++var7;
+ } catch (CommandException var15) {
+ par1ICommandSender.sendChatToPlayer(EnumChatFormatting.RED
+ + par1ICommandSender.translateString(var15.getMessage(), var15.getErrorOjbects()));
+ }
+ }
+
+ var3[var6] = var9;
+ } else {
+ var5.processCommand(par1ICommandSender, var3);
+ ++var7;
+ }
+ } else {
+ par1ICommandSender.sendChatToPlayer(
+ "" + EnumChatFormatting.RED + "You do not have permission to use this command.");
+ }
+ } catch (WrongUsageException var16) {
+ par1ICommandSender.sendChatToPlayer(EnumChatFormatting.RED + par1ICommandSender.translateString(
+ "commands.generic.usage",
+ new Object[] { par1ICommandSender.translateString(var16.getMessage(), var16.getErrorOjbects()) }));
+ } catch (CommandException var17) {
+ par1ICommandSender.sendChatToPlayer(EnumChatFormatting.RED
+ + par1ICommandSender.translateString(var17.getMessage(), var17.getErrorOjbects()));
+ } catch (Throwable var18) {
+ par1ICommandSender.sendChatToPlayer(EnumChatFormatting.RED
+ + par1ICommandSender.translateString("commands.generic.exception", new Object[0]));
+ var18.printStackTrace();
+ }
+
+ return var7;
+ }
+
+ /**
+ * adds the command and any aliases it has to the internal map of available
+ * commands
+ */
+ public ICommand registerCommand(ICommand par1ICommand) {
+ List var2 = par1ICommand.getCommandAliases();
+ this.commandMap.put(par1ICommand.getCommandName(), par1ICommand);
+ this.commandSet.add(par1ICommand);
+
+ if (var2 != null) {
+ Iterator var3 = var2.iterator();
+
+ while (var3.hasNext()) {
+ String var4 = (String) var3.next();
+ ICommand var5 = (ICommand) this.commandMap.get(var4);
+
+ if (var5 == null || !var5.getCommandName().equals(var4)) {
+ this.commandMap.put(var4, par1ICommand);
+ }
+ }
+ }
+
+ return par1ICommand;
+ }
+
+ /**
+ * creates a new array and sets elements 0..n-2 to be 0..n-1 of the input (n
+ * elements)
+ */
+ private static String[] dropFirstString(String[] par0ArrayOfStr) {
+ String[] var1 = new String[par0ArrayOfStr.length - 1];
+
+ for (int var2 = 1; var2 < par0ArrayOfStr.length; ++var2) {
+ var1[var2 - 1] = par0ArrayOfStr[var2];
+ }
+
+ return var1;
+ }
+
+ /**
+ * Performs a "begins with" string match on each token in par2. Only returns
+ * commands that par1 can use.
+ */
+ public List getPossibleCommands(ICommandSender par1ICommandSender, String par2Str) {
+ String[] var3 = par2Str.split(" ", -1);
+ String var4 = var3[0];
+
+ if (var3.length == 1) {
+ ArrayList var8 = new ArrayList();
+ Iterator var6 = this.commandMap.entrySet().iterator();
+
+ while (var6.hasNext()) {
+ Entry var7 = (Entry) var6.next();
+
+ if (CommandBase.doesStringStartWith(var4, (String) var7.getKey())
+ && ((ICommand) var7.getValue()).canCommandSenderUseCommand(par1ICommandSender)) {
+ var8.add(var7.getKey());
+ }
+ }
+
+ return var8;
+ } else {
+ if (var3.length > 1) {
+ ICommand var5 = (ICommand) this.commandMap.get(var4);
+
+ if (var5 != null) {
+ return var5.addTabCompletionOptions(par1ICommandSender, dropFirstString(var3));
+ }
+ }
+
+ return null;
+ }
+ }
+
+ /**
+ * returns all commands that the commandSender can use
+ */
+ public List getPossibleCommands(ICommandSender par1ICommandSender) {
+ ArrayList var2 = new ArrayList();
+ Iterator var3 = this.commandSet.iterator();
+
+ while (var3.hasNext()) {
+ ICommand var4 = (ICommand) var3.next();
+
+ if (var4.canCommandSenderUseCommand(par1ICommandSender)) {
+ var2.add(var4);
+ }
+ }
+
+ return var2;
+ }
+
+ /**
+ * returns a map of string to commads. All commands are returned, not just ones
+ * which someone has permission to use.
+ */
+ public Map getCommands() {
+ return this.commandMap;
+ }
+
+ /**
+ * Return a command's first parameter index containing a valid username.
+ */
+ private int getUsernameIndex(ICommand par1ICommand, String[] par2ArrayOfStr) {
+ if (par1ICommand == null) {
+ return -1;
+ } else {
+ for (int var3 = 0; var3 < par2ArrayOfStr.length; ++var3) {
+ if (par1ICommand.isUsernameIndex(par2ArrayOfStr, var3)
+ && PlayerSelector.matchesMultiplePlayers(par2ArrayOfStr[var3])) {
+ return var3;
+ }
+ }
+
+ return -1;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/CommandHelp.java b/sp-server/src/main/java/net/minecraft/src/CommandHelp.java
new file mode 100644
index 0000000..898193f
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/CommandHelp.java
@@ -0,0 +1,79 @@
+package net.minecraft.src;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import net.minecraft.server.MinecraftServer;
+
+public class CommandHelp extends CommandBase {
+ public String getCommandName() {
+ return "help";
+ }
+
+ /**
+ * Return the required permission level for this command.
+ */
+ public int getRequiredPermissionLevel() {
+ return 0;
+ }
+
+ public String getCommandUsage(ICommandSender par1ICommandSender) {
+ return par1ICommandSender.translateString("commands.help.usage", new Object[0]);
+ }
+
+ public List getCommandAliases() {
+ return Arrays.asList(new String[] { "?" });
+ }
+
+ public void processCommand(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) {
+ List var3 = this.getSortedPossibleCommands(par1ICommandSender);
+ byte var4 = 7;
+ int var5 = (var3.size() - 1) / var4;
+ boolean var6 = false;
+ ICommand var9;
+ int var11;
+
+ try {
+ var11 = par2ArrayOfStr.length == 0 ? 0
+ : parseIntBounded(par1ICommandSender, par2ArrayOfStr[0], 1, var5 + 1) - 1;
+ } catch (NumberInvalidException var10) {
+ Map var8 = this.getCommands();
+ var9 = (ICommand) var8.get(par2ArrayOfStr[0]);
+
+ if (var9 != null) {
+ throw new WrongUsageException(var9.getCommandUsage(par1ICommandSender), new Object[0]);
+ }
+
+ throw new CommandNotFoundException();
+ }
+
+ int var7 = Math.min((var11 + 1) * var4, var3.size());
+ par1ICommandSender.sendChatToPlayer(EnumChatFormatting.DARK_GREEN + par1ICommandSender.translateString(
+ "commands.help.header", new Object[] { Integer.valueOf(var11 + 1), Integer.valueOf(var5 + 1) }));
+
+ for (int var12 = var11 * var4; var12 < var7; ++var12) {
+ var9 = (ICommand) var3.get(var12);
+ par1ICommandSender.sendChatToPlayer(var9.getCommandUsage(par1ICommandSender));
+ }
+
+ if (var11 == 0 && par1ICommandSender instanceof EntityPlayer) {
+ par1ICommandSender.sendChatToPlayer(EnumChatFormatting.GREEN
+ + par1ICommandSender.translateString("commands.help.footer", new Object[0]));
+ }
+ }
+
+ /**
+ * Returns a sorted list of all possible commands for the given ICommandSender.
+ */
+ protected List getSortedPossibleCommands(ICommandSender par1ICommandSender) {
+ List var2 = MinecraftServer.getServer().getCommandManager().getPossibleCommands(par1ICommandSender);
+ Collections.sort(var2);
+ return var2;
+ }
+
+ protected Map getCommands() {
+ return MinecraftServer.getServer().getCommandManager().getCommands();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/CommandKick.java b/sp-server/src/main/java/net/minecraft/src/CommandKick.java
new file mode 100644
index 0000000..5fe8aab
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/CommandKick.java
@@ -0,0 +1,35 @@
+package net.minecraft.src;
+
+public class CommandKick extends CommandBase {
+ public String getCommandName() {
+ return "kick";
+ }
+
+ /**
+ * Return the required permission level for this command.
+ */
+ public int getRequiredPermissionLevel() {
+ return 2;
+ }
+
+ public void processCommand(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) {
+ if (par2ArrayOfStr.length == 0) {
+ throw new WrongUsageException("commands.kick.usage", new Object[0]);
+ }
+ EntityPlayerMP target = func_82359_c(par1ICommandSender, par2ArrayOfStr[0]);
+ if (target.mcServer.getServerOwner().equals(target.username)) {
+ throw new SyntaxErrorException("commands.kick.owner", new Object[0]);
+ }
+ if (par2ArrayOfStr.length == 1) {
+ target.playerNetServerHandler.kickPlayer("Kicked.");
+ notifyAdmins(par1ICommandSender, "commands.kick.success",
+ new Object[] { target.getEntityName() });
+ } else {
+ String message = String.join(" ", par2ArrayOfStr);
+ message = message.substring(message.indexOf(' ') + 1).trim();
+ target.playerNetServerHandler.kickPlayer(message);
+ notifyAdmins(par1ICommandSender, "commands.kick.success.reason",
+ new Object[] { target.getEntityName(), message });
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/CommandKill.java b/sp-server/src/main/java/net/minecraft/src/CommandKill.java
new file mode 100644
index 0000000..e4c0b8f
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/CommandKill.java
@@ -0,0 +1,20 @@
+package net.minecraft.src;
+
+public class CommandKill extends CommandBase {
+ public String getCommandName() {
+ return "kill";
+ }
+
+ /**
+ * Return the required permission level for this command.
+ */
+ public int getRequiredPermissionLevel() {
+ return 0;
+ }
+
+ public void processCommand(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) {
+ EntityPlayerMP var3 = getCommandSenderAsPlayer(par1ICommandSender);
+ var3.attackEntityFrom(DamageSource.outOfWorld, 1000);
+ par1ICommandSender.sendChatToPlayer("Ouch. That looks like it hurt.");
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/CommandNotFoundException.java b/sp-server/src/main/java/net/minecraft/src/CommandNotFoundException.java
new file mode 100644
index 0000000..f2d4be0
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/CommandNotFoundException.java
@@ -0,0 +1,11 @@
+package net.minecraft.src;
+
+public class CommandNotFoundException extends CommandException {
+ public CommandNotFoundException() {
+ this("commands.generic.notFound", new Object[0]);
+ }
+
+ public CommandNotFoundException(String par1Str, Object... par2ArrayOfObj) {
+ super(par1Str, par2ArrayOfObj);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/CommandServerEmote.java b/sp-server/src/main/java/net/minecraft/src/CommandServerEmote.java
new file mode 100644
index 0000000..5ae8502
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/CommandServerEmote.java
@@ -0,0 +1,41 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.minecraft.server.MinecraftServer;
+
+public class CommandServerEmote extends CommandBase {
+ public String getCommandName() {
+ return "me";
+ }
+
+ /**
+ * Return the required permission level for this command.
+ */
+ public int getRequiredPermissionLevel() {
+ return 0;
+ }
+
+ public String getCommandUsage(ICommandSender par1ICommandSender) {
+ return par1ICommandSender.translateString("commands.me.usage", new Object[0]);
+ }
+
+ public void processCommand(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) {
+ if (par2ArrayOfStr.length > 0) {
+ String var3 = func_82361_a(par1ICommandSender, par2ArrayOfStr, 0,
+ par1ICommandSender.canCommandSenderUseCommand(1, "me"));
+ MinecraftServer.getServer().getConfigurationManager().sendPacketToAllPlayers(
+ new Packet3Chat("* " + par1ICommandSender.getCommandSenderName() + " " + var3));
+ } else {
+ throw new WrongUsageException("commands.me.usage", new Object[0]);
+ }
+ }
+
+ /**
+ * Adds the strings available in this command to the given list of tab
+ * completion options.
+ */
+ public List addTabCompletionOptions(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) {
+ return getListOfStringsMatchingLastWord(par2ArrayOfStr, MinecraftServer.getServer().getAllUsernames());
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/CommandServerMessage.java b/sp-server/src/main/java/net/minecraft/src/CommandServerMessage.java
new file mode 100644
index 0000000..35c18e2
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/CommandServerMessage.java
@@ -0,0 +1,61 @@
+package net.minecraft.src;
+
+import java.util.Arrays;
+import java.util.List;
+
+import net.minecraft.server.MinecraftServer;
+
+public class CommandServerMessage extends CommandBase {
+ public List getCommandAliases() {
+ return Arrays.asList(new String[] { "w", "msg" });
+ }
+
+ public String getCommandName() {
+ return "tell";
+ }
+
+ /**
+ * Return the required permission level for this command.
+ */
+ public int getRequiredPermissionLevel() {
+ return 0;
+ }
+
+ public void processCommand(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) {
+ if (par2ArrayOfStr.length < 2) {
+ throw new WrongUsageException("commands.message.usage", new Object[0]);
+ } else {
+ EntityPlayerMP var3 = func_82359_c(par1ICommandSender, par2ArrayOfStr[0]);
+
+ if (var3 == null) {
+ throw new PlayerNotFoundException();
+ } else if (var3 == par1ICommandSender) {
+ throw new PlayerNotFoundException("commands.message.sameTarget", new Object[0]);
+ } else {
+ String var4 = func_82361_a(par1ICommandSender, par2ArrayOfStr, 1,
+ !(par1ICommandSender instanceof EntityPlayer));
+ var3.sendChatToPlayer(EnumChatFormatting.GRAY + "" + EnumChatFormatting.ITALIC
+ + var3.translateString("commands.message.display.incoming",
+ new Object[] { par1ICommandSender.getCommandSenderName(), var4 }));
+ par1ICommandSender.sendChatToPlayer(EnumChatFormatting.GRAY + "" + EnumChatFormatting.ITALIC
+ + par1ICommandSender.translateString("commands.message.display.outgoing",
+ new Object[] { var3.getCommandSenderName(), var4 }));
+ }
+ }
+ }
+
+ /**
+ * Adds the strings available in this command to the given list of tab
+ * completion options.
+ */
+ public List addTabCompletionOptions(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) {
+ return getListOfStringsMatchingLastWord(par2ArrayOfStr, MinecraftServer.getServer().getAllUsernames());
+ }
+
+ /**
+ * Return whether the specified command parameter index is a username parameter.
+ */
+ public boolean isUsernameIndex(String[] par1ArrayOfStr, int par2) {
+ return par2 == 0;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/CommandServerSay.java b/sp-server/src/main/java/net/minecraft/src/CommandServerSay.java
new file mode 100644
index 0000000..7351f02
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/CommandServerSay.java
@@ -0,0 +1,42 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.minecraft.server.MinecraftServer;
+
+public class CommandServerSay extends CommandBase {
+ public String getCommandName() {
+ return "say";
+ }
+
+ /**
+ * Return the required permission level for this command.
+ */
+ public int getRequiredPermissionLevel() {
+ return 1;
+ }
+
+ public String getCommandUsage(ICommandSender par1ICommandSender) {
+ return par1ICommandSender.translateString("commands.say.usage", new Object[0]);
+ }
+
+ public void processCommand(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) {
+ if (par2ArrayOfStr.length > 0 && par2ArrayOfStr[0].length() > 0) {
+ String var3 = func_82361_a(par1ICommandSender, par2ArrayOfStr, 0, true);
+ MinecraftServer.getServer().getConfigurationManager().sendChatMsg(
+ String.format("[%s] %s", new Object[] { par1ICommandSender.getCommandSenderName(), var3 }));
+ } else {
+ throw new WrongUsageException("commands.say.usage", new Object[0]);
+ }
+ }
+
+ /**
+ * Adds the strings available in this command to the given list of tab
+ * completion options.
+ */
+ public List addTabCompletionOptions(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) {
+ return par2ArrayOfStr.length >= 1
+ ? getListOfStringsMatchingLastWord(par2ArrayOfStr, MinecraftServer.getServer().getAllUsernames())
+ : null;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/CommandServerTp.java b/sp-server/src/main/java/net/minecraft/src/CommandServerTp.java
new file mode 100644
index 0000000..15e8d7b
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/CommandServerTp.java
@@ -0,0 +1,129 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.minecraft.server.MinecraftServer;
+
+public class CommandServerTp extends CommandBase {
+ public String getCommandName() {
+ return "tp";
+ }
+
+ /**
+ * Return the required permission level for this command.
+ */
+ public int getRequiredPermissionLevel() {
+ return 2;
+ }
+
+ public String getCommandUsage(ICommandSender par1ICommandSender) {
+ return par1ICommandSender.translateString("commands.tp.usage", new Object[0]);
+ }
+
+ public void processCommand(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) {
+ if (par2ArrayOfStr.length < 1) {
+ throw new WrongUsageException("commands.tp.usage", new Object[0]);
+ } else {
+ EntityPlayerMP var3;
+
+ if (par2ArrayOfStr.length != 2 && par2ArrayOfStr.length != 4) {
+ var3 = getCommandSenderAsPlayer(par1ICommandSender);
+ } else {
+ var3 = func_82359_c(par1ICommandSender, par2ArrayOfStr[0]);
+
+ if (var3 == null) {
+ throw new PlayerNotFoundException();
+ }
+ }
+
+ if (par2ArrayOfStr.length != 3 && par2ArrayOfStr.length != 4) {
+ if (par2ArrayOfStr.length == 1 || par2ArrayOfStr.length == 2) {
+ EntityPlayerMP var11 = func_82359_c(par1ICommandSender, par2ArrayOfStr[par2ArrayOfStr.length - 1]);
+
+ if (var11 == null) {
+ throw new PlayerNotFoundException();
+ }
+
+ // var3.mountEntity((Entity) null);
+
+ if (var11.worldObj != var3.worldObj) {
+ notifyAdmins(par1ICommandSender, "commands.tp.notSameDimension", new Object[0]);
+ return;
+ // var3.mcServer.getConfigurationManager().transferPlayerToDimension(var3, var11.dimension);
+ // var3.playerNetServerHandler.playerEntity = var3.mcServer.getConfigurationManager().recreatePlayerEntity(var3, var11.dimension, true, false);
+ // var3 = var3.playerNetServerHandler.playerEntity;
+ }
+
+ var3.mountEntity((Entity) null);
+
+ var3.playerNetServerHandler.setPlayerLocation(var11.posX, var11.posY, var11.posZ, var11.rotationYaw,
+ var11.rotationPitch);
+ notifyAdmins(par1ICommandSender, "commands.tp.success",
+ new Object[] { var3.getEntityName(), var11.getEntityName() });
+ }
+ } else if (var3.worldObj != null) {
+ int var4 = par2ArrayOfStr.length - 3;
+ double var5 = this.func_82368_a(par1ICommandSender, var3.posX, par2ArrayOfStr[var4++]);
+ double var7 = this.func_82367_a(par1ICommandSender, var3.posY, par2ArrayOfStr[var4++], 0, 0);
+ double var9 = this.func_82368_a(par1ICommandSender, var3.posZ, par2ArrayOfStr[var4++]);
+ var3.mountEntity((Entity) null);
+ var3.setPositionAndUpdate(var5, var7, var9);
+ notifyAdmins(par1ICommandSender, "commands.tp.success.coordinates", new Object[] { var3.getEntityName(),
+ Double.valueOf(var5), Double.valueOf(var7), Double.valueOf(var9) });
+ }
+ }
+ }
+
+ private double func_82368_a(ICommandSender par1ICommandSender, double par2, String par4Str) {
+ return this.func_82367_a(par1ICommandSender, par2, par4Str, -30000000, 30000000);
+ }
+
+ private double func_82367_a(ICommandSender par1ICommandSender, double par2, String par4Str, int par5, int par6) {
+ boolean var7 = par4Str.startsWith("~");
+ double var8 = var7 ? par2 : 0.0D;
+
+ if (!var7 || par4Str.length() > 1) {
+ boolean var10 = par4Str.contains(".");
+
+ if (var7) {
+ par4Str = par4Str.substring(1);
+ }
+
+ var8 += parseDouble(par1ICommandSender, par4Str);
+
+ if (!var10 && !var7) {
+ var8 += 0.5D;
+ }
+ }
+
+ if (par5 != 0 || par6 != 0) {
+ if (var8 < (double) par5) {
+ throw new NumberInvalidException("commands.generic.double.tooSmall",
+ new Object[] { Double.valueOf(var8), Integer.valueOf(par5) });
+ }
+
+ if (var8 > (double) par6) {
+ throw new NumberInvalidException("commands.generic.double.tooBig",
+ new Object[] { Double.valueOf(var8), Integer.valueOf(par6) });
+ }
+ }
+
+ return var8;
+ }
+
+ /**
+ * Adds the strings available in this command to the given list of tab
+ * completion options.
+ */
+ public List addTabCompletionOptions(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) {
+ return par2ArrayOfStr.length != 1 && par2ArrayOfStr.length != 2 ? null
+ : getListOfStringsMatchingLastWord(par2ArrayOfStr, MinecraftServer.getServer().getAllUsernames());
+ }
+
+ /**
+ * Return whether the specified command parameter index is a username parameter.
+ */
+ public boolean isUsernameIndex(String[] par1ArrayOfStr, int par2) {
+ return par2 == 0;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/CommandSetSpawnpoint.java b/sp-server/src/main/java/net/minecraft/src/CommandSetSpawnpoint.java
new file mode 100644
index 0000000..89ba9fd
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/CommandSetSpawnpoint.java
@@ -0,0 +1,66 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.minecraft.server.MinecraftServer;
+
+public class CommandSetSpawnpoint extends CommandBase {
+ public String getCommandName() {
+ return "spawnpoint";
+ }
+
+ /**
+ * Return the required permission level for this command.
+ */
+ public int getRequiredPermissionLevel() {
+ return 2;
+ }
+
+ public String getCommandUsage(ICommandSender par1ICommandSender) {
+ return par1ICommandSender.translateString("commands.spawnpoint.usage", new Object[0]);
+ }
+
+ public void processCommand(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) {
+ EntityPlayerMP var3 = par2ArrayOfStr.length == 0 ? getCommandSenderAsPlayer(par1ICommandSender)
+ : func_82359_c(par1ICommandSender, par2ArrayOfStr[0]);
+
+ if (par2ArrayOfStr.length == 4) {
+ if (var3.worldObj != null) {
+ byte var4 = 1;
+ int var5 = 30000000;
+ int var9 = var4 + 1;
+ int var6 = parseIntBounded(par1ICommandSender, par2ArrayOfStr[var4], -var5, var5);
+ int var7 = parseIntBounded(par1ICommandSender, par2ArrayOfStr[var9++], 0, 256);
+ int var8 = parseIntBounded(par1ICommandSender, par2ArrayOfStr[var9++], -var5, var5);
+ var3.setSpawnChunk(new ChunkCoordinates(var6, var7, var8), true);
+ notifyAdmins(par1ICommandSender, "commands.spawnpoint.success", new Object[] { var3.getEntityName(),
+ Integer.valueOf(var6), Integer.valueOf(var7), Integer.valueOf(var8) });
+ }
+ } else {
+ if (par2ArrayOfStr.length > 1) {
+ throw new WrongUsageException("commands.spawnpoint.usage", new Object[0]);
+ }
+
+ ChunkCoordinates var10 = var3.getCommandSenderPosition();
+ var3.setSpawnChunk(var10, true);
+ notifyAdmins(par1ICommandSender, "commands.spawnpoint.success", new Object[] { var3.getEntityName(),
+ Integer.valueOf(var10.posX), Integer.valueOf(var10.posY), Integer.valueOf(var10.posZ) });
+ }
+ }
+
+ /**
+ * Adds the strings available in this command to the given list of tab
+ * completion options.
+ */
+ public List addTabCompletionOptions(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) {
+ return par2ArrayOfStr.length != 1 && par2ArrayOfStr.length != 2 ? null
+ : getListOfStringsMatchingLastWord(par2ArrayOfStr, MinecraftServer.getServer().getAllUsernames());
+ }
+
+ /**
+ * Return whether the specified command parameter index is a username parameter.
+ */
+ public boolean isUsernameIndex(String[] par1ArrayOfStr, int par2) {
+ return par2 == 0;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/CommandShowSeed.java b/sp-server/src/main/java/net/minecraft/src/CommandShowSeed.java
new file mode 100644
index 0000000..6b3af28
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/CommandShowSeed.java
@@ -0,0 +1,29 @@
+package net.minecraft.src;
+
+import net.minecraft.server.MinecraftServer;
+
+public class CommandShowSeed extends CommandBase {
+ /**
+ * Returns true if the given command sender is allowed to use this command.
+ */
+ public boolean canCommandSenderUseCommand(ICommandSender par1ICommandSender) {
+ return MinecraftServer.getServer().isSinglePlayer() || super.canCommandSenderUseCommand(par1ICommandSender);
+ }
+
+ public String getCommandName() {
+ return "seed";
+ }
+
+ /**
+ * Return the required permission level for this command.
+ */
+ public int getRequiredPermissionLevel() {
+ return 2;
+ }
+
+ public void processCommand(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) {
+ Object var3 = par1ICommandSender instanceof EntityPlayer ? ((EntityPlayer) par1ICommandSender).worldObj
+ : MinecraftServer.getServer().worldServerForDimension(0);
+ par1ICommandSender.sendChatToPlayer("Seed: " + ((World) var3).getSeed());
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/CommandTime.java b/sp-server/src/main/java/net/minecraft/src/CommandTime.java
new file mode 100644
index 0000000..995555e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/CommandTime.java
@@ -0,0 +1,82 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.minecraft.server.MinecraftServer;
+
+public class CommandTime extends CommandBase {
+ public String getCommandName() {
+ return "time";
+ }
+
+ /**
+ * Return the required permission level for this command.
+ */
+ public int getRequiredPermissionLevel() {
+ return 2;
+ }
+
+ public String getCommandUsage(ICommandSender par1ICommandSender) {
+ return par1ICommandSender.translateString("commands.time.usage", new Object[0]);
+ }
+
+ public void processCommand(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) {
+ if (par2ArrayOfStr.length > 1) {
+ int var3;
+
+ if (par2ArrayOfStr[0].equals("set")) {
+ if (par2ArrayOfStr[1].equals("day")) {
+ var3 = 0;
+ } else if (par2ArrayOfStr[1].equals("night")) {
+ var3 = 12500;
+ } else {
+ var3 = parseIntWithMin(par1ICommandSender, par2ArrayOfStr[1], 0);
+ }
+
+ this.setTime(par1ICommandSender, var3);
+ notifyAdmins(par1ICommandSender, "commands.time.set", new Object[] { Integer.valueOf(var3) });
+ return;
+ }
+
+ if (par2ArrayOfStr[0].equals("add")) {
+ var3 = parseIntWithMin(par1ICommandSender, par2ArrayOfStr[1], 0);
+ this.addTime(par1ICommandSender, var3);
+ notifyAdmins(par1ICommandSender, "commands.time.added", new Object[] { Integer.valueOf(var3) });
+ return;
+ }
+ }
+
+ throw new WrongUsageException("commands.time.usage", new Object[0]);
+ }
+
+ /**
+ * Adds the strings available in this command to the given list of tab
+ * completion options.
+ */
+ public List addTabCompletionOptions(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) {
+ return par2ArrayOfStr.length == 1
+ ? getListOfStringsMatchingLastWord(par2ArrayOfStr, new String[] { "set", "add" })
+ : (par2ArrayOfStr.length == 2 && par2ArrayOfStr[0].equals("set")
+ ? getListOfStringsMatchingLastWord(par2ArrayOfStr, new String[] { "day", "night" })
+ : null);
+ }
+
+ /**
+ * Set the time in the server object.
+ */
+ protected void setTime(ICommandSender par1ICommandSender, int par2) {
+ for (int var3 = 0; var3 < MinecraftServer.getServer().worldServers.length; ++var3) {
+ MinecraftServer.getServer().worldServers[var3].setWorldTime((long) par2);
+ }
+ }
+
+ /**
+ * Adds (or removes) time in the server object.
+ */
+ protected void addTime(ICommandSender par1ICommandSender, int par2) {
+ for (int var3 = 0; var3 < MinecraftServer.getServer().worldServers.length; ++var3) {
+ WorldServer var4 = MinecraftServer.getServer().worldServers[var3];
+ var4.setWorldTime(var4.getWorldTime() + (long) par2);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/CommandToggleDownfall.java b/sp-server/src/main/java/net/minecraft/src/CommandToggleDownfall.java
new file mode 100644
index 0000000..ed17834
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/CommandToggleDownfall.java
@@ -0,0 +1,29 @@
+package net.minecraft.src;
+
+import net.minecraft.server.MinecraftServer;
+
+public class CommandToggleDownfall extends CommandBase {
+ public String getCommandName() {
+ return "toggledownfall";
+ }
+
+ /**
+ * Return the required permission level for this command.
+ */
+ public int getRequiredPermissionLevel() {
+ return 2;
+ }
+
+ public void processCommand(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) {
+ this.toggleDownfall();
+ notifyAdmins(par1ICommandSender, "commands.downfall.success", new Object[0]);
+ }
+
+ /**
+ * Toggle rain and enable thundering.
+ */
+ protected void toggleDownfall() {
+ MinecraftServer.getServer().worldServers[0].commandToggleDownfall();
+ MinecraftServer.getServer().worldServers[0].getWorldInfo().setThundering(true);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/CommandWeather.java b/sp-server/src/main/java/net/minecraft/src/CommandWeather.java
new file mode 100644
index 0000000..03b4e3e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/CommandWeather.java
@@ -0,0 +1,61 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+import net.minecraft.server.MinecraftServer;
+
+public class CommandWeather extends CommandBase {
+ public String getCommandName() {
+ return "weather";
+ }
+
+ /**
+ * Return the required permission level for this command.
+ */
+ public int getRequiredPermissionLevel() {
+ return 2;
+ }
+
+ public void processCommand(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) {
+ if (par2ArrayOfStr.length < 1) {
+ throw new WrongUsageException("commands.weather.usage", new Object[0]);
+ } else {
+ boolean clear = "clear".equalsIgnoreCase(par2ArrayOfStr[0]);
+ int var3 = (300 + (new EaglercraftRandom()).nextInt(600)) * (clear ? 80 : 20);
+
+ if (par2ArrayOfStr.length >= 2) {
+ var3 = parseIntBounded(par1ICommandSender, par2ArrayOfStr[1], 1, 1000000) * 20;
+ }
+
+ WorldServer var4 = MinecraftServer.getServer().worldServers[0];
+ WorldInfo var5 = var4.getWorldInfo();
+ var5.setRainTime(var3);
+ var5.setThunderTime(var3);
+
+ if (clear) {
+ var5.setRaining(false);
+ var5.setThundering(false);
+ notifyAdmins(par1ICommandSender, "commands.weather.clear", new Object[0]);
+ } else if ("rain".equalsIgnoreCase(par2ArrayOfStr[0])) {
+ var5.setRaining(true);
+ var5.setThundering(false);
+ notifyAdmins(par1ICommandSender, "commands.weather.rain", new Object[0]);
+ } else if ("thunder".equalsIgnoreCase(par2ArrayOfStr[0])) {
+ var5.setRaining(true);
+ var5.setThundering(true);
+ notifyAdmins(par1ICommandSender, "commands.weather.thunder", new Object[0]);
+ }
+ }
+ }
+
+ /**
+ * Adds the strings available in this command to the given list of tab
+ * completion options.
+ */
+ public List addTabCompletionOptions(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) {
+ return par2ArrayOfStr.length == 1
+ ? getListOfStringsMatchingLastWord(par2ArrayOfStr, new String[] { "clear", "rain", "thunder" })
+ : null;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/CommandXP.java b/sp-server/src/main/java/net/minecraft/src/CommandXP.java
new file mode 100644
index 0000000..a1bdf89
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/CommandXP.java
@@ -0,0 +1,90 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.minecraft.server.MinecraftServer;
+
+public class CommandXP extends CommandBase {
+ public String getCommandName() {
+ return "xp";
+ }
+
+ /**
+ * Return the required permission level for this command.
+ */
+ public int getRequiredPermissionLevel() {
+ return 2;
+ }
+
+ public String getCommandUsage(ICommandSender par1ICommandSender) {
+ return par1ICommandSender.translateString("commands.xp.usage", new Object[0]);
+ }
+
+ public void processCommand(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) {
+ if (par2ArrayOfStr.length <= 0) {
+ throw new WrongUsageException("commands.xp.usage", new Object[0]);
+ } else {
+ String var4 = par2ArrayOfStr[0];
+ boolean var5 = var4.endsWith("l") || var4.endsWith("L");
+
+ if (var5 && var4.length() > 1) {
+ var4 = var4.substring(0, var4.length() - 1);
+ }
+
+ int var6 = parseInt(par1ICommandSender, var4);
+ boolean var7 = var6 < 0;
+
+ if (var7) {
+ var6 *= -1;
+ }
+
+ EntityPlayerMP var3;
+
+ if (par2ArrayOfStr.length > 1) {
+ var3 = func_82359_c(par1ICommandSender, par2ArrayOfStr[1]);
+ } else {
+ var3 = getCommandSenderAsPlayer(par1ICommandSender);
+ }
+
+ if (var5) {
+ if (var7) {
+ var3.addExperienceLevel(-var6);
+ notifyAdmins(par1ICommandSender, "commands.xp.success.negative.levels",
+ new Object[] { Integer.valueOf(var6), var3.getEntityName() });
+ } else {
+ var3.addExperienceLevel(var6);
+ notifyAdmins(par1ICommandSender, "commands.xp.success.levels",
+ new Object[] { Integer.valueOf(var6), var3.getEntityName() });
+ }
+ } else {
+ if (var7) {
+ throw new WrongUsageException("commands.xp.failure.widthdrawXp", new Object[0]);
+ }
+
+ var3.addExperience(var6);
+ notifyAdmins(par1ICommandSender, "commands.xp.success",
+ new Object[] { Integer.valueOf(var6), var3.getEntityName() });
+ }
+ }
+ }
+
+ /**
+ * Adds the strings available in this command to the given list of tab
+ * completion options.
+ */
+ public List addTabCompletionOptions(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) {
+ return par2ArrayOfStr.length == 2 ? getListOfStringsMatchingLastWord(par2ArrayOfStr, this.getAllUsernames())
+ : null;
+ }
+
+ protected String[] getAllUsernames() {
+ return MinecraftServer.getServer().getAllUsernames();
+ }
+
+ /**
+ * Return whether the specified command parameter index is a username parameter.
+ */
+ public boolean isUsernameIndex(String[] par1ArrayOfStr, int par2) {
+ return par2 == 1;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentMineshaftCorridor.java b/sp-server/src/main/java/net/minecraft/src/ComponentMineshaftCorridor.java
new file mode 100644
index 0000000..96c9082
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentMineshaftCorridor.java
@@ -0,0 +1,324 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentMineshaftCorridor extends StructureComponent {
+ private final boolean hasRails;
+ private final boolean hasSpiders;
+ private boolean spawnerPlaced;
+
+ /**
+ * A count of the different sections of this mine. The space between ceiling
+ * supports.
+ */
+ private int sectionCount;
+
+ public ComponentMineshaftCorridor(int par1, EaglercraftRandom par2Random, StructureBoundingBox par3StructureBoundingBox,
+ int par4) {
+ super(par1);
+ this.coordBaseMode = par4;
+ this.boundingBox = par3StructureBoundingBox;
+ this.hasRails = par2Random.nextInt(3) == 0;
+ this.hasSpiders = !this.hasRails && par2Random.nextInt(23) == 0;
+
+ if (this.coordBaseMode != 2 && this.coordBaseMode != 0) {
+ this.sectionCount = par3StructureBoundingBox.getXSize() / 5;
+ } else {
+ this.sectionCount = par3StructureBoundingBox.getZSize() / 5;
+ }
+ }
+
+ public static StructureBoundingBox findValidPlacement(List par0List, EaglercraftRandom par1Random, int par2, int par3,
+ int par4, int par5) {
+ StructureBoundingBox var6 = new StructureBoundingBox(par2, par3, par4, par2, par3 + 2, par4);
+ int var7;
+
+ for (var7 = par1Random.nextInt(3) + 2; var7 > 0; --var7) {
+ int var8 = var7 * 5;
+
+ switch (par5) {
+ case 0:
+ var6.maxX = par2 + 2;
+ var6.maxZ = par4 + (var8 - 1);
+ break;
+
+ case 1:
+ var6.minX = par2 - (var8 - 1);
+ var6.maxZ = par4 + 2;
+ break;
+
+ case 2:
+ var6.maxX = par2 + 2;
+ var6.minZ = par4 - (var8 - 1);
+ break;
+
+ case 3:
+ var6.maxX = par2 + (var8 - 1);
+ var6.maxZ = par4 + 2;
+ }
+
+ if (StructureComponent.findIntersecting(par0List, var6) == null) {
+ break;
+ }
+ }
+
+ return var7 > 0 ? var6 : null;
+ }
+
+ /**
+ * Initiates construction of the Structure Component picked, at the current
+ * Location of StructGen
+ */
+ public void buildComponent(StructureComponent par1StructureComponent, List par2List, EaglercraftRandom par3Random) {
+ int var4 = this.getComponentType();
+ int var5 = par3Random.nextInt(4);
+
+ switch (this.coordBaseMode) {
+ case 0:
+ if (var5 <= 1) {
+ StructureMineshaftPieces.getNextComponent(par1StructureComponent, par2List, par3Random,
+ this.boundingBox.minX, this.boundingBox.minY - 1 + par3Random.nextInt(3),
+ this.boundingBox.maxZ + 1, this.coordBaseMode, var4);
+ } else if (var5 == 2) {
+ StructureMineshaftPieces.getNextComponent(par1StructureComponent, par2List, par3Random,
+ this.boundingBox.minX - 1, this.boundingBox.minY - 1 + par3Random.nextInt(3),
+ this.boundingBox.maxZ - 3, 1, var4);
+ } else {
+ StructureMineshaftPieces.getNextComponent(par1StructureComponent, par2List, par3Random,
+ this.boundingBox.maxX + 1, this.boundingBox.minY - 1 + par3Random.nextInt(3),
+ this.boundingBox.maxZ - 3, 3, var4);
+ }
+
+ break;
+
+ case 1:
+ if (var5 <= 1) {
+ StructureMineshaftPieces.getNextComponent(par1StructureComponent, par2List, par3Random,
+ this.boundingBox.minX - 1, this.boundingBox.minY - 1 + par3Random.nextInt(3),
+ this.boundingBox.minZ, this.coordBaseMode, var4);
+ } else if (var5 == 2) {
+ StructureMineshaftPieces.getNextComponent(par1StructureComponent, par2List, par3Random,
+ this.boundingBox.minX, this.boundingBox.minY - 1 + par3Random.nextInt(3),
+ this.boundingBox.minZ - 1, 2, var4);
+ } else {
+ StructureMineshaftPieces.getNextComponent(par1StructureComponent, par2List, par3Random,
+ this.boundingBox.minX, this.boundingBox.minY - 1 + par3Random.nextInt(3),
+ this.boundingBox.maxZ + 1, 0, var4);
+ }
+
+ break;
+
+ case 2:
+ if (var5 <= 1) {
+ StructureMineshaftPieces.getNextComponent(par1StructureComponent, par2List, par3Random,
+ this.boundingBox.minX, this.boundingBox.minY - 1 + par3Random.nextInt(3),
+ this.boundingBox.minZ - 1, this.coordBaseMode, var4);
+ } else if (var5 == 2) {
+ StructureMineshaftPieces.getNextComponent(par1StructureComponent, par2List, par3Random,
+ this.boundingBox.minX - 1, this.boundingBox.minY - 1 + par3Random.nextInt(3),
+ this.boundingBox.minZ, 1, var4);
+ } else {
+ StructureMineshaftPieces.getNextComponent(par1StructureComponent, par2List, par3Random,
+ this.boundingBox.maxX + 1, this.boundingBox.minY - 1 + par3Random.nextInt(3),
+ this.boundingBox.minZ, 3, var4);
+ }
+
+ break;
+
+ case 3:
+ if (var5 <= 1) {
+ StructureMineshaftPieces.getNextComponent(par1StructureComponent, par2List, par3Random,
+ this.boundingBox.maxX + 1, this.boundingBox.minY - 1 + par3Random.nextInt(3),
+ this.boundingBox.minZ, this.coordBaseMode, var4);
+ } else if (var5 == 2) {
+ StructureMineshaftPieces.getNextComponent(par1StructureComponent, par2List, par3Random,
+ this.boundingBox.maxX - 3, this.boundingBox.minY - 1 + par3Random.nextInt(3),
+ this.boundingBox.minZ - 1, 2, var4);
+ } else {
+ StructureMineshaftPieces.getNextComponent(par1StructureComponent, par2List, par3Random,
+ this.boundingBox.maxX - 3, this.boundingBox.minY - 1 + par3Random.nextInt(3),
+ this.boundingBox.maxZ + 1, 0, var4);
+ }
+ }
+
+ if (var4 < 8) {
+ int var6;
+ int var7;
+
+ if (this.coordBaseMode != 2 && this.coordBaseMode != 0) {
+ for (var6 = this.boundingBox.minX + 3; var6 + 3 <= this.boundingBox.maxX; var6 += 5) {
+ var7 = par3Random.nextInt(5);
+
+ if (var7 == 0) {
+ StructureMineshaftPieces.getNextComponent(par1StructureComponent, par2List, par3Random, var6,
+ this.boundingBox.minY, this.boundingBox.minZ - 1, 2, var4 + 1);
+ } else if (var7 == 1) {
+ StructureMineshaftPieces.getNextComponent(par1StructureComponent, par2List, par3Random, var6,
+ this.boundingBox.minY, this.boundingBox.maxZ + 1, 0, var4 + 1);
+ }
+ }
+ } else {
+ for (var6 = this.boundingBox.minZ + 3; var6 + 3 <= this.boundingBox.maxZ; var6 += 5) {
+ var7 = par3Random.nextInt(5);
+
+ if (var7 == 0) {
+ StructureMineshaftPieces.getNextComponent(par1StructureComponent, par2List, par3Random,
+ this.boundingBox.minX - 1, this.boundingBox.minY, var6, 1, var4 + 1);
+ } else if (var7 == 1) {
+ StructureMineshaftPieces.getNextComponent(par1StructureComponent, par2List, par3Random,
+ this.boundingBox.maxX + 1, this.boundingBox.minY, var6, 3, var4 + 1);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Used to generate chests with items in it. ex: Temple Chests, Village
+ * Blacksmith Chests, Mineshaft Chests.
+ */
+ protected boolean generateStructureChestContents(World par1World, StructureBoundingBox par2StructureBoundingBox,
+ EaglercraftRandom par3Random, int par4, int par5, int par6,
+ WeightedRandomChestContent[] par7ArrayOfWeightedRandomChestContent, int par8) {
+ int var9 = this.getXWithOffset(par4, par6);
+ int var10 = this.getYWithOffset(par5);
+ int var11 = this.getZWithOffset(par4, par6);
+
+ if (par2StructureBoundingBox.isVecInside(var9, var10, var11) && par1World.getBlockId(var9, var10, var11) == 0) {
+ par1World.setBlock(var9, var10, var11, Block.rail.blockID,
+ this.getMetadataWithOffset(Block.rail.blockID, par3Random.nextBoolean() ? 1 : 0), 2);
+ EntityMinecartChest var12 = new EntityMinecartChest(par1World, (double) ((float) var9 + 0.5F),
+ (double) ((float) var10 + 0.5F), (double) ((float) var11 + 0.5F));
+ WeightedRandomChestContent.generateChestContents(par3Random, par7ArrayOfWeightedRandomChestContent, var12,
+ par8);
+ par1World.spawnEntityInWorld(var12);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ if (this.isLiquidInStructureBoundingBox(par1World, par3StructureBoundingBox)) {
+ return false;
+ } else {
+ int var8 = this.sectionCount * 5 - 1;
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 0, 0, 2, 1, var8, 0, 0, false);
+ this.randomlyFillWithBlocks(par1World, par3StructureBoundingBox, par2Random, 0.8F, 0, 2, 0, 2, 2, var8, 0,
+ 0, false);
+
+ if (this.hasSpiders) {
+ this.randomlyFillWithBlocks(par1World, par3StructureBoundingBox, par2Random, 0.6F, 0, 0, 0, 2, 1, var8,
+ Block.web.blockID, 0, false);
+ }
+
+ int var9;
+ int var10;
+ int var11;
+
+ for (var9 = 0; var9 < this.sectionCount; ++var9) {
+ var10 = 2 + var9 * 5;
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 0, var10, 0, 1, var10, Block.fence.blockID,
+ 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 2, 0, var10, 2, 1, var10, Block.fence.blockID,
+ 0, false);
+
+ if (par2Random.nextInt(4) == 0) {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 2, var10, 0, 2, var10,
+ Block.planks.blockID, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 2, 2, var10, 2, 2, var10,
+ Block.planks.blockID, 0, false);
+ } else {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 2, var10, 2, 2, var10,
+ Block.planks.blockID, 0, false);
+ }
+
+ this.randomlyPlaceBlock(par1World, par3StructureBoundingBox, par2Random, 0.1F, 0, 2, var10 - 1,
+ Block.web.blockID, 0);
+ this.randomlyPlaceBlock(par1World, par3StructureBoundingBox, par2Random, 0.1F, 2, 2, var10 - 1,
+ Block.web.blockID, 0);
+ this.randomlyPlaceBlock(par1World, par3StructureBoundingBox, par2Random, 0.1F, 0, 2, var10 + 1,
+ Block.web.blockID, 0);
+ this.randomlyPlaceBlock(par1World, par3StructureBoundingBox, par2Random, 0.1F, 2, 2, var10 + 1,
+ Block.web.blockID, 0);
+ this.randomlyPlaceBlock(par1World, par3StructureBoundingBox, par2Random, 0.05F, 0, 2, var10 - 2,
+ Block.web.blockID, 0);
+ this.randomlyPlaceBlock(par1World, par3StructureBoundingBox, par2Random, 0.05F, 2, 2, var10 - 2,
+ Block.web.blockID, 0);
+ this.randomlyPlaceBlock(par1World, par3StructureBoundingBox, par2Random, 0.05F, 0, 2, var10 + 2,
+ Block.web.blockID, 0);
+ this.randomlyPlaceBlock(par1World, par3StructureBoundingBox, par2Random, 0.05F, 2, 2, var10 + 2,
+ Block.web.blockID, 0);
+ this.randomlyPlaceBlock(par1World, par3StructureBoundingBox, par2Random, 0.05F, 1, 2, var10 - 1,
+ Block.torchWood.blockID, 0);
+ this.randomlyPlaceBlock(par1World, par3StructureBoundingBox, par2Random, 0.05F, 1, 2, var10 + 1,
+ Block.torchWood.blockID, 0);
+
+ if (par2Random.nextInt(100) == 0) {
+ this.generateStructureChestContents(par1World, par3StructureBoundingBox, par2Random, 2, 0,
+ var10 - 1,
+ WeightedRandomChestContent.func_92080_a(StructureMineshaftPieces.func_78816_a(),
+ new WeightedRandomChestContent[] { Item.enchantedBook.func_92114_b(par2Random) }),
+ 3 + par2Random.nextInt(4));
+ }
+
+ if (par2Random.nextInt(100) == 0) {
+ this.generateStructureChestContents(par1World, par3StructureBoundingBox, par2Random, 0, 0,
+ var10 + 1,
+ WeightedRandomChestContent.func_92080_a(StructureMineshaftPieces.func_78816_a(),
+ new WeightedRandomChestContent[] { Item.enchantedBook.func_92114_b(par2Random) }),
+ 3 + par2Random.nextInt(4));
+ }
+
+ if (this.hasSpiders && !this.spawnerPlaced) {
+ var11 = this.getYWithOffset(0);
+ int var12 = var10 - 1 + par2Random.nextInt(3);
+ int var13 = this.getXWithOffset(1, var12);
+ var12 = this.getZWithOffset(1, var12);
+
+ if (par3StructureBoundingBox.isVecInside(var13, var11, var12)) {
+ this.spawnerPlaced = true;
+ par1World.setBlock(var13, var11, var12, Block.mobSpawner.blockID, 0, 2);
+ TileEntityMobSpawner var14 = (TileEntityMobSpawner) par1World.getBlockTileEntity(var13, var11,
+ var12);
+
+ if (var14 != null) {
+ var14.func_98049_a().setMobID("CaveSpider");
+ }
+ }
+ }
+ }
+
+ for (var9 = 0; var9 <= 2; ++var9) {
+ for (var10 = 0; var10 <= var8; ++var10) {
+ var11 = this.getBlockIdAtCurrentPosition(par1World, var9, -1, var10, par3StructureBoundingBox);
+
+ if (var11 == 0) {
+ this.placeBlockAtCurrentPosition(par1World, Block.planks.blockID, 0, var9, -1, var10,
+ par3StructureBoundingBox);
+ }
+ }
+ }
+
+ if (this.hasRails) {
+ for (var9 = 0; var9 <= var8; ++var9) {
+ var10 = this.getBlockIdAtCurrentPosition(par1World, 1, -1, var9, par3StructureBoundingBox);
+
+ if (var10 > 0 && Block.opaqueCubeLookup[var10]) {
+ this.randomlyPlaceBlock(par1World, par3StructureBoundingBox, par2Random, 0.7F, 1, 0, var9,
+ Block.rail.blockID, this.getMetadataWithOffset(Block.rail.blockID, 0));
+ }
+ }
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentMineshaftCross.java b/sp-server/src/main/java/net/minecraft/src/ComponentMineshaftCross.java
new file mode 100644
index 0000000..fac0537
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentMineshaftCross.java
@@ -0,0 +1,184 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentMineshaftCross extends StructureComponent {
+ private final int corridorDirection;
+ private final boolean isMultipleFloors;
+
+ public ComponentMineshaftCross(int par1, EaglercraftRandom par2Random, StructureBoundingBox par3StructureBoundingBox,
+ int par4) {
+ super(par1);
+ this.corridorDirection = par4;
+ this.boundingBox = par3StructureBoundingBox;
+ this.isMultipleFloors = par3StructureBoundingBox.getYSize() > 3;
+ }
+
+ public static StructureBoundingBox findValidPlacement(List par0List, EaglercraftRandom par1Random, int par2, int par3,
+ int par4, int par5) {
+ StructureBoundingBox var6 = new StructureBoundingBox(par2, par3, par4, par2, par3 + 2, par4);
+
+ if (par1Random.nextInt(4) == 0) {
+ var6.maxY += 4;
+ }
+
+ switch (par5) {
+ case 0:
+ var6.minX = par2 - 1;
+ var6.maxX = par2 + 3;
+ var6.maxZ = par4 + 4;
+ break;
+
+ case 1:
+ var6.minX = par2 - 4;
+ var6.minZ = par4 - 1;
+ var6.maxZ = par4 + 3;
+ break;
+
+ case 2:
+ var6.minX = par2 - 1;
+ var6.maxX = par2 + 3;
+ var6.minZ = par4 - 4;
+ break;
+
+ case 3:
+ var6.maxX = par2 + 4;
+ var6.minZ = par4 - 1;
+ var6.maxZ = par4 + 3;
+ }
+
+ return StructureComponent.findIntersecting(par0List, var6) != null ? null : var6;
+ }
+
+ /**
+ * Initiates construction of the Structure Component picked, at the current
+ * Location of StructGen
+ */
+ public void buildComponent(StructureComponent par1StructureComponent, List par2List, EaglercraftRandom par3Random) {
+ int var4 = this.getComponentType();
+
+ switch (this.corridorDirection) {
+ case 0:
+ StructureMineshaftPieces.getNextComponent(par1StructureComponent, par2List, par3Random,
+ this.boundingBox.minX + 1, this.boundingBox.minY, this.boundingBox.maxZ + 1, 0, var4);
+ StructureMineshaftPieces.getNextComponent(par1StructureComponent, par2List, par3Random,
+ this.boundingBox.minX - 1, this.boundingBox.minY, this.boundingBox.minZ + 1, 1, var4);
+ StructureMineshaftPieces.getNextComponent(par1StructureComponent, par2List, par3Random,
+ this.boundingBox.maxX + 1, this.boundingBox.minY, this.boundingBox.minZ + 1, 3, var4);
+ break;
+
+ case 1:
+ StructureMineshaftPieces.getNextComponent(par1StructureComponent, par2List, par3Random,
+ this.boundingBox.minX + 1, this.boundingBox.minY, this.boundingBox.minZ - 1, 2, var4);
+ StructureMineshaftPieces.getNextComponent(par1StructureComponent, par2List, par3Random,
+ this.boundingBox.minX + 1, this.boundingBox.minY, this.boundingBox.maxZ + 1, 0, var4);
+ StructureMineshaftPieces.getNextComponent(par1StructureComponent, par2List, par3Random,
+ this.boundingBox.minX - 1, this.boundingBox.minY, this.boundingBox.minZ + 1, 1, var4);
+ break;
+
+ case 2:
+ StructureMineshaftPieces.getNextComponent(par1StructureComponent, par2List, par3Random,
+ this.boundingBox.minX + 1, this.boundingBox.minY, this.boundingBox.minZ - 1, 2, var4);
+ StructureMineshaftPieces.getNextComponent(par1StructureComponent, par2List, par3Random,
+ this.boundingBox.minX - 1, this.boundingBox.minY, this.boundingBox.minZ + 1, 1, var4);
+ StructureMineshaftPieces.getNextComponent(par1StructureComponent, par2List, par3Random,
+ this.boundingBox.maxX + 1, this.boundingBox.minY, this.boundingBox.minZ + 1, 3, var4);
+ break;
+
+ case 3:
+ StructureMineshaftPieces.getNextComponent(par1StructureComponent, par2List, par3Random,
+ this.boundingBox.minX + 1, this.boundingBox.minY, this.boundingBox.minZ - 1, 2, var4);
+ StructureMineshaftPieces.getNextComponent(par1StructureComponent, par2List, par3Random,
+ this.boundingBox.minX + 1, this.boundingBox.minY, this.boundingBox.maxZ + 1, 0, var4);
+ StructureMineshaftPieces.getNextComponent(par1StructureComponent, par2List, par3Random,
+ this.boundingBox.maxX + 1, this.boundingBox.minY, this.boundingBox.minZ + 1, 3, var4);
+ }
+
+ if (this.isMultipleFloors) {
+ if (par3Random.nextBoolean()) {
+ StructureMineshaftPieces.getNextComponent(par1StructureComponent, par2List, par3Random,
+ this.boundingBox.minX + 1, this.boundingBox.minY + 3 + 1, this.boundingBox.minZ - 1, 2, var4);
+ }
+
+ if (par3Random.nextBoolean()) {
+ StructureMineshaftPieces.getNextComponent(par1StructureComponent, par2List, par3Random,
+ this.boundingBox.minX - 1, this.boundingBox.minY + 3 + 1, this.boundingBox.minZ + 1, 1, var4);
+ }
+
+ if (par3Random.nextBoolean()) {
+ StructureMineshaftPieces.getNextComponent(par1StructureComponent, par2List, par3Random,
+ this.boundingBox.maxX + 1, this.boundingBox.minY + 3 + 1, this.boundingBox.minZ + 1, 3, var4);
+ }
+
+ if (par3Random.nextBoolean()) {
+ StructureMineshaftPieces.getNextComponent(par1StructureComponent, par2List, par3Random,
+ this.boundingBox.minX + 1, this.boundingBox.minY + 3 + 1, this.boundingBox.maxZ + 1, 0, var4);
+ }
+ }
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ if (this.isLiquidInStructureBoundingBox(par1World, par3StructureBoundingBox)) {
+ return false;
+ } else {
+ if (this.isMultipleFloors) {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, this.boundingBox.minX + 1,
+ this.boundingBox.minY, this.boundingBox.minZ, this.boundingBox.maxX - 1,
+ this.boundingBox.minY + 3 - 1, this.boundingBox.maxZ, 0, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, this.boundingBox.minX, this.boundingBox.minY,
+ this.boundingBox.minZ + 1, this.boundingBox.maxX, this.boundingBox.minY + 3 - 1,
+ this.boundingBox.maxZ - 1, 0, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, this.boundingBox.minX + 1,
+ this.boundingBox.maxY - 2, this.boundingBox.minZ, this.boundingBox.maxX - 1,
+ this.boundingBox.maxY, this.boundingBox.maxZ, 0, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, this.boundingBox.minX,
+ this.boundingBox.maxY - 2, this.boundingBox.minZ + 1, this.boundingBox.maxX,
+ this.boundingBox.maxY, this.boundingBox.maxZ - 1, 0, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, this.boundingBox.minX + 1,
+ this.boundingBox.minY + 3, this.boundingBox.minZ + 1, this.boundingBox.maxX - 1,
+ this.boundingBox.minY + 3, this.boundingBox.maxZ - 1, 0, 0, false);
+ } else {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, this.boundingBox.minX + 1,
+ this.boundingBox.minY, this.boundingBox.minZ, this.boundingBox.maxX - 1, this.boundingBox.maxY,
+ this.boundingBox.maxZ, 0, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, this.boundingBox.minX, this.boundingBox.minY,
+ this.boundingBox.minZ + 1, this.boundingBox.maxX, this.boundingBox.maxY,
+ this.boundingBox.maxZ - 1, 0, 0, false);
+ }
+
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, this.boundingBox.minX + 1, this.boundingBox.minY,
+ this.boundingBox.minZ + 1, this.boundingBox.minX + 1, this.boundingBox.maxY,
+ this.boundingBox.minZ + 1, Block.planks.blockID, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, this.boundingBox.minX + 1, this.boundingBox.minY,
+ this.boundingBox.maxZ - 1, this.boundingBox.minX + 1, this.boundingBox.maxY,
+ this.boundingBox.maxZ - 1, Block.planks.blockID, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, this.boundingBox.maxX - 1, this.boundingBox.minY,
+ this.boundingBox.minZ + 1, this.boundingBox.maxX - 1, this.boundingBox.maxY,
+ this.boundingBox.minZ + 1, Block.planks.blockID, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, this.boundingBox.maxX - 1, this.boundingBox.minY,
+ this.boundingBox.maxZ - 1, this.boundingBox.maxX - 1, this.boundingBox.maxY,
+ this.boundingBox.maxZ - 1, Block.planks.blockID, 0, false);
+
+ for (int var4 = this.boundingBox.minX; var4 <= this.boundingBox.maxX; ++var4) {
+ for (int var5 = this.boundingBox.minZ; var5 <= this.boundingBox.maxZ; ++var5) {
+ int var6 = this.getBlockIdAtCurrentPosition(par1World, var4, this.boundingBox.minY - 1, var5,
+ par3StructureBoundingBox);
+
+ if (var6 == 0) {
+ this.placeBlockAtCurrentPosition(par1World, Block.planks.blockID, 0, var4,
+ this.boundingBox.minY - 1, var5, par3StructureBoundingBox);
+ }
+ }
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentMineshaftRoom.java b/sp-server/src/main/java/net/minecraft/src/ComponentMineshaftRoom.java
new file mode 100644
index 0000000..04e4b2b
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentMineshaftRoom.java
@@ -0,0 +1,137 @@
+package net.minecraft.src;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentMineshaftRoom extends StructureComponent {
+ /** List of other Mineshaft components linked to this room. */
+ private List roomsLinkedToTheRoom = new LinkedList();
+
+ public ComponentMineshaftRoom(int par1, EaglercraftRandom par2Random, int par3, int par4) {
+ super(par1);
+ this.boundingBox = new StructureBoundingBox(par3, 50, par4, par3 + 7 + par2Random.nextInt(6),
+ 54 + par2Random.nextInt(6), par4 + 7 + par2Random.nextInt(6));
+ }
+
+ /**
+ * Initiates construction of the Structure Component picked, at the current
+ * Location of StructGen
+ */
+ public void buildComponent(StructureComponent par1StructureComponent, List par2List, EaglercraftRandom par3Random) {
+ int var4 = this.getComponentType();
+ int var6 = this.boundingBox.getYSize() - 3 - 1;
+
+ if (var6 <= 0) {
+ var6 = 1;
+ }
+
+ int var5;
+ StructureComponent var7;
+ StructureBoundingBox var8;
+
+ for (var5 = 0; var5 < this.boundingBox.getXSize(); var5 += 4) {
+ var5 += par3Random.nextInt(this.boundingBox.getXSize());
+
+ if (var5 + 3 > this.boundingBox.getXSize()) {
+ break;
+ }
+
+ var7 = StructureMineshaftPieces.getNextComponent(par1StructureComponent, par2List, par3Random,
+ this.boundingBox.minX + var5, this.boundingBox.minY + par3Random.nextInt(var6) + 1,
+ this.boundingBox.minZ - 1, 2, var4);
+
+ if (var7 != null) {
+ var8 = var7.getBoundingBox();
+ this.roomsLinkedToTheRoom.add(new StructureBoundingBox(var8.minX, var8.minY, this.boundingBox.minZ,
+ var8.maxX, var8.maxY, this.boundingBox.minZ + 1));
+ }
+ }
+
+ for (var5 = 0; var5 < this.boundingBox.getXSize(); var5 += 4) {
+ var5 += par3Random.nextInt(this.boundingBox.getXSize());
+
+ if (var5 + 3 > this.boundingBox.getXSize()) {
+ break;
+ }
+
+ var7 = StructureMineshaftPieces.getNextComponent(par1StructureComponent, par2List, par3Random,
+ this.boundingBox.minX + var5, this.boundingBox.minY + par3Random.nextInt(var6) + 1,
+ this.boundingBox.maxZ + 1, 0, var4);
+
+ if (var7 != null) {
+ var8 = var7.getBoundingBox();
+ this.roomsLinkedToTheRoom.add(new StructureBoundingBox(var8.minX, var8.minY, this.boundingBox.maxZ - 1,
+ var8.maxX, var8.maxY, this.boundingBox.maxZ));
+ }
+ }
+
+ for (var5 = 0; var5 < this.boundingBox.getZSize(); var5 += 4) {
+ var5 += par3Random.nextInt(this.boundingBox.getZSize());
+
+ if (var5 + 3 > this.boundingBox.getZSize()) {
+ break;
+ }
+
+ var7 = StructureMineshaftPieces.getNextComponent(par1StructureComponent, par2List, par3Random,
+ this.boundingBox.minX - 1, this.boundingBox.minY + par3Random.nextInt(var6) + 1,
+ this.boundingBox.minZ + var5, 1, var4);
+
+ if (var7 != null) {
+ var8 = var7.getBoundingBox();
+ this.roomsLinkedToTheRoom.add(new StructureBoundingBox(this.boundingBox.minX, var8.minY, var8.minZ,
+ this.boundingBox.minX + 1, var8.maxY, var8.maxZ));
+ }
+ }
+
+ for (var5 = 0; var5 < this.boundingBox.getZSize(); var5 += 4) {
+ var5 += par3Random.nextInt(this.boundingBox.getZSize());
+
+ if (var5 + 3 > this.boundingBox.getZSize()) {
+ break;
+ }
+
+ var7 = StructureMineshaftPieces.getNextComponent(par1StructureComponent, par2List, par3Random,
+ this.boundingBox.maxX + 1, this.boundingBox.minY + par3Random.nextInt(var6) + 1,
+ this.boundingBox.minZ + var5, 3, var4);
+
+ if (var7 != null) {
+ var8 = var7.getBoundingBox();
+ this.roomsLinkedToTheRoom.add(new StructureBoundingBox(this.boundingBox.maxX - 1, var8.minY, var8.minZ,
+ this.boundingBox.maxX, var8.maxY, var8.maxZ));
+ }
+ }
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ if (this.isLiquidInStructureBoundingBox(par1World, par3StructureBoundingBox)) {
+ return false;
+ } else {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, this.boundingBox.minX, this.boundingBox.minY,
+ this.boundingBox.minZ, this.boundingBox.maxX, this.boundingBox.minY, this.boundingBox.maxZ,
+ Block.dirt.blockID, 0, true);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, this.boundingBox.minX, this.boundingBox.minY + 1,
+ this.boundingBox.minZ, this.boundingBox.maxX,
+ Math.min(this.boundingBox.minY + 3, this.boundingBox.maxY), this.boundingBox.maxZ, 0, 0, false);
+ Iterator var4 = this.roomsLinkedToTheRoom.iterator();
+
+ while (var4.hasNext()) {
+ StructureBoundingBox var5 = (StructureBoundingBox) var4.next();
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, var5.minX, var5.maxY - 2, var5.minZ, var5.maxX,
+ var5.maxY, var5.maxZ, 0, 0, false);
+ }
+
+ this.randomlyRareFillWithBlocks(par1World, par3StructureBoundingBox, this.boundingBox.minX,
+ this.boundingBox.minY + 4, this.boundingBox.minZ, this.boundingBox.maxX, this.boundingBox.maxY,
+ this.boundingBox.maxZ, 0, false);
+ return true;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentMineshaftStairs.java b/sp-server/src/main/java/net/minecraft/src/ComponentMineshaftStairs.java
new file mode 100644
index 0000000..5e7e62d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentMineshaftStairs.java
@@ -0,0 +1,95 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentMineshaftStairs extends StructureComponent {
+ public ComponentMineshaftStairs(int par1, EaglercraftRandom par2Random, StructureBoundingBox par3StructureBoundingBox,
+ int par4) {
+ super(par1);
+ this.coordBaseMode = par4;
+ this.boundingBox = par3StructureBoundingBox;
+ }
+
+ /**
+ * Trys to find a valid place to put this component.
+ */
+ public static StructureBoundingBox findValidPlacement(List par0List, EaglercraftRandom par1Random, int par2, int par3,
+ int par4, int par5) {
+ StructureBoundingBox var6 = new StructureBoundingBox(par2, par3 - 5, par4, par2, par3 + 2, par4);
+
+ switch (par5) {
+ case 0:
+ var6.maxX = par2 + 2;
+ var6.maxZ = par4 + 8;
+ break;
+
+ case 1:
+ var6.minX = par2 - 8;
+ var6.maxZ = par4 + 2;
+ break;
+
+ case 2:
+ var6.maxX = par2 + 2;
+ var6.minZ = par4 - 8;
+ break;
+
+ case 3:
+ var6.maxX = par2 + 8;
+ var6.maxZ = par4 + 2;
+ }
+
+ return StructureComponent.findIntersecting(par0List, var6) != null ? null : var6;
+ }
+
+ /**
+ * Initiates construction of the Structure Component picked, at the current
+ * Location of StructGen
+ */
+ public void buildComponent(StructureComponent par1StructureComponent, List par2List, EaglercraftRandom par3Random) {
+ int var4 = this.getComponentType();
+
+ switch (this.coordBaseMode) {
+ case 0:
+ StructureMineshaftPieces.getNextComponent(par1StructureComponent, par2List, par3Random,
+ this.boundingBox.minX, this.boundingBox.minY, this.boundingBox.maxZ + 1, 0, var4);
+ break;
+
+ case 1:
+ StructureMineshaftPieces.getNextComponent(par1StructureComponent, par2List, par3Random,
+ this.boundingBox.minX - 1, this.boundingBox.minY, this.boundingBox.minZ, 1, var4);
+ break;
+
+ case 2:
+ StructureMineshaftPieces.getNextComponent(par1StructureComponent, par2List, par3Random,
+ this.boundingBox.minX, this.boundingBox.minY, this.boundingBox.minZ - 1, 2, var4);
+ break;
+
+ case 3:
+ StructureMineshaftPieces.getNextComponent(par1StructureComponent, par2List, par3Random,
+ this.boundingBox.maxX + 1, this.boundingBox.minY, this.boundingBox.minZ, 3, var4);
+ }
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ if (this.isLiquidInStructureBoundingBox(par1World, par3StructureBoundingBox)) {
+ return false;
+ } else {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 5, 0, 2, 7, 1, 0, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 0, 7, 2, 2, 8, 0, 0, false);
+
+ for (int var4 = 0; var4 < 5; ++var4) {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 5 - var4 - (var4 < 4 ? 1 : 0), 2 + var4, 2,
+ 7 - var4, 2 + var4, 0, 0, false);
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeCorridor.java b/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeCorridor.java
new file mode 100644
index 0000000..3788d22
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeCorridor.java
@@ -0,0 +1,72 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentNetherBridgeCorridor extends ComponentNetherBridgePiece {
+ public ComponentNetherBridgeCorridor(int par1, EaglercraftRandom par2Random, StructureBoundingBox par3StructureBoundingBox,
+ int par4) {
+ super(par1);
+ this.coordBaseMode = par4;
+ this.boundingBox = par3StructureBoundingBox;
+ }
+
+ /**
+ * Initiates construction of the Structure Component picked, at the current
+ * Location of StructGen
+ */
+ public void buildComponent(StructureComponent par1StructureComponent, List par2List, EaglercraftRandom par3Random) {
+ this.getNextComponentX((ComponentNetherBridgeStartPiece) par1StructureComponent, par2List, par3Random, 0, 1,
+ true);
+ }
+
+ /**
+ * Creates and returns a new component piece. Or null if it could not find
+ * enough room to place it.
+ */
+ public static ComponentNetherBridgeCorridor createValidComponent(List par0List, EaglercraftRandom par1Random, int par2,
+ int par3, int par4, int par5, int par6) {
+ StructureBoundingBox var7 = StructureBoundingBox.getComponentToAddBoundingBox(par2, par3, par4, -1, 0, 0, 5, 7,
+ 5, par5);
+ return isAboveGround(var7) && StructureComponent.findIntersecting(par0List, var7) == null
+ ? new ComponentNetherBridgeCorridor(par6, par1Random, var7, par5)
+ : null;
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 0, 0, 4, 1, 4, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 2, 0, 4, 5, 4, 0, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 2, 0, 4, 5, 4, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 3, 1, 4, 4, 1, Block.netherFence.blockID,
+ Block.netherFence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 3, 3, 4, 4, 3, Block.netherFence.blockID,
+ Block.netherFence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 2, 0, 0, 5, 0, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 2, 4, 3, 5, 4, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 3, 4, 1, 4, 4, Block.netherFence.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 3, 3, 4, 3, 4, 4, Block.netherFence.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 6, 0, 4, 6, 4, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+
+ for (int var4 = 0; var4 <= 4; ++var4) {
+ for (int var5 = 0; var5 <= 4; ++var5) {
+ this.fillCurrentPositionBlocksDownwards(par1World, Block.netherBrick.blockID, 0, var4, -1, var5,
+ par3StructureBoundingBox);
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeCorridor2.java b/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeCorridor2.java
new file mode 100644
index 0000000..4b4bacb
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeCorridor2.java
@@ -0,0 +1,72 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentNetherBridgeCorridor2 extends ComponentNetherBridgePiece {
+ public ComponentNetherBridgeCorridor2(int par1, EaglercraftRandom par2Random, StructureBoundingBox par3StructureBoundingBox,
+ int par4) {
+ super(par1);
+ this.coordBaseMode = par4;
+ this.boundingBox = par3StructureBoundingBox;
+ }
+
+ /**
+ * Initiates construction of the Structure Component picked, at the current
+ * Location of StructGen
+ */
+ public void buildComponent(StructureComponent par1StructureComponent, List par2List, EaglercraftRandom par3Random) {
+ this.getNextComponentZ((ComponentNetherBridgeStartPiece) par1StructureComponent, par2List, par3Random, 0, 1,
+ true);
+ }
+
+ /**
+ * Creates and returns a new component piece. Or null if it could not find
+ * enough room to place it.
+ */
+ public static ComponentNetherBridgeCorridor2 createValidComponent(List par0List, EaglercraftRandom par1Random, int par2,
+ int par3, int par4, int par5, int par6) {
+ StructureBoundingBox var7 = StructureBoundingBox.getComponentToAddBoundingBox(par2, par3, par4, -1, 0, 0, 5, 7,
+ 5, par5);
+ return isAboveGround(var7) && StructureComponent.findIntersecting(par0List, var7) == null
+ ? new ComponentNetherBridgeCorridor2(par6, par1Random, var7, par5)
+ : null;
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 0, 0, 4, 1, 4, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 2, 0, 4, 5, 4, 0, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 2, 0, 0, 5, 4, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 3, 1, 0, 4, 1, Block.netherFence.blockID,
+ Block.netherFence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 3, 3, 0, 4, 3, Block.netherFence.blockID,
+ Block.netherFence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 2, 0, 4, 5, 0, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 2, 4, 4, 5, 4, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 3, 4, 1, 4, 4, Block.netherFence.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 3, 3, 4, 3, 4, 4, Block.netherFence.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 6, 0, 4, 6, 4, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+
+ for (int var4 = 0; var4 <= 4; ++var4) {
+ for (int var5 = 0; var5 <= 4; ++var5) {
+ this.fillCurrentPositionBlocksDownwards(par1World, Block.netherBrick.blockID, 0, var4, -1, var5,
+ par3StructureBoundingBox);
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeCorridor3.java b/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeCorridor3.java
new file mode 100644
index 0000000..65f2692
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeCorridor3.java
@@ -0,0 +1,84 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentNetherBridgeCorridor3 extends ComponentNetherBridgePiece {
+ public ComponentNetherBridgeCorridor3(int par1, EaglercraftRandom par2Random, StructureBoundingBox par3StructureBoundingBox,
+ int par4) {
+ super(par1);
+ this.coordBaseMode = par4;
+ this.boundingBox = par3StructureBoundingBox;
+ }
+
+ /**
+ * Initiates construction of the Structure Component picked, at the current
+ * Location of StructGen
+ */
+ public void buildComponent(StructureComponent par1StructureComponent, List par2List, EaglercraftRandom par3Random) {
+ this.getNextComponentNormal((ComponentNetherBridgeStartPiece) par1StructureComponent, par2List, par3Random, 1,
+ 0, true);
+ }
+
+ /**
+ * Creates and returns a new component piece. Or null if it could not find
+ * enough room to place it.
+ */
+ public static ComponentNetherBridgeCorridor3 createValidComponent(List par0List, EaglercraftRandom par1Random, int par2,
+ int par3, int par4, int par5, int par6) {
+ StructureBoundingBox var7 = StructureBoundingBox.getComponentToAddBoundingBox(par2, par3, par4, -1, -7, 0, 5,
+ 14, 10, par5);
+ return isAboveGround(var7) && StructureComponent.findIntersecting(par0List, var7) == null
+ ? new ComponentNetherBridgeCorridor3(par6, par1Random, var7, par5)
+ : null;
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ int var4 = this.getMetadataWithOffset(Block.stairsNetherBrick.blockID, 2);
+
+ for (int var5 = 0; var5 <= 9; ++var5) {
+ int var6 = Math.max(1, 7 - var5);
+ int var7 = Math.min(Math.max(var6 + 5, 14 - var5), 13);
+ int var8 = var5;
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 0, var5, 4, var6, var5,
+ Block.netherBrick.blockID, Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, var6 + 1, var5, 3, var7 - 1, var5, 0, 0, false);
+
+ if (var5 <= 6) {
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsNetherBrick.blockID, var4, 1, var6 + 1, var5,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsNetherBrick.blockID, var4, 2, var6 + 1, var5,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsNetherBrick.blockID, var4, 3, var6 + 1, var5,
+ par3StructureBoundingBox);
+ }
+
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, var7, var5, 4, var7, var5,
+ Block.netherBrick.blockID, Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, var6 + 1, var5, 0, var7 - 1, var5,
+ Block.netherBrick.blockID, Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, var6 + 1, var5, 4, var7 - 1, var5,
+ Block.netherBrick.blockID, Block.netherBrick.blockID, false);
+
+ if ((var5 & 1) == 0) {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, var6 + 2, var5, 0, var6 + 3, var5,
+ Block.netherFence.blockID, Block.netherFence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, var6 + 2, var5, 4, var6 + 3, var5,
+ Block.netherFence.blockID, Block.netherFence.blockID, false);
+ }
+
+ for (int var9 = 0; var9 <= 4; ++var9) {
+ this.fillCurrentPositionBlocksDownwards(par1World, Block.netherBrick.blockID, 0, var9, -1, var8,
+ par3StructureBoundingBox);
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeCorridor4.java b/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeCorridor4.java
new file mode 100644
index 0000000..d63700a
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeCorridor4.java
@@ -0,0 +1,96 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentNetherBridgeCorridor4 extends ComponentNetherBridgePiece {
+ public ComponentNetherBridgeCorridor4(int par1, EaglercraftRandom par2Random, StructureBoundingBox par3StructureBoundingBox,
+ int par4) {
+ super(par1);
+ this.coordBaseMode = par4;
+ this.boundingBox = par3StructureBoundingBox;
+ }
+
+ /**
+ * Initiates construction of the Structure Component picked, at the current
+ * Location of StructGen
+ */
+ public void buildComponent(StructureComponent par1StructureComponent, List par2List, EaglercraftRandom par3Random) {
+ byte var4 = 1;
+
+ if (this.coordBaseMode == 1 || this.coordBaseMode == 2) {
+ var4 = 5;
+ }
+
+ this.getNextComponentX((ComponentNetherBridgeStartPiece) par1StructureComponent, par2List, par3Random, 0, var4,
+ par3Random.nextInt(8) > 0);
+ this.getNextComponentZ((ComponentNetherBridgeStartPiece) par1StructureComponent, par2List, par3Random, 0, var4,
+ par3Random.nextInt(8) > 0);
+ }
+
+ /**
+ * Creates and returns a new component piece. Or null if it could not find
+ * enough room to place it.
+ */
+ public static ComponentNetherBridgeCorridor4 createValidComponent(List par0List, EaglercraftRandom par1Random, int par2,
+ int par3, int par4, int par5, int par6) {
+ StructureBoundingBox var7 = StructureBoundingBox.getComponentToAddBoundingBox(par2, par3, par4, -3, 0, 0, 9, 7,
+ 9, par5);
+ return isAboveGround(var7) && StructureComponent.findIntersecting(par0List, var7) == null
+ ? new ComponentNetherBridgeCorridor4(par6, par1Random, var7, par5)
+ : null;
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 0, 0, 8, 1, 8, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 2, 0, 8, 5, 8, 0, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 6, 0, 8, 6, 5, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 2, 0, 2, 5, 0, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 6, 2, 0, 8, 5, 0, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 3, 0, 1, 4, 0, Block.netherFence.blockID,
+ Block.netherFence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 7, 3, 0, 7, 4, 0, Block.netherFence.blockID,
+ Block.netherFence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 2, 4, 8, 2, 8, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 1, 4, 2, 2, 4, 0, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 6, 1, 4, 7, 2, 4, 0, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 3, 8, 8, 3, 8, Block.netherFence.blockID,
+ Block.netherFence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 3, 6, 0, 3, 7, Block.netherFence.blockID,
+ Block.netherFence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 8, 3, 6, 8, 3, 7, Block.netherFence.blockID,
+ Block.netherFence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 3, 4, 0, 5, 5, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 8, 3, 4, 8, 5, 5, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 3, 5, 2, 5, 5, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 6, 3, 5, 7, 5, 5, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 4, 5, 1, 5, 5, Block.netherFence.blockID,
+ Block.netherFence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 7, 4, 5, 7, 5, 5, Block.netherFence.blockID,
+ Block.netherFence.blockID, false);
+
+ for (int var4 = 0; var4 <= 5; ++var4) {
+ for (int var5 = 0; var5 <= 8; ++var5) {
+ this.fillCurrentPositionBlocksDownwards(par1World, Block.netherBrick.blockID, 0, var5, -1, var4,
+ par3StructureBoundingBox);
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeCorridor5.java b/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeCorridor5.java
new file mode 100644
index 0000000..f9a0a02
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeCorridor5.java
@@ -0,0 +1,70 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentNetherBridgeCorridor5 extends ComponentNetherBridgePiece {
+ public ComponentNetherBridgeCorridor5(int par1, EaglercraftRandom par2Random, StructureBoundingBox par3StructureBoundingBox,
+ int par4) {
+ super(par1);
+ this.coordBaseMode = par4;
+ this.boundingBox = par3StructureBoundingBox;
+ }
+
+ /**
+ * Initiates construction of the Structure Component picked, at the current
+ * Location of StructGen
+ */
+ public void buildComponent(StructureComponent par1StructureComponent, List par2List, EaglercraftRandom par3Random) {
+ this.getNextComponentNormal((ComponentNetherBridgeStartPiece) par1StructureComponent, par2List, par3Random, 1,
+ 0, true);
+ }
+
+ /**
+ * Creates and returns a new component piece. Or null if it could not find
+ * enough room to place it.
+ */
+ public static ComponentNetherBridgeCorridor5 createValidComponent(List par0List, EaglercraftRandom par1Random, int par2,
+ int par3, int par4, int par5, int par6) {
+ StructureBoundingBox var7 = StructureBoundingBox.getComponentToAddBoundingBox(par2, par3, par4, -1, 0, 0, 5, 7,
+ 5, par5);
+ return isAboveGround(var7) && StructureComponent.findIntersecting(par0List, var7) == null
+ ? new ComponentNetherBridgeCorridor5(par6, par1Random, var7, par5)
+ : null;
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 0, 0, 4, 1, 4, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 2, 0, 4, 5, 4, 0, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 2, 0, 0, 5, 4, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 2, 0, 4, 5, 4, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 3, 1, 0, 4, 1, Block.netherFence.blockID,
+ Block.netherFence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 3, 3, 0, 4, 3, Block.netherFence.blockID,
+ Block.netherFence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 3, 1, 4, 4, 1, Block.netherFence.blockID,
+ Block.netherFence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 3, 3, 4, 4, 3, Block.netherFence.blockID,
+ Block.netherFence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 6, 0, 4, 6, 4, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+
+ for (int var4 = 0; var4 <= 4; ++var4) {
+ for (int var5 = 0; var5 <= 4; ++var5) {
+ this.fillCurrentPositionBlocksDownwards(par1World, Block.netherBrick.blockID, 0, var4, -1, var5,
+ par3StructureBoundingBox);
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeCrossing.java b/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeCrossing.java
new file mode 100644
index 0000000..e8a85ec
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeCrossing.java
@@ -0,0 +1,92 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentNetherBridgeCrossing extends ComponentNetherBridgePiece {
+ public ComponentNetherBridgeCrossing(int par1, EaglercraftRandom par2Random, StructureBoundingBox par3StructureBoundingBox,
+ int par4) {
+ super(par1);
+ this.coordBaseMode = par4;
+ this.boundingBox = par3StructureBoundingBox;
+ }
+
+ /**
+ * Initiates construction of the Structure Component picked, at the current
+ * Location of StructGen
+ */
+ public void buildComponent(StructureComponent par1StructureComponent, List par2List, EaglercraftRandom par3Random) {
+ this.getNextComponentNormal((ComponentNetherBridgeStartPiece) par1StructureComponent, par2List, par3Random, 2,
+ 0, false);
+ this.getNextComponentX((ComponentNetherBridgeStartPiece) par1StructureComponent, par2List, par3Random, 0, 2,
+ false);
+ this.getNextComponentZ((ComponentNetherBridgeStartPiece) par1StructureComponent, par2List, par3Random, 0, 2,
+ false);
+ }
+
+ /**
+ * Creates and returns a new component piece. Or null if it could not find
+ * enough room to place it.
+ */
+ public static ComponentNetherBridgeCrossing createValidComponent(List par0List, EaglercraftRandom par1Random, int par2,
+ int par3, int par4, int par5, int par6) {
+ StructureBoundingBox var7 = StructureBoundingBox.getComponentToAddBoundingBox(par2, par3, par4, -2, 0, 0, 7, 9,
+ 7, par5);
+ return isAboveGround(var7) && StructureComponent.findIntersecting(par0List, var7) == null
+ ? new ComponentNetherBridgeCrossing(par6, par1Random, var7, par5)
+ : null;
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 0, 0, 6, 1, 6, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 2, 0, 6, 7, 6, 0, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 2, 0, 1, 6, 0, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 2, 6, 1, 6, 6, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 5, 2, 0, 6, 6, 0, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 5, 2, 6, 6, 6, 6, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 2, 0, 0, 6, 1, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 2, 5, 0, 6, 6, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 6, 2, 0, 6, 6, 1, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 6, 2, 5, 6, 6, 6, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 2, 6, 0, 4, 6, 0, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 2, 5, 0, 4, 5, 0, Block.netherFence.blockID,
+ Block.netherFence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 2, 6, 6, 4, 6, 6, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 2, 5, 6, 4, 5, 6, Block.netherFence.blockID,
+ Block.netherFence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 6, 2, 0, 6, 4, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 5, 2, 0, 5, 4, Block.netherFence.blockID,
+ Block.netherFence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 6, 6, 2, 6, 6, 4, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 6, 5, 2, 6, 5, 4, Block.netherFence.blockID,
+ Block.netherFence.blockID, false);
+
+ for (int var4 = 0; var4 <= 6; ++var4) {
+ for (int var5 = 0; var5 <= 6; ++var5) {
+ this.fillCurrentPositionBlocksDownwards(par1World, Block.netherBrick.blockID, 0, var4, -1, var5,
+ par3StructureBoundingBox);
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeCrossing2.java b/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeCrossing2.java
new file mode 100644
index 0000000..a1ad7d0
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeCrossing2.java
@@ -0,0 +1,70 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentNetherBridgeCrossing2 extends ComponentNetherBridgePiece {
+ public ComponentNetherBridgeCrossing2(int par1, EaglercraftRandom par2Random, StructureBoundingBox par3StructureBoundingBox,
+ int par4) {
+ super(par1);
+ this.coordBaseMode = par4;
+ this.boundingBox = par3StructureBoundingBox;
+ }
+
+ /**
+ * Initiates construction of the Structure Component picked, at the current
+ * Location of StructGen
+ */
+ public void buildComponent(StructureComponent par1StructureComponent, List par2List, EaglercraftRandom par3Random) {
+ this.getNextComponentNormal((ComponentNetherBridgeStartPiece) par1StructureComponent, par2List, par3Random, 1,
+ 0, true);
+ this.getNextComponentX((ComponentNetherBridgeStartPiece) par1StructureComponent, par2List, par3Random, 0, 1,
+ true);
+ this.getNextComponentZ((ComponentNetherBridgeStartPiece) par1StructureComponent, par2List, par3Random, 0, 1,
+ true);
+ }
+
+ /**
+ * Creates and returns a new component piece. Or null if it could not find
+ * enough room to place it.
+ */
+ public static ComponentNetherBridgeCrossing2 createValidComponent(List par0List, EaglercraftRandom par1Random, int par2,
+ int par3, int par4, int par5, int par6) {
+ StructureBoundingBox var7 = StructureBoundingBox.getComponentToAddBoundingBox(par2, par3, par4, -1, 0, 0, 5, 7,
+ 5, par5);
+ return isAboveGround(var7) && StructureComponent.findIntersecting(par0List, var7) == null
+ ? new ComponentNetherBridgeCrossing2(par6, par1Random, var7, par5)
+ : null;
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 0, 0, 4, 1, 4, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 2, 0, 4, 5, 4, 0, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 2, 0, 0, 5, 0, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 2, 0, 4, 5, 0, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 2, 4, 0, 5, 4, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 2, 4, 4, 5, 4, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 6, 0, 4, 6, 4, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+
+ for (int var4 = 0; var4 <= 4; ++var4) {
+ for (int var5 = 0; var5 <= 4; ++var5) {
+ this.fillCurrentPositionBlocksDownwards(par1World, Block.netherBrick.blockID, 0, var4, -1, var5,
+ par3StructureBoundingBox);
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeCrossing3.java b/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeCrossing3.java
new file mode 100644
index 0000000..d73ad4f
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeCrossing3.java
@@ -0,0 +1,124 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentNetherBridgeCrossing3 extends ComponentNetherBridgePiece {
+ public ComponentNetherBridgeCrossing3(int par1, EaglercraftRandom par2Random, StructureBoundingBox par3StructureBoundingBox,
+ int par4) {
+ super(par1);
+ this.coordBaseMode = par4;
+ this.boundingBox = par3StructureBoundingBox;
+ }
+
+ protected ComponentNetherBridgeCrossing3(EaglercraftRandom par1Random, int par2, int par3) {
+ super(0);
+ this.coordBaseMode = par1Random.nextInt(4);
+
+ switch (this.coordBaseMode) {
+ case 0:
+ case 2:
+ this.boundingBox = new StructureBoundingBox(par2, 64, par3, par2 + 19 - 1, 73, par3 + 19 - 1);
+ break;
+
+ default:
+ this.boundingBox = new StructureBoundingBox(par2, 64, par3, par2 + 19 - 1, 73, par3 + 19 - 1);
+ }
+ }
+
+ /**
+ * Initiates construction of the Structure Component picked, at the current
+ * Location of StructGen
+ */
+ public void buildComponent(StructureComponent par1StructureComponent, List par2List, EaglercraftRandom par3Random) {
+ this.getNextComponentNormal((ComponentNetherBridgeStartPiece) par1StructureComponent, par2List, par3Random, 8,
+ 3, false);
+ this.getNextComponentX((ComponentNetherBridgeStartPiece) par1StructureComponent, par2List, par3Random, 3, 8,
+ false);
+ this.getNextComponentZ((ComponentNetherBridgeStartPiece) par1StructureComponent, par2List, par3Random, 3, 8,
+ false);
+ }
+
+ /**
+ * Creates and returns a new component piece. Or null if it could not find
+ * enough room to place it.
+ */
+ public static ComponentNetherBridgeCrossing3 createValidComponent(List par0List, EaglercraftRandom par1Random, int par2,
+ int par3, int par4, int par5, int par6) {
+ StructureBoundingBox var7 = StructureBoundingBox.getComponentToAddBoundingBox(par2, par3, par4, -8, -3, 0, 19,
+ 10, 19, par5);
+ return isAboveGround(var7) && StructureComponent.findIntersecting(par0List, var7) == null
+ ? new ComponentNetherBridgeCrossing3(par6, par1Random, var7, par5)
+ : null;
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 7, 3, 0, 11, 4, 18, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 3, 7, 18, 4, 11, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 8, 5, 0, 10, 7, 18, 0, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 5, 8, 18, 7, 10, 0, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 7, 5, 0, 7, 5, 7, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 7, 5, 11, 7, 5, 18, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 11, 5, 0, 11, 5, 7, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 11, 5, 11, 11, 5, 18, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 5, 7, 7, 5, 7, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 11, 5, 7, 18, 5, 7, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 5, 11, 7, 5, 11, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 11, 5, 11, 18, 5, 11, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 7, 2, 0, 11, 2, 5, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 7, 2, 13, 11, 2, 18, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 7, 0, 0, 11, 1, 3, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 7, 0, 15, 11, 1, 18, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ int var4;
+ int var5;
+
+ for (var4 = 7; var4 <= 11; ++var4) {
+ for (var5 = 0; var5 <= 2; ++var5) {
+ this.fillCurrentPositionBlocksDownwards(par1World, Block.netherBrick.blockID, 0, var4, -1, var5,
+ par3StructureBoundingBox);
+ this.fillCurrentPositionBlocksDownwards(par1World, Block.netherBrick.blockID, 0, var4, -1, 18 - var5,
+ par3StructureBoundingBox);
+ }
+ }
+
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 2, 7, 5, 2, 11, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 13, 2, 7, 18, 2, 11, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 0, 7, 3, 1, 11, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 15, 0, 7, 18, 1, 11, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+
+ for (var4 = 0; var4 <= 2; ++var4) {
+ for (var5 = 7; var5 <= 11; ++var5) {
+ this.fillCurrentPositionBlocksDownwards(par1World, Block.netherBrick.blockID, 0, var4, -1, var5,
+ par3StructureBoundingBox);
+ this.fillCurrentPositionBlocksDownwards(par1World, Block.netherBrick.blockID, 0, 18 - var4, -1, var5,
+ par3StructureBoundingBox);
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeEnd.java b/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeEnd.java
new file mode 100644
index 0000000..b4b8a86
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeEnd.java
@@ -0,0 +1,69 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentNetherBridgeEnd extends ComponentNetherBridgePiece {
+ private int fillSeed;
+
+ public ComponentNetherBridgeEnd(int par1, EaglercraftRandom par2Random, StructureBoundingBox par3StructureBoundingBox,
+ int par4) {
+ super(par1);
+ this.coordBaseMode = par4;
+ this.boundingBox = par3StructureBoundingBox;
+ this.fillSeed = par2Random.nextInt();
+ }
+
+ public static ComponentNetherBridgeEnd func_74971_a(List par0List, EaglercraftRandom par1Random, int par2, int par3, int par4,
+ int par5, int par6) {
+ StructureBoundingBox var7 = StructureBoundingBox.getComponentToAddBoundingBox(par2, par3, par4, -1, -3, 0, 5,
+ 10, 8, par5);
+ return isAboveGround(var7) && StructureComponent.findIntersecting(par0List, var7) == null
+ ? new ComponentNetherBridgeEnd(par6, par1Random, var7, par5)
+ : null;
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ EaglercraftRandom var4 = new EaglercraftRandom((long) this.fillSeed);
+ int var5;
+ int var6;
+ int var7;
+
+ for (var5 = 0; var5 <= 4; ++var5) {
+ for (var6 = 3; var6 <= 4; ++var6) {
+ var7 = var4.nextInt(8);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, var5, var6, 0, var5, var6, var7,
+ Block.netherBrick.blockID, Block.netherBrick.blockID, false);
+ }
+ }
+
+ var5 = var4.nextInt(8);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 5, 0, 0, 5, var5, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ var5 = var4.nextInt(8);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 5, 0, 4, 5, var5, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+
+ for (var5 = 0; var5 <= 4; ++var5) {
+ var6 = var4.nextInt(5);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, var5, 2, 0, var5, 2, var6,
+ Block.netherBrick.blockID, Block.netherBrick.blockID, false);
+ }
+
+ for (var5 = 0; var5 <= 4; ++var5) {
+ for (var6 = 0; var6 <= 1; ++var6) {
+ var7 = var4.nextInt(3);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, var5, var6, 0, var5, var6, var7,
+ Block.netherBrick.blockID, Block.netherBrick.blockID, false);
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeEntrance.java b/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeEntrance.java
new file mode 100644
index 0000000..8847023
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeEntrance.java
@@ -0,0 +1,156 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentNetherBridgeEntrance extends ComponentNetherBridgePiece {
+ public ComponentNetherBridgeEntrance(int par1, EaglercraftRandom par2Random, StructureBoundingBox par3StructureBoundingBox,
+ int par4) {
+ super(par1);
+ this.coordBaseMode = par4;
+ this.boundingBox = par3StructureBoundingBox;
+ }
+
+ /**
+ * Initiates construction of the Structure Component picked, at the current
+ * Location of StructGen
+ */
+ public void buildComponent(StructureComponent par1StructureComponent, List par2List, EaglercraftRandom par3Random) {
+ this.getNextComponentNormal((ComponentNetherBridgeStartPiece) par1StructureComponent, par2List, par3Random, 5,
+ 3, true);
+ }
+
+ /**
+ * Creates and returns a new component piece. Or null if it could not find
+ * enough room to place it.
+ */
+ public static ComponentNetherBridgeEntrance createValidComponent(List par0List, EaglercraftRandom par1Random, int par2,
+ int par3, int par4, int par5, int par6) {
+ StructureBoundingBox var7 = StructureBoundingBox.getComponentToAddBoundingBox(par2, par3, par4, -5, -3, 0, 13,
+ 14, 13, par5);
+ return isAboveGround(var7) && StructureComponent.findIntersecting(par0List, var7) == null
+ ? new ComponentNetherBridgeEntrance(par6, par1Random, var7, par5)
+ : null;
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 3, 0, 12, 4, 12, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 5, 0, 12, 13, 12, 0, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 5, 0, 1, 12, 12, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 11, 5, 0, 12, 12, 12, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 2, 5, 11, 4, 12, 12, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 8, 5, 11, 10, 12, 12, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 5, 9, 11, 7, 12, 12, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 2, 5, 0, 4, 12, 1, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 8, 5, 0, 10, 12, 1, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 5, 9, 0, 7, 12, 1, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 2, 11, 2, 10, 12, 10, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 5, 8, 0, 7, 8, 0, Block.netherFence.blockID,
+ Block.netherFence.blockID, false);
+ int var4;
+
+ for (var4 = 1; var4 <= 11; var4 += 2) {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, var4, 10, 0, var4, 11, 0,
+ Block.netherFence.blockID, Block.netherFence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, var4, 10, 12, var4, 11, 12,
+ Block.netherFence.blockID, Block.netherFence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 10, var4, 0, 11, var4,
+ Block.netherFence.blockID, Block.netherFence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 12, 10, var4, 12, 11, var4,
+ Block.netherFence.blockID, Block.netherFence.blockID, false);
+ this.placeBlockAtCurrentPosition(par1World, Block.netherBrick.blockID, 0, var4, 13, 0,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.netherBrick.blockID, 0, var4, 13, 12,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.netherBrick.blockID, 0, 0, 13, var4,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.netherBrick.blockID, 0, 12, 13, var4,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.netherFence.blockID, 0, var4 + 1, 13, 0,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.netherFence.blockID, 0, var4 + 1, 13, 12,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.netherFence.blockID, 0, 0, 13, var4 + 1,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.netherFence.blockID, 0, 12, 13, var4 + 1,
+ par3StructureBoundingBox);
+ }
+
+ this.placeBlockAtCurrentPosition(par1World, Block.netherFence.blockID, 0, 0, 13, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.netherFence.blockID, 0, 0, 13, 12, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.netherFence.blockID, 0, 0, 13, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.netherFence.blockID, 0, 12, 13, 0, par3StructureBoundingBox);
+
+ for (var4 = 3; var4 <= 9; var4 += 2) {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 7, var4, 1, 8, var4, Block.netherFence.blockID,
+ Block.netherFence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 11, 7, var4, 11, 8, var4,
+ Block.netherFence.blockID, Block.netherFence.blockID, false);
+ }
+
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 2, 0, 8, 2, 12, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 2, 4, 12, 2, 8, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 0, 0, 8, 1, 3, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 0, 9, 8, 1, 12, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 0, 4, 3, 1, 8, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 9, 0, 4, 12, 1, 8, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ int var5;
+
+ for (var4 = 4; var4 <= 8; ++var4) {
+ for (var5 = 0; var5 <= 2; ++var5) {
+ this.fillCurrentPositionBlocksDownwards(par1World, Block.netherBrick.blockID, 0, var4, -1, var5,
+ par3StructureBoundingBox);
+ this.fillCurrentPositionBlocksDownwards(par1World, Block.netherBrick.blockID, 0, var4, -1, 12 - var5,
+ par3StructureBoundingBox);
+ }
+ }
+
+ for (var4 = 0; var4 <= 2; ++var4) {
+ for (var5 = 4; var5 <= 8; ++var5) {
+ this.fillCurrentPositionBlocksDownwards(par1World, Block.netherBrick.blockID, 0, var4, -1, var5,
+ par3StructureBoundingBox);
+ this.fillCurrentPositionBlocksDownwards(par1World, Block.netherBrick.blockID, 0, 12 - var4, -1, var5,
+ par3StructureBoundingBox);
+ }
+ }
+
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 5, 5, 5, 7, 5, 7, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 6, 1, 6, 6, 4, 6, 0, 0, false);
+ this.placeBlockAtCurrentPosition(par1World, Block.netherBrick.blockID, 0, 6, 0, 6, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.lavaMoving.blockID, 0, 6, 5, 6, par3StructureBoundingBox);
+ var4 = this.getXWithOffset(6, 6);
+ var5 = this.getYWithOffset(5);
+ int var6 = this.getZWithOffset(6, 6);
+
+ if (par3StructureBoundingBox.isVecInside(var4, var5, var6)) {
+ par1World.scheduledUpdatesAreImmediate = true;
+ Block.blocksList[Block.lavaMoving.blockID].updateTick(par1World, var4, var5, var6, par2Random);
+ par1World.scheduledUpdatesAreImmediate = false;
+ }
+
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeNetherStalkRoom.java b/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeNetherStalkRoom.java
new file mode 100644
index 0000000..35a4578
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeNetherStalkRoom.java
@@ -0,0 +1,216 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentNetherBridgeNetherStalkRoom extends ComponentNetherBridgePiece {
+ public ComponentNetherBridgeNetherStalkRoom(int par1, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox, int par4) {
+ super(par1);
+ this.coordBaseMode = par4;
+ this.boundingBox = par3StructureBoundingBox;
+ }
+
+ /**
+ * Initiates construction of the Structure Component picked, at the current
+ * Location of StructGen
+ */
+ public void buildComponent(StructureComponent par1StructureComponent, List par2List, EaglercraftRandom par3Random) {
+ this.getNextComponentNormal((ComponentNetherBridgeStartPiece) par1StructureComponent, par2List, par3Random, 5,
+ 3, true);
+ this.getNextComponentNormal((ComponentNetherBridgeStartPiece) par1StructureComponent, par2List, par3Random, 5,
+ 11, true);
+ }
+
+ /**
+ * Creates and returns a new component piece. Or null if it could not find
+ * enough room to place it.
+ */
+ public static ComponentNetherBridgeNetherStalkRoom createValidComponent(List par0List, EaglercraftRandom par1Random, int par2,
+ int par3, int par4, int par5, int par6) {
+ StructureBoundingBox var7 = StructureBoundingBox.getComponentToAddBoundingBox(par2, par3, par4, -5, -3, 0, 13,
+ 14, 13, par5);
+ return isAboveGround(var7) && StructureComponent.findIntersecting(par0List, var7) == null
+ ? new ComponentNetherBridgeNetherStalkRoom(par6, par1Random, var7, par5)
+ : null;
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 3, 0, 12, 4, 12, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 5, 0, 12, 13, 12, 0, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 5, 0, 1, 12, 12, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 11, 5, 0, 12, 12, 12, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 2, 5, 11, 4, 12, 12, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 8, 5, 11, 10, 12, 12, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 5, 9, 11, 7, 12, 12, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 2, 5, 0, 4, 12, 1, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 8, 5, 0, 10, 12, 1, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 5, 9, 0, 7, 12, 1, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 2, 11, 2, 10, 12, 10, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ int var4;
+
+ for (var4 = 1; var4 <= 11; var4 += 2) {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, var4, 10, 0, var4, 11, 0,
+ Block.netherFence.blockID, Block.netherFence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, var4, 10, 12, var4, 11, 12,
+ Block.netherFence.blockID, Block.netherFence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 10, var4, 0, 11, var4,
+ Block.netherFence.blockID, Block.netherFence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 12, 10, var4, 12, 11, var4,
+ Block.netherFence.blockID, Block.netherFence.blockID, false);
+ this.placeBlockAtCurrentPosition(par1World, Block.netherBrick.blockID, 0, var4, 13, 0,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.netherBrick.blockID, 0, var4, 13, 12,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.netherBrick.blockID, 0, 0, 13, var4,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.netherBrick.blockID, 0, 12, 13, var4,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.netherFence.blockID, 0, var4 + 1, 13, 0,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.netherFence.blockID, 0, var4 + 1, 13, 12,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.netherFence.blockID, 0, 0, 13, var4 + 1,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.netherFence.blockID, 0, 12, 13, var4 + 1,
+ par3StructureBoundingBox);
+ }
+
+ this.placeBlockAtCurrentPosition(par1World, Block.netherFence.blockID, 0, 0, 13, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.netherFence.blockID, 0, 0, 13, 12, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.netherFence.blockID, 0, 0, 13, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.netherFence.blockID, 0, 12, 13, 0, par3StructureBoundingBox);
+
+ for (var4 = 3; var4 <= 9; var4 += 2) {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 7, var4, 1, 8, var4, Block.netherFence.blockID,
+ Block.netherFence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 11, 7, var4, 11, 8, var4,
+ Block.netherFence.blockID, Block.netherFence.blockID, false);
+ }
+
+ var4 = this.getMetadataWithOffset(Block.stairsNetherBrick.blockID, 3);
+ int var5;
+ int var6;
+ int var7;
+
+ for (var5 = 0; var5 <= 6; ++var5) {
+ var6 = var5 + 4;
+
+ for (var7 = 5; var7 <= 7; ++var7) {
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsNetherBrick.blockID, var4, var7, 5 + var5, var6,
+ par3StructureBoundingBox);
+ }
+
+ if (var6 >= 5 && var6 <= 8) {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 5, 5, var6, 7, var5 + 4, var6,
+ Block.netherBrick.blockID, Block.netherBrick.blockID, false);
+ } else if (var6 >= 9 && var6 <= 10) {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 5, 8, var6, 7, var5 + 4, var6,
+ Block.netherBrick.blockID, Block.netherBrick.blockID, false);
+ }
+
+ if (var5 >= 1) {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 5, 6 + var5, var6, 7, 9 + var5, var6, 0, 0,
+ false);
+ }
+ }
+
+ for (var5 = 5; var5 <= 7; ++var5) {
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsNetherBrick.blockID, var4, var5, 12, 11,
+ par3StructureBoundingBox);
+ }
+
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 5, 6, 7, 5, 7, 7, Block.netherFence.blockID,
+ Block.netherFence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 7, 6, 7, 7, 7, 7, Block.netherFence.blockID,
+ Block.netherFence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 5, 13, 12, 7, 13, 12, 0, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 2, 5, 2, 3, 5, 3, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 2, 5, 9, 3, 5, 10, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 2, 5, 4, 2, 5, 8, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 9, 5, 2, 10, 5, 3, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 9, 5, 9, 10, 5, 10, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 10, 5, 4, 10, 5, 8, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ var5 = this.getMetadataWithOffset(Block.stairsNetherBrick.blockID, 0);
+ var6 = this.getMetadataWithOffset(Block.stairsNetherBrick.blockID, 1);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsNetherBrick.blockID, var6, 4, 5, 2,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsNetherBrick.blockID, var6, 4, 5, 3,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsNetherBrick.blockID, var6, 4, 5, 9,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsNetherBrick.blockID, var6, 4, 5, 10,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsNetherBrick.blockID, var5, 8, 5, 2,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsNetherBrick.blockID, var5, 8, 5, 3,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsNetherBrick.blockID, var5, 8, 5, 9,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsNetherBrick.blockID, var5, 8, 5, 10,
+ par3StructureBoundingBox);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 3, 4, 4, 4, 4, 8, Block.slowSand.blockID,
+ Block.slowSand.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 8, 4, 4, 9, 4, 8, Block.slowSand.blockID,
+ Block.slowSand.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 3, 5, 4, 4, 5, 8, Block.netherStalk.blockID,
+ Block.netherStalk.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 8, 5, 4, 9, 5, 8, Block.netherStalk.blockID,
+ Block.netherStalk.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 2, 0, 8, 2, 12, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 2, 4, 12, 2, 8, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 0, 0, 8, 1, 3, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 0, 9, 8, 1, 12, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 0, 4, 3, 1, 8, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 9, 0, 4, 12, 1, 8, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ int var8;
+
+ for (var7 = 4; var7 <= 8; ++var7) {
+ for (var8 = 0; var8 <= 2; ++var8) {
+ this.fillCurrentPositionBlocksDownwards(par1World, Block.netherBrick.blockID, 0, var7, -1, var8,
+ par3StructureBoundingBox);
+ this.fillCurrentPositionBlocksDownwards(par1World, Block.netherBrick.blockID, 0, var7, -1, 12 - var8,
+ par3StructureBoundingBox);
+ }
+ }
+
+ for (var7 = 0; var7 <= 2; ++var7) {
+ for (var8 = 4; var8 <= 8; ++var8) {
+ this.fillCurrentPositionBlocksDownwards(par1World, Block.netherBrick.blockID, 0, var7, -1, var8,
+ par3StructureBoundingBox);
+ this.fillCurrentPositionBlocksDownwards(par1World, Block.netherBrick.blockID, 0, 12 - var7, -1, var8,
+ par3StructureBoundingBox);
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgePiece.java b/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgePiece.java
new file mode 100644
index 0000000..25b3166
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgePiece.java
@@ -0,0 +1,199 @@
+package net.minecraft.src;
+
+import java.util.Iterator;
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+abstract class ComponentNetherBridgePiece extends StructureComponent {
+ protected ComponentNetherBridgePiece(int par1) {
+ super(par1);
+ }
+
+ private int getTotalWeight(List par1List) {
+ boolean var2 = false;
+ int var3 = 0;
+ StructureNetherBridgePieceWeight var5;
+
+ for (Iterator var4 = par1List.iterator(); var4.hasNext(); var3 += var5.field_78826_b) {
+ var5 = (StructureNetherBridgePieceWeight) var4.next();
+
+ if (var5.field_78824_d > 0 && var5.field_78827_c < var5.field_78824_d) {
+ var2 = true;
+ }
+ }
+
+ return var2 ? var3 : -1;
+ }
+
+ private ComponentNetherBridgePiece getNextComponent(
+ ComponentNetherBridgeStartPiece par1ComponentNetherBridgeStartPiece, List par2List, List par3List,
+ EaglercraftRandom par4Random, int par5, int par6, int par7, int par8, int par9) {
+ int var10 = this.getTotalWeight(par2List);
+ boolean var11 = var10 > 0 && par9 <= 30;
+ int var12 = 0;
+
+ while (var12 < 5 && var11) {
+ ++var12;
+ int var13 = par4Random.nextInt(var10);
+ Iterator var14 = par2List.iterator();
+
+ while (var14.hasNext()) {
+ StructureNetherBridgePieceWeight var15 = (StructureNetherBridgePieceWeight) var14.next();
+ var13 -= var15.field_78826_b;
+
+ if (var13 < 0) {
+ if (!var15.func_78822_a(par9)
+ || var15 == par1ComponentNetherBridgeStartPiece.theNetherBridgePieceWeight
+ && !var15.field_78825_e) {
+ break;
+ }
+
+ ComponentNetherBridgePiece var16 = StructureNetherBridgePieces.createNextComponent(var15, par3List,
+ par4Random, par5, par6, par7, par8, par9);
+
+ if (var16 != null) {
+ ++var15.field_78827_c;
+ par1ComponentNetherBridgeStartPiece.theNetherBridgePieceWeight = var15;
+
+ if (!var15.func_78823_a()) {
+ par2List.remove(var15);
+ }
+
+ return var16;
+ }
+ }
+ }
+ }
+
+ return ComponentNetherBridgeEnd.func_74971_a(par3List, par4Random, par5, par6, par7, par8, par9);
+ }
+
+ /**
+ * Finds a random component to tack on to the bridge. Or builds the end.
+ */
+ private StructureComponent getNextComponent(ComponentNetherBridgeStartPiece par1ComponentNetherBridgeStartPiece,
+ List par2List, EaglercraftRandom par3Random, int par4, int par5, int par6, int par7, int par8, boolean par9) {
+ if (Math.abs(par4 - par1ComponentNetherBridgeStartPiece.getBoundingBox().minX) <= 112
+ && Math.abs(par6 - par1ComponentNetherBridgeStartPiece.getBoundingBox().minZ) <= 112) {
+ List var10 = par1ComponentNetherBridgeStartPiece.primaryWeights;
+
+ if (par9) {
+ var10 = par1ComponentNetherBridgeStartPiece.secondaryWeights;
+ }
+
+ ComponentNetherBridgePiece var11 = this.getNextComponent(par1ComponentNetherBridgeStartPiece, var10,
+ par2List, par3Random, par4, par5, par6, par7, par8 + 1);
+
+ if (var11 != null) {
+ par2List.add(var11);
+ par1ComponentNetherBridgeStartPiece.field_74967_d.add(var11);
+ }
+
+ return var11;
+ } else {
+ return ComponentNetherBridgeEnd.func_74971_a(par2List, par3Random, par4, par5, par6, par7, par8);
+ }
+ }
+
+ /**
+ * Gets the next component in any cardinal direction
+ */
+ protected StructureComponent getNextComponentNormal(
+ ComponentNetherBridgeStartPiece par1ComponentNetherBridgeStartPiece, List par2List, EaglercraftRandom par3Random,
+ int par4, int par5, boolean par6) {
+ switch (this.coordBaseMode) {
+ case 0:
+ return this.getNextComponent(par1ComponentNetherBridgeStartPiece, par2List, par3Random,
+ this.boundingBox.minX + par4, this.boundingBox.minY + par5, this.boundingBox.maxZ + 1,
+ this.coordBaseMode, this.getComponentType(), par6);
+
+ case 1:
+ return this.getNextComponent(par1ComponentNetherBridgeStartPiece, par2List, par3Random,
+ this.boundingBox.minX - 1, this.boundingBox.minY + par5, this.boundingBox.minZ + par4,
+ this.coordBaseMode, this.getComponentType(), par6);
+
+ case 2:
+ return this.getNextComponent(par1ComponentNetherBridgeStartPiece, par2List, par3Random,
+ this.boundingBox.minX + par4, this.boundingBox.minY + par5, this.boundingBox.minZ - 1,
+ this.coordBaseMode, this.getComponentType(), par6);
+
+ case 3:
+ return this.getNextComponent(par1ComponentNetherBridgeStartPiece, par2List, par3Random,
+ this.boundingBox.maxX + 1, this.boundingBox.minY + par5, this.boundingBox.minZ + par4,
+ this.coordBaseMode, this.getComponentType(), par6);
+
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Gets the next component in the +/- X direction
+ */
+ protected StructureComponent getNextComponentX(ComponentNetherBridgeStartPiece par1ComponentNetherBridgeStartPiece,
+ List par2List, EaglercraftRandom par3Random, int par4, int par5, boolean par6) {
+ switch (this.coordBaseMode) {
+ case 0:
+ return this.getNextComponent(par1ComponentNetherBridgeStartPiece, par2List, par3Random,
+ this.boundingBox.minX - 1, this.boundingBox.minY + par4, this.boundingBox.minZ + par5, 1,
+ this.getComponentType(), par6);
+
+ case 1:
+ return this.getNextComponent(par1ComponentNetherBridgeStartPiece, par2List, par3Random,
+ this.boundingBox.minX + par5, this.boundingBox.minY + par4, this.boundingBox.minZ - 1, 2,
+ this.getComponentType(), par6);
+
+ case 2:
+ return this.getNextComponent(par1ComponentNetherBridgeStartPiece, par2List, par3Random,
+ this.boundingBox.minX - 1, this.boundingBox.minY + par4, this.boundingBox.minZ + par5, 1,
+ this.getComponentType(), par6);
+
+ case 3:
+ return this.getNextComponent(par1ComponentNetherBridgeStartPiece, par2List, par3Random,
+ this.boundingBox.minX + par5, this.boundingBox.minY + par4, this.boundingBox.minZ - 1, 2,
+ this.getComponentType(), par6);
+
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Gets the next component in the +/- Z direction
+ */
+ protected StructureComponent getNextComponentZ(ComponentNetherBridgeStartPiece par1ComponentNetherBridgeStartPiece,
+ List par2List, EaglercraftRandom par3Random, int par4, int par5, boolean par6) {
+ switch (this.coordBaseMode) {
+ case 0:
+ return this.getNextComponent(par1ComponentNetherBridgeStartPiece, par2List, par3Random,
+ this.boundingBox.maxX + 1, this.boundingBox.minY + par4, this.boundingBox.minZ + par5, 3,
+ this.getComponentType(), par6);
+
+ case 1:
+ return this.getNextComponent(par1ComponentNetherBridgeStartPiece, par2List, par3Random,
+ this.boundingBox.minX + par5, this.boundingBox.minY + par4, this.boundingBox.maxZ + 1, 0,
+ this.getComponentType(), par6);
+
+ case 2:
+ return this.getNextComponent(par1ComponentNetherBridgeStartPiece, par2List, par3Random,
+ this.boundingBox.maxX + 1, this.boundingBox.minY + par4, this.boundingBox.minZ + par5, 3,
+ this.getComponentType(), par6);
+
+ case 3:
+ return this.getNextComponent(par1ComponentNetherBridgeStartPiece, par2List, par3Random,
+ this.boundingBox.minX + par5, this.boundingBox.minY + par4, this.boundingBox.maxZ + 1, 0,
+ this.getComponentType(), par6);
+
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Checks if the bounding box's minY is > 10
+ */
+ protected static boolean isAboveGround(StructureBoundingBox par0StructureBoundingBox) {
+ return par0StructureBoundingBox != null && par0StructureBoundingBox.minY > 10;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeStairs.java b/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeStairs.java
new file mode 100644
index 0000000..ad16794
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeStairs.java
@@ -0,0 +1,88 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentNetherBridgeStairs extends ComponentNetherBridgePiece {
+ public ComponentNetherBridgeStairs(int par1, EaglercraftRandom par2Random, StructureBoundingBox par3StructureBoundingBox,
+ int par4) {
+ super(par1);
+ this.coordBaseMode = par4;
+ this.boundingBox = par3StructureBoundingBox;
+ }
+
+ /**
+ * Initiates construction of the Structure Component picked, at the current
+ * Location of StructGen
+ */
+ public void buildComponent(StructureComponent par1StructureComponent, List par2List, EaglercraftRandom par3Random) {
+ this.getNextComponentZ((ComponentNetherBridgeStartPiece) par1StructureComponent, par2List, par3Random, 6, 2,
+ false);
+ }
+
+ /**
+ * Creates and returns a new component piece. Or null if it could not find
+ * enough room to place it.
+ */
+ public static ComponentNetherBridgeStairs createValidComponent(List par0List, EaglercraftRandom par1Random, int par2, int par3,
+ int par4, int par5, int par6) {
+ StructureBoundingBox var7 = StructureBoundingBox.getComponentToAddBoundingBox(par2, par3, par4, -2, 0, 0, 7, 11,
+ 7, par5);
+ return isAboveGround(var7) && StructureComponent.findIntersecting(par0List, var7) == null
+ ? new ComponentNetherBridgeStairs(par6, par1Random, var7, par5)
+ : null;
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 0, 0, 6, 1, 6, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 2, 0, 6, 10, 6, 0, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 2, 0, 1, 8, 0, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 5, 2, 0, 6, 8, 0, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 2, 1, 0, 8, 6, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 6, 2, 1, 6, 8, 6, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 2, 6, 5, 8, 6, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 3, 2, 0, 5, 4, Block.netherFence.blockID,
+ Block.netherFence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 6, 3, 2, 6, 5, 2, Block.netherFence.blockID,
+ Block.netherFence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 6, 3, 4, 6, 5, 4, Block.netherFence.blockID,
+ Block.netherFence.blockID, false);
+ this.placeBlockAtCurrentPosition(par1World, Block.netherBrick.blockID, 0, 5, 2, 5, par3StructureBoundingBox);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 2, 5, 4, 3, 5, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 3, 2, 5, 3, 4, 5, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 2, 2, 5, 2, 5, 5, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 2, 5, 1, 6, 5, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 7, 1, 5, 7, 4, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 6, 8, 2, 6, 8, 4, 0, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 2, 6, 0, 4, 8, 0, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 2, 5, 0, 4, 5, 0, Block.netherFence.blockID,
+ Block.netherFence.blockID, false);
+
+ for (int var4 = 0; var4 <= 6; ++var4) {
+ for (int var5 = 0; var5 <= 6; ++var5) {
+ this.fillCurrentPositionBlocksDownwards(par1World, Block.netherBrick.blockID, 0, var4, -1, var5,
+ par3StructureBoundingBox);
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeStartPiece.java b/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeStartPiece.java
new file mode 100644
index 0000000..de07d1f
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeStartPiece.java
@@ -0,0 +1,48 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentNetherBridgeStartPiece extends ComponentNetherBridgeCrossing3 {
+ /** Instance of StructureNetherBridgePieceWeight. */
+ public StructureNetherBridgePieceWeight theNetherBridgePieceWeight;
+
+ /**
+ * Contains the list of valid piece weights for the set of nether bridge
+ * structure pieces.
+ */
+ public List primaryWeights = new ArrayList();
+
+ /**
+ * Contains the list of valid piece weights for the secondary set of nether
+ * bridge structure pieces.
+ */
+ public List secondaryWeights;
+ public ArrayList field_74967_d = new ArrayList();
+
+ public ComponentNetherBridgeStartPiece(EaglercraftRandom par1Random, int par2, int par3) {
+ super(par1Random, par2, par3);
+ StructureNetherBridgePieceWeight[] var4 = StructureNetherBridgePieces.getPrimaryComponents();
+ int var5 = var4.length;
+ int var6;
+ StructureNetherBridgePieceWeight var7;
+
+ for (var6 = 0; var6 < var5; ++var6) {
+ var7 = var4[var6];
+ var7.field_78827_c = 0;
+ this.primaryWeights.add(var7);
+ }
+
+ this.secondaryWeights = new ArrayList();
+ var4 = StructureNetherBridgePieces.getSecondaryComponents();
+ var5 = var4.length;
+
+ for (var6 = 0; var6 < var5; ++var6) {
+ var7 = var4[var6];
+ var7.field_78827_c = 0;
+ this.secondaryWeights.add(var7);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeStraight.java b/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeStraight.java
new file mode 100644
index 0000000..8f4e5ff
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeStraight.java
@@ -0,0 +1,86 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentNetherBridgeStraight extends ComponentNetherBridgePiece {
+ public ComponentNetherBridgeStraight(int par1, EaglercraftRandom par2Random, StructureBoundingBox par3StructureBoundingBox,
+ int par4) {
+ super(par1);
+ this.coordBaseMode = par4;
+ this.boundingBox = par3StructureBoundingBox;
+ }
+
+ /**
+ * Initiates construction of the Structure Component picked, at the current
+ * Location of StructGen
+ */
+ public void buildComponent(StructureComponent par1StructureComponent, List par2List, EaglercraftRandom par3Random) {
+ this.getNextComponentNormal((ComponentNetherBridgeStartPiece) par1StructureComponent, par2List, par3Random, 1,
+ 3, false);
+ }
+
+ /**
+ * Creates and returns a new component piece. Or null if it could not find
+ * enough room to place it.
+ */
+ public static ComponentNetherBridgeStraight createValidComponent(List par0List, EaglercraftRandom par1Random, int par2,
+ int par3, int par4, int par5, int par6) {
+ StructureBoundingBox var7 = StructureBoundingBox.getComponentToAddBoundingBox(par2, par3, par4, -1, -3, 0, 5,
+ 10, 19, par5);
+ return isAboveGround(var7) && StructureComponent.findIntersecting(par0List, var7) == null
+ ? new ComponentNetherBridgeStraight(par6, par1Random, var7, par5)
+ : null;
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 3, 0, 4, 4, 18, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 5, 0, 3, 7, 18, 0, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 5, 0, 0, 5, 18, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 5, 0, 4, 5, 18, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 2, 0, 4, 2, 5, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 2, 13, 4, 2, 18, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 0, 0, 4, 1, 3, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 0, 15, 4, 1, 18, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+
+ for (int var4 = 0; var4 <= 4; ++var4) {
+ for (int var5 = 0; var5 <= 2; ++var5) {
+ this.fillCurrentPositionBlocksDownwards(par1World, Block.netherBrick.blockID, 0, var4, -1, var5,
+ par3StructureBoundingBox);
+ this.fillCurrentPositionBlocksDownwards(par1World, Block.netherBrick.blockID, 0, var4, -1, 18 - var5,
+ par3StructureBoundingBox);
+ }
+ }
+
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 1, 1, 0, 4, 1, Block.netherFence.blockID,
+ Block.netherFence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 3, 4, 0, 4, 4, Block.netherFence.blockID,
+ Block.netherFence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 3, 14, 0, 4, 14, Block.netherFence.blockID,
+ Block.netherFence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 1, 17, 0, 4, 17, Block.netherFence.blockID,
+ Block.netherFence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 1, 1, 4, 4, 1, Block.netherFence.blockID,
+ Block.netherFence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 3, 4, 4, 4, 4, Block.netherFence.blockID,
+ Block.netherFence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 3, 14, 4, 4, 14, Block.netherFence.blockID,
+ Block.netherFence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 1, 17, 4, 4, 17, Block.netherFence.blockID,
+ Block.netherFence.blockID, false);
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeThrone.java b/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeThrone.java
new file mode 100644
index 0000000..285c6bf
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentNetherBridgeThrone.java
@@ -0,0 +1,97 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentNetherBridgeThrone extends ComponentNetherBridgePiece {
+ private boolean hasSpawner;
+
+ public ComponentNetherBridgeThrone(int par1, EaglercraftRandom par2Random, StructureBoundingBox par3StructureBoundingBox,
+ int par4) {
+ super(par1);
+ this.coordBaseMode = par4;
+ this.boundingBox = par3StructureBoundingBox;
+ }
+
+ /**
+ * Creates and returns a new component piece. Or null if it could not find
+ * enough room to place it.
+ */
+ public static ComponentNetherBridgeThrone createValidComponent(List par0List, EaglercraftRandom par1Random, int par2, int par3,
+ int par4, int par5, int par6) {
+ StructureBoundingBox var7 = StructureBoundingBox.getComponentToAddBoundingBox(par2, par3, par4, -2, 0, 0, 7, 8,
+ 9, par5);
+ return isAboveGround(var7) && StructureComponent.findIntersecting(par0List, var7) == null
+ ? new ComponentNetherBridgeThrone(par6, par1Random, var7, par5)
+ : null;
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 2, 0, 6, 7, 7, 0, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 0, 0, 5, 1, 7, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 2, 1, 5, 2, 7, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 3, 2, 5, 3, 7, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 4, 3, 5, 4, 7, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 2, 0, 1, 4, 2, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 5, 2, 0, 5, 4, 2, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 5, 2, 1, 5, 3, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 5, 5, 2, 5, 5, 3, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 5, 3, 0, 5, 8, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 6, 5, 3, 6, 5, 8, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 5, 8, 5, 5, 8, Block.netherBrick.blockID,
+ Block.netherBrick.blockID, false);
+ this.placeBlockAtCurrentPosition(par1World, Block.netherFence.blockID, 0, 1, 6, 3, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.netherFence.blockID, 0, 5, 6, 3, par3StructureBoundingBox);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 6, 3, 0, 6, 8, Block.netherFence.blockID,
+ Block.netherFence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 6, 6, 3, 6, 6, 8, Block.netherFence.blockID,
+ Block.netherFence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 6, 8, 5, 7, 8, Block.netherFence.blockID,
+ Block.netherFence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 2, 8, 8, 4, 8, 8, Block.netherFence.blockID,
+ Block.netherFence.blockID, false);
+ int var4;
+ int var5;
+
+ if (!this.hasSpawner) {
+ var4 = this.getYWithOffset(5);
+ var5 = this.getXWithOffset(3, 5);
+ int var6 = this.getZWithOffset(3, 5);
+
+ if (par3StructureBoundingBox.isVecInside(var5, var4, var6)) {
+ this.hasSpawner = true;
+ par1World.setBlock(var5, var4, var6, Block.mobSpawner.blockID, 0, 2);
+ TileEntityMobSpawner var7 = (TileEntityMobSpawner) par1World.getBlockTileEntity(var5, var4, var6);
+
+ if (var7 != null) {
+ var7.func_98049_a().setMobID("Blaze");
+ }
+ }
+ }
+
+ for (var4 = 0; var4 <= 6; ++var4) {
+ for (var5 = 0; var5 <= 6; ++var5) {
+ this.fillCurrentPositionBlocksDownwards(par1World, Block.netherBrick.blockID, 0, var4, -1, var5,
+ par3StructureBoundingBox);
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentScatteredFeature.java b/sp-server/src/main/java/net/minecraft/src/ComponentScatteredFeature.java
new file mode 100644
index 0000000..1933a29
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentScatteredFeature.java
@@ -0,0 +1,62 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+abstract class ComponentScatteredFeature extends StructureComponent {
+ /** The size of the bounding box for this feature in the X axis */
+ protected final int scatteredFeatureSizeX;
+
+ /** The size of the bounding box for this feature in the Y axis */
+ protected final int scatteredFeatureSizeY;
+
+ /** The size of the bounding box for this feature in the Z axis */
+ protected final int scatteredFeatureSizeZ;
+ protected int field_74936_d = -1;
+
+ protected ComponentScatteredFeature(EaglercraftRandom par1Random, int par2, int par3, int par4, int par5, int par6, int par7) {
+ super(0);
+ this.scatteredFeatureSizeX = par5;
+ this.scatteredFeatureSizeY = par6;
+ this.scatteredFeatureSizeZ = par7;
+ this.coordBaseMode = par1Random.nextInt(4);
+
+ switch (this.coordBaseMode) {
+ case 0:
+ case 2:
+ this.boundingBox = new StructureBoundingBox(par2, par3, par4, par2 + par5 - 1, par3 + par6 - 1,
+ par4 + par7 - 1);
+ break;
+
+ default:
+ this.boundingBox = new StructureBoundingBox(par2, par3, par4, par2 + par7 - 1, par3 + par6 - 1,
+ par4 + par5 - 1);
+ }
+ }
+
+ protected boolean func_74935_a(World par1World, StructureBoundingBox par2StructureBoundingBox, int par3) {
+ if (this.field_74936_d >= 0) {
+ return true;
+ } else {
+ int var4 = 0;
+ int var5 = 0;
+
+ for (int var6 = this.boundingBox.minZ; var6 <= this.boundingBox.maxZ; ++var6) {
+ for (int var7 = this.boundingBox.minX; var7 <= this.boundingBox.maxX; ++var7) {
+ if (par2StructureBoundingBox.isVecInside(var7, 64, var6)) {
+ var4 += Math.max(par1World.getTopSolidOrLiquidBlock(var7, var6),
+ par1World.provider.getAverageGroundLevel());
+ ++var5;
+ }
+ }
+ }
+
+ if (var5 == 0) {
+ return false;
+ } else {
+ this.field_74936_d = var4 / var5;
+ this.boundingBox.offset(0, this.field_74936_d - this.boundingBox.minY + par3, 0);
+ return true;
+ }
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentScatteredFeatureDesertPyramid.java b/sp-server/src/main/java/net/minecraft/src/ComponentScatteredFeatureDesertPyramid.java
new file mode 100644
index 0000000..fa67b7b
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentScatteredFeatureDesertPyramid.java
@@ -0,0 +1,323 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentScatteredFeatureDesertPyramid extends ComponentScatteredFeature {
+ private boolean[] field_74940_h = new boolean[4];
+
+ /** List of items to generate in chests of Temples. */
+ private static final WeightedRandomChestContent[] itemsToGenerateInTemple = new WeightedRandomChestContent[] {
+ new WeightedRandomChestContent(Item.diamond.itemID, 0, 1, 3, 3),
+ new WeightedRandomChestContent(Item.ingotIron.itemID, 0, 1, 5, 10),
+ new WeightedRandomChestContent(Item.ingotGold.itemID, 0, 2, 7, 15),
+ new WeightedRandomChestContent(Item.emerald.itemID, 0, 1, 3, 2),
+ new WeightedRandomChestContent(Item.bone.itemID, 0, 4, 6, 20),
+ new WeightedRandomChestContent(Item.rottenFlesh.itemID, 0, 3, 7, 16) };
+
+ public ComponentScatteredFeatureDesertPyramid(EaglercraftRandom par1Random, int par2, int par3) {
+ super(par1Random, par2, 64, par3, 21, 15, 21);
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, -4, 0, this.scatteredFeatureSizeX - 1, 0,
+ this.scatteredFeatureSizeZ - 1, Block.sandStone.blockID, Block.sandStone.blockID, false);
+ int var4;
+
+ for (var4 = 1; var4 <= 9; ++var4) {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, var4, var4, var4,
+ this.scatteredFeatureSizeX - 1 - var4, var4, this.scatteredFeatureSizeZ - 1 - var4,
+ Block.sandStone.blockID, Block.sandStone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, var4 + 1, var4, var4 + 1,
+ this.scatteredFeatureSizeX - 2 - var4, var4, this.scatteredFeatureSizeZ - 2 - var4, 0, 0, false);
+ }
+
+ int var5;
+
+ for (var4 = 0; var4 < this.scatteredFeatureSizeX; ++var4) {
+ for (var5 = 0; var5 < this.scatteredFeatureSizeZ; ++var5) {
+ this.fillCurrentPositionBlocksDownwards(par1World, Block.sandStone.blockID, 0, var4, -5, var5,
+ par3StructureBoundingBox);
+ }
+ }
+
+ var4 = this.getMetadataWithOffset(Block.stairsSandStone.blockID, 3);
+ var5 = this.getMetadataWithOffset(Block.stairsSandStone.blockID, 2);
+ int var6 = this.getMetadataWithOffset(Block.stairsSandStone.blockID, 0);
+ int var7 = this.getMetadataWithOffset(Block.stairsSandStone.blockID, 1);
+ byte var8 = 1;
+ byte var9 = 11;
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 0, 0, 4, 9, 4, Block.sandStone.blockID, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 10, 1, 3, 10, 3, Block.sandStone.blockID,
+ Block.sandStone.blockID, false);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsSandStone.blockID, var4, 2, 10, 0,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsSandStone.blockID, var5, 2, 10, 4,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsSandStone.blockID, var6, 0, 10, 2,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsSandStone.blockID, var7, 4, 10, 2,
+ par3StructureBoundingBox);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, this.scatteredFeatureSizeX - 5, 0, 0,
+ this.scatteredFeatureSizeX - 1, 9, 4, Block.sandStone.blockID, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, this.scatteredFeatureSizeX - 4, 10, 1,
+ this.scatteredFeatureSizeX - 2, 10, 3, Block.sandStone.blockID, Block.sandStone.blockID, false);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsSandStone.blockID, var4, this.scatteredFeatureSizeX - 3,
+ 10, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsSandStone.blockID, var5, this.scatteredFeatureSizeX - 3,
+ 10, 4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsSandStone.blockID, var6, this.scatteredFeatureSizeX - 5,
+ 10, 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsSandStone.blockID, var7, this.scatteredFeatureSizeX - 1,
+ 10, 2, par3StructureBoundingBox);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 8, 0, 0, 12, 4, 4, Block.sandStone.blockID, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 9, 1, 0, 11, 3, 4, 0, 0, false);
+ this.placeBlockAtCurrentPosition(par1World, Block.sandStone.blockID, 2, 9, 1, 1, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.sandStone.blockID, 2, 9, 2, 1, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.sandStone.blockID, 2, 9, 3, 1, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.sandStone.blockID, 2, 10, 3, 1, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.sandStone.blockID, 2, 11, 3, 1, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.sandStone.blockID, 2, 11, 2, 1, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.sandStone.blockID, 2, 11, 1, 1, par3StructureBoundingBox);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 1, 1, 8, 3, 3, Block.sandStone.blockID, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 1, 2, 8, 2, 2, 0, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 12, 1, 1, 16, 3, 3, Block.sandStone.blockID, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 12, 1, 2, 16, 2, 2, 0, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 5, 4, 5, this.scatteredFeatureSizeX - 6, 4,
+ this.scatteredFeatureSizeZ - 6, Block.sandStone.blockID, Block.sandStone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 9, 4, 9, 11, 4, 11, 0, 0, false);
+ this.fillWithMetadataBlocks(par1World, par3StructureBoundingBox, 8, 1, 8, 8, 3, 8, Block.sandStone.blockID, 2,
+ Block.sandStone.blockID, 2, false);
+ this.fillWithMetadataBlocks(par1World, par3StructureBoundingBox, 12, 1, 8, 12, 3, 8, Block.sandStone.blockID, 2,
+ Block.sandStone.blockID, 2, false);
+ this.fillWithMetadataBlocks(par1World, par3StructureBoundingBox, 8, 1, 12, 8, 3, 12, Block.sandStone.blockID, 2,
+ Block.sandStone.blockID, 2, false);
+ this.fillWithMetadataBlocks(par1World, par3StructureBoundingBox, 12, 1, 12, 12, 3, 12, Block.sandStone.blockID,
+ 2, Block.sandStone.blockID, 2, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 1, 5, 4, 4, 11, Block.sandStone.blockID,
+ Block.sandStone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, this.scatteredFeatureSizeX - 5, 1, 5,
+ this.scatteredFeatureSizeX - 2, 4, 11, Block.sandStone.blockID, Block.sandStone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 6, 7, 9, 6, 7, 11, Block.sandStone.blockID,
+ Block.sandStone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, this.scatteredFeatureSizeX - 7, 7, 9,
+ this.scatteredFeatureSizeX - 7, 7, 11, Block.sandStone.blockID, Block.sandStone.blockID, false);
+ this.fillWithMetadataBlocks(par1World, par3StructureBoundingBox, 5, 5, 9, 5, 7, 11, Block.sandStone.blockID, 2,
+ Block.sandStone.blockID, 2, false);
+ this.fillWithMetadataBlocks(par1World, par3StructureBoundingBox, this.scatteredFeatureSizeX - 6, 5, 9,
+ this.scatteredFeatureSizeX - 6, 7, 11, Block.sandStone.blockID, 2, Block.sandStone.blockID, 2, false);
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, 5, 5, 10, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, 5, 6, 10, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, 6, 6, 10, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, this.scatteredFeatureSizeX - 6, 5, 10,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, this.scatteredFeatureSizeX - 6, 6, 10,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, this.scatteredFeatureSizeX - 7, 6, 10,
+ par3StructureBoundingBox);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 2, 4, 4, 2, 6, 4, 0, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, this.scatteredFeatureSizeX - 3, 4, 4,
+ this.scatteredFeatureSizeX - 3, 6, 4, 0, 0, false);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsSandStone.blockID, var4, 2, 4, 5,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsSandStone.blockID, var4, 2, 3, 4,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsSandStone.blockID, var4, this.scatteredFeatureSizeX - 3,
+ 4, 5, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsSandStone.blockID, var4, this.scatteredFeatureSizeX - 3,
+ 3, 4, par3StructureBoundingBox);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 1, 3, 2, 2, 3, Block.sandStone.blockID,
+ Block.sandStone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, this.scatteredFeatureSizeX - 3, 1, 3,
+ this.scatteredFeatureSizeX - 2, 2, 3, Block.sandStone.blockID, Block.sandStone.blockID, false);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsSandStone.blockID, 0, 1, 1, 2,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsSandStone.blockID, 0, this.scatteredFeatureSizeX - 2, 1,
+ 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneSingleSlab.blockID, 1, 1, 2, 2,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneSingleSlab.blockID, 1, this.scatteredFeatureSizeX - 2, 2,
+ 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsSandStone.blockID, var7, 2, 1, 2,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsSandStone.blockID, var6, this.scatteredFeatureSizeX - 3,
+ 1, 2, par3StructureBoundingBox);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 3, 5, 4, 3, 18, Block.sandStone.blockID,
+ Block.sandStone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, this.scatteredFeatureSizeX - 5, 3, 5,
+ this.scatteredFeatureSizeX - 5, 3, 17, Block.sandStone.blockID, Block.sandStone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 3, 1, 5, 4, 2, 16, 0, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, this.scatteredFeatureSizeX - 6, 1, 5,
+ this.scatteredFeatureSizeX - 5, 2, 16, 0, 0, false);
+ int var10;
+
+ for (var10 = 5; var10 <= 17; var10 += 2) {
+ this.placeBlockAtCurrentPosition(par1World, Block.sandStone.blockID, 2, 4, 1, var10,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.sandStone.blockID, 1, 4, 2, var10,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.sandStone.blockID, 2, this.scatteredFeatureSizeX - 5, 1,
+ var10, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.sandStone.blockID, 1, this.scatteredFeatureSizeX - 5, 2,
+ var10, par3StructureBoundingBox);
+ }
+
+ this.placeBlockAtCurrentPosition(par1World, Block.cloth.blockID, var8, 10, 0, 7, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cloth.blockID, var8, 10, 0, 8, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cloth.blockID, var8, 9, 0, 9, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cloth.blockID, var8, 11, 0, 9, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cloth.blockID, var8, 8, 0, 10, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cloth.blockID, var8, 12, 0, 10, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cloth.blockID, var8, 7, 0, 10, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cloth.blockID, var8, 13, 0, 10, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cloth.blockID, var8, 9, 0, 11, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cloth.blockID, var8, 11, 0, 11, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cloth.blockID, var8, 10, 0, 12, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cloth.blockID, var8, 10, 0, 13, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cloth.blockID, var9, 10, 0, 10, par3StructureBoundingBox);
+
+ for (var10 = 0; var10 <= this.scatteredFeatureSizeX - 1; var10 += this.scatteredFeatureSizeX - 1) {
+ this.placeBlockAtCurrentPosition(par1World, Block.sandStone.blockID, 2, var10, 2, 1,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cloth.blockID, var8, var10, 2, 2,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.sandStone.blockID, 2, var10, 2, 3,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.sandStone.blockID, 2, var10, 3, 1,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cloth.blockID, var8, var10, 3, 2,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.sandStone.blockID, 2, var10, 3, 3,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cloth.blockID, var8, var10, 4, 1,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.sandStone.blockID, 1, var10, 4, 2,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cloth.blockID, var8, var10, 4, 3,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.sandStone.blockID, 2, var10, 5, 1,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cloth.blockID, var8, var10, 5, 2,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.sandStone.blockID, 2, var10, 5, 3,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cloth.blockID, var8, var10, 6, 1,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.sandStone.blockID, 1, var10, 6, 2,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cloth.blockID, var8, var10, 6, 3,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cloth.blockID, var8, var10, 7, 1,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cloth.blockID, var8, var10, 7, 2,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cloth.blockID, var8, var10, 7, 3,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.sandStone.blockID, 2, var10, 8, 1,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.sandStone.blockID, 2, var10, 8, 2,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.sandStone.blockID, 2, var10, 8, 3,
+ par3StructureBoundingBox);
+ }
+
+ for (var10 = 2; var10 <= this.scatteredFeatureSizeX - 3; var10 += this.scatteredFeatureSizeX - 3 - 2) {
+ this.placeBlockAtCurrentPosition(par1World, Block.sandStone.blockID, 2, var10 - 1, 2, 0,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cloth.blockID, var8, var10, 2, 0,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.sandStone.blockID, 2, var10 + 1, 2, 0,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.sandStone.blockID, 2, var10 - 1, 3, 0,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cloth.blockID, var8, var10, 3, 0,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.sandStone.blockID, 2, var10 + 1, 3, 0,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cloth.blockID, var8, var10 - 1, 4, 0,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.sandStone.blockID, 1, var10, 4, 0,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cloth.blockID, var8, var10 + 1, 4, 0,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.sandStone.blockID, 2, var10 - 1, 5, 0,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cloth.blockID, var8, var10, 5, 0,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.sandStone.blockID, 2, var10 + 1, 5, 0,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cloth.blockID, var8, var10 - 1, 6, 0,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.sandStone.blockID, 1, var10, 6, 0,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cloth.blockID, var8, var10 + 1, 6, 0,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cloth.blockID, var8, var10 - 1, 7, 0,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cloth.blockID, var8, var10, 7, 0,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cloth.blockID, var8, var10 + 1, 7, 0,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.sandStone.blockID, 2, var10 - 1, 8, 0,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.sandStone.blockID, 2, var10, 8, 0,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.sandStone.blockID, 2, var10 + 1, 8, 0,
+ par3StructureBoundingBox);
+ }
+
+ this.fillWithMetadataBlocks(par1World, par3StructureBoundingBox, 8, 4, 0, 12, 6, 0, Block.sandStone.blockID, 2,
+ Block.sandStone.blockID, 2, false);
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, 8, 6, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, 12, 6, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cloth.blockID, var8, 9, 5, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.sandStone.blockID, 1, 10, 5, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cloth.blockID, var8, 11, 5, 0, par3StructureBoundingBox);
+ this.fillWithMetadataBlocks(par1World, par3StructureBoundingBox, 8, -14, 8, 12, -11, 12,
+ Block.sandStone.blockID, 2, Block.sandStone.blockID, 2, false);
+ this.fillWithMetadataBlocks(par1World, par3StructureBoundingBox, 8, -10, 8, 12, -10, 12,
+ Block.sandStone.blockID, 1, Block.sandStone.blockID, 1, false);
+ this.fillWithMetadataBlocks(par1World, par3StructureBoundingBox, 8, -9, 8, 12, -9, 12, Block.sandStone.blockID,
+ 2, Block.sandStone.blockID, 2, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 8, -8, 8, 12, -1, 12, Block.sandStone.blockID,
+ Block.sandStone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 9, -11, 9, 11, -1, 11, 0, 0, false);
+ this.placeBlockAtCurrentPosition(par1World, Block.pressurePlateStone.blockID, 0, 10, -11, 10,
+ par3StructureBoundingBox);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 9, -13, 9, 11, -13, 11, Block.tnt.blockID, 0, false);
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, 8, -11, 10, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, 8, -10, 10, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.sandStone.blockID, 1, 7, -10, 10, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.sandStone.blockID, 2, 7, -11, 10, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, 12, -11, 10, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, 12, -10, 10, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.sandStone.blockID, 1, 13, -10, 10, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.sandStone.blockID, 2, 13, -11, 10, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, 10, -11, 8, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, 10, -10, 8, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.sandStone.blockID, 1, 10, -10, 7, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.sandStone.blockID, 2, 10, -11, 7, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, 10, -11, 12, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, 10, -10, 12, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.sandStone.blockID, 1, 10, -10, 13, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.sandStone.blockID, 2, 10, -11, 13, par3StructureBoundingBox);
+
+ for (var10 = 0; var10 < 4; ++var10) {
+ if (!this.field_74940_h[var10]) {
+ int var11 = Direction.offsetX[var10] * 2;
+ int var12 = Direction.offsetZ[var10] * 2;
+ this.field_74940_h[var10] = this.generateStructureChestContents(par1World, par3StructureBoundingBox,
+ par2Random, 10 + var11, -11, 10 + var12,
+ WeightedRandomChestContent.func_92080_a(itemsToGenerateInTemple,
+ new WeightedRandomChestContent[] { Item.enchantedBook.func_92114_b(par2Random) }),
+ 2 + par2Random.nextInt(5));
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentScatteredFeatureJunglePyramid.java b/sp-server/src/main/java/net/minecraft/src/ComponentScatteredFeatureJunglePyramid.java
new file mode 100644
index 0000000..2d1c920
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentScatteredFeatureJunglePyramid.java
@@ -0,0 +1,341 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentScatteredFeatureJunglePyramid extends ComponentScatteredFeature {
+ private boolean field_74947_h;
+ private boolean field_74948_i;
+ private boolean field_74945_j;
+ private boolean field_74946_k;
+
+ /** List of Chest contents to be generated in the Jungle Pyramid chests. */
+ private static final WeightedRandomChestContent[] junglePyramidsChestContents = new WeightedRandomChestContent[] {
+ new WeightedRandomChestContent(Item.diamond.itemID, 0, 1, 3, 3),
+ new WeightedRandomChestContent(Item.ingotIron.itemID, 0, 1, 5, 10),
+ new WeightedRandomChestContent(Item.ingotGold.itemID, 0, 2, 7, 15),
+ new WeightedRandomChestContent(Item.emerald.itemID, 0, 1, 3, 2),
+ new WeightedRandomChestContent(Item.bone.itemID, 0, 4, 6, 20),
+ new WeightedRandomChestContent(Item.rottenFlesh.itemID, 0, 3, 7, 16) };
+
+ /**
+ * List of Dispenser contents to be generated in the Jungle Pyramid dispensers.
+ */
+ private static final WeightedRandomChestContent[] junglePyramidsDispenserContents = new WeightedRandomChestContent[] {
+ new WeightedRandomChestContent(Item.arrow.itemID, 0, 2, 7, 30) };
+
+ /** List of random stones to be generated in the Jungle Pyramid. */
+ private static StructureScatteredFeatureStones junglePyramidsRandomScatteredStones = new StructureScatteredFeatureStones(
+ (ComponentScatteredFeaturePieces2) null);
+
+ public ComponentScatteredFeatureJunglePyramid(EaglercraftRandom par1Random, int par2, int par3) {
+ super(par1Random, par2, 64, par3, 12, 10, 15);
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ if (!this.func_74935_a(par1World, par3StructureBoundingBox, 0)) {
+ return false;
+ } else {
+ int var4 = this.getMetadataWithOffset(Block.stairsCobblestone.blockID, 3);
+ int var5 = this.getMetadataWithOffset(Block.stairsCobblestone.blockID, 2);
+ int var6 = this.getMetadataWithOffset(Block.stairsCobblestone.blockID, 0);
+ int var7 = this.getMetadataWithOffset(Block.stairsCobblestone.blockID, 1);
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 0, -4, 0, this.scatteredFeatureSizeX - 1,
+ 0, this.scatteredFeatureSizeZ - 1, false, par2Random, junglePyramidsRandomScatteredStones);
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 2, 1, 2, 9, 2, 2, false, par2Random,
+ junglePyramidsRandomScatteredStones);
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 2, 1, 12, 9, 2, 12, false, par2Random,
+ junglePyramidsRandomScatteredStones);
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 2, 1, 3, 2, 2, 11, false, par2Random,
+ junglePyramidsRandomScatteredStones);
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 9, 1, 3, 9, 2, 11, false, par2Random,
+ junglePyramidsRandomScatteredStones);
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 1, 3, 1, 10, 6, 1, false, par2Random,
+ junglePyramidsRandomScatteredStones);
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 1, 3, 13, 10, 6, 13, false, par2Random,
+ junglePyramidsRandomScatteredStones);
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 1, 3, 2, 1, 6, 12, false, par2Random,
+ junglePyramidsRandomScatteredStones);
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 10, 3, 2, 10, 6, 12, false, par2Random,
+ junglePyramidsRandomScatteredStones);
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 2, 3, 2, 9, 3, 12, false, par2Random,
+ junglePyramidsRandomScatteredStones);
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 2, 6, 2, 9, 6, 12, false, par2Random,
+ junglePyramidsRandomScatteredStones);
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 3, 7, 3, 8, 7, 11, false, par2Random,
+ junglePyramidsRandomScatteredStones);
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 4, 8, 4, 7, 8, 10, false, par2Random,
+ junglePyramidsRandomScatteredStones);
+ this.fillWithAir(par1World, par3StructureBoundingBox, 3, 1, 3, 8, 2, 11);
+ this.fillWithAir(par1World, par3StructureBoundingBox, 4, 3, 6, 7, 3, 9);
+ this.fillWithAir(par1World, par3StructureBoundingBox, 2, 4, 2, 9, 5, 12);
+ this.fillWithAir(par1World, par3StructureBoundingBox, 4, 6, 5, 7, 6, 9);
+ this.fillWithAir(par1World, par3StructureBoundingBox, 5, 7, 6, 6, 7, 8);
+ this.fillWithAir(par1World, par3StructureBoundingBox, 5, 1, 2, 6, 2, 2);
+ this.fillWithAir(par1World, par3StructureBoundingBox, 5, 2, 12, 6, 2, 12);
+ this.fillWithAir(par1World, par3StructureBoundingBox, 5, 5, 1, 6, 5, 1);
+ this.fillWithAir(par1World, par3StructureBoundingBox, 5, 5, 13, 6, 5, 13);
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, 1, 5, 5, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, 10, 5, 5, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, 1, 5, 9, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, 10, 5, 9, par3StructureBoundingBox);
+ int var8;
+
+ for (var8 = 0; var8 <= 14; var8 += 14) {
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 2, 4, var8, 2, 5, var8, false,
+ par2Random, junglePyramidsRandomScatteredStones);
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 4, 4, var8, 4, 5, var8, false,
+ par2Random, junglePyramidsRandomScatteredStones);
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 7, 4, var8, 7, 5, var8, false,
+ par2Random, junglePyramidsRandomScatteredStones);
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 9, 4, var8, 9, 5, var8, false,
+ par2Random, junglePyramidsRandomScatteredStones);
+ }
+
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 5, 6, 0, 6, 6, 0, false, par2Random,
+ junglePyramidsRandomScatteredStones);
+
+ for (var8 = 0; var8 <= 11; var8 += 11) {
+ for (int var9 = 2; var9 <= 12; var9 += 2) {
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, var8, 4, var9, var8, 5, var9,
+ false, par2Random, junglePyramidsRandomScatteredStones);
+ }
+
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, var8, 6, 5, var8, 6, 5, false,
+ par2Random, junglePyramidsRandomScatteredStones);
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, var8, 6, 9, var8, 6, 9, false,
+ par2Random, junglePyramidsRandomScatteredStones);
+ }
+
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 2, 7, 2, 2, 9, 2, false, par2Random,
+ junglePyramidsRandomScatteredStones);
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 9, 7, 2, 9, 9, 2, false, par2Random,
+ junglePyramidsRandomScatteredStones);
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 2, 7, 12, 2, 9, 12, false, par2Random,
+ junglePyramidsRandomScatteredStones);
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 9, 7, 12, 9, 9, 12, false, par2Random,
+ junglePyramidsRandomScatteredStones);
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 4, 9, 4, 4, 9, 4, false, par2Random,
+ junglePyramidsRandomScatteredStones);
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 7, 9, 4, 7, 9, 4, false, par2Random,
+ junglePyramidsRandomScatteredStones);
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 4, 9, 10, 4, 9, 10, false, par2Random,
+ junglePyramidsRandomScatteredStones);
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 7, 9, 10, 7, 9, 10, false, par2Random,
+ junglePyramidsRandomScatteredStones);
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 5, 9, 7, 6, 9, 7, false, par2Random,
+ junglePyramidsRandomScatteredStones);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsCobblestone.blockID, var4, 5, 9, 6,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsCobblestone.blockID, var4, 6, 9, 6,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsCobblestone.blockID, var5, 5, 9, 8,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsCobblestone.blockID, var5, 6, 9, 8,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsCobblestone.blockID, var4, 4, 0, 0,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsCobblestone.blockID, var4, 5, 0, 0,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsCobblestone.blockID, var4, 6, 0, 0,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsCobblestone.blockID, var4, 7, 0, 0,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsCobblestone.blockID, var4, 4, 1, 8,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsCobblestone.blockID, var4, 4, 2, 9,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsCobblestone.blockID, var4, 4, 3, 10,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsCobblestone.blockID, var4, 7, 1, 8,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsCobblestone.blockID, var4, 7, 2, 9,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsCobblestone.blockID, var4, 7, 3, 10,
+ par3StructureBoundingBox);
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 4, 1, 9, 4, 1, 9, false, par2Random,
+ junglePyramidsRandomScatteredStones);
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 7, 1, 9, 7, 1, 9, false, par2Random,
+ junglePyramidsRandomScatteredStones);
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 4, 1, 10, 7, 2, 10, false, par2Random,
+ junglePyramidsRandomScatteredStones);
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 5, 4, 5, 6, 4, 5, false, par2Random,
+ junglePyramidsRandomScatteredStones);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsCobblestone.blockID, var6, 4, 4, 5,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsCobblestone.blockID, var7, 7, 4, 5,
+ par3StructureBoundingBox);
+
+ for (var8 = 0; var8 < 4; ++var8) {
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsCobblestone.blockID, var5, 5, 0 - var8,
+ 6 + var8, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsCobblestone.blockID, var5, 6, 0 - var8,
+ 6 + var8, par3StructureBoundingBox);
+ this.fillWithAir(par1World, par3StructureBoundingBox, 5, 0 - var8, 7 + var8, 6, 0 - var8, 9 + var8);
+ }
+
+ this.fillWithAir(par1World, par3StructureBoundingBox, 1, -3, 12, 10, -1, 13);
+ this.fillWithAir(par1World, par3StructureBoundingBox, 1, -3, 1, 3, -1, 13);
+ this.fillWithAir(par1World, par3StructureBoundingBox, 1, -3, 1, 9, -1, 5);
+
+ for (var8 = 1; var8 <= 13; var8 += 2) {
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 1, -3, var8, 1, -2, var8, false,
+ par2Random, junglePyramidsRandomScatteredStones);
+ }
+
+ for (var8 = 2; var8 <= 12; var8 += 2) {
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 1, -1, var8, 3, -1, var8, false,
+ par2Random, junglePyramidsRandomScatteredStones);
+ }
+
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 2, -2, 1, 5, -2, 1, false, par2Random,
+ junglePyramidsRandomScatteredStones);
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 7, -2, 1, 9, -2, 1, false, par2Random,
+ junglePyramidsRandomScatteredStones);
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 6, -3, 1, 6, -3, 1, false, par2Random,
+ junglePyramidsRandomScatteredStones);
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 6, -1, 1, 6, -1, 1, false, par2Random,
+ junglePyramidsRandomScatteredStones);
+ this.placeBlockAtCurrentPosition(par1World, Block.tripWireSource.blockID,
+ this.getMetadataWithOffset(Block.tripWireSource.blockID, 3) | 4, 1, -3, 8,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.tripWireSource.blockID,
+ this.getMetadataWithOffset(Block.tripWireSource.blockID, 1) | 4, 4, -3, 8,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.tripWire.blockID, 4, 2, -3, 8, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.tripWire.blockID, 4, 3, -3, 8, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.redstoneWire.blockID, 0, 5, -3, 7,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.redstoneWire.blockID, 0, 5, -3, 6,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.redstoneWire.blockID, 0, 5, -3, 5,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.redstoneWire.blockID, 0, 5, -3, 4,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.redstoneWire.blockID, 0, 5, -3, 3,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.redstoneWire.blockID, 0, 5, -3, 2,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.redstoneWire.blockID, 0, 5, -3, 1,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.redstoneWire.blockID, 0, 4, -3, 1,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestoneMossy.blockID, 0, 3, -3, 1,
+ par3StructureBoundingBox);
+
+ if (!this.field_74945_j) {
+ this.field_74945_j = this.generateStructureDispenserContents(par1World, par3StructureBoundingBox,
+ par2Random, 3, -2, 1, 2, junglePyramidsDispenserContents, 2);
+ }
+
+ this.placeBlockAtCurrentPosition(par1World, Block.vine.blockID, 15, 3, -2, 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.tripWireSource.blockID,
+ this.getMetadataWithOffset(Block.tripWireSource.blockID, 2) | 4, 7, -3, 1,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.tripWireSource.blockID,
+ this.getMetadataWithOffset(Block.tripWireSource.blockID, 0) | 4, 7, -3, 5,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.tripWire.blockID, 4, 7, -3, 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.tripWire.blockID, 4, 7, -3, 3, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.tripWire.blockID, 4, 7, -3, 4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.redstoneWire.blockID, 0, 8, -3, 6,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.redstoneWire.blockID, 0, 9, -3, 6,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.redstoneWire.blockID, 0, 9, -3, 5,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestoneMossy.blockID, 0, 9, -3, 4,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.redstoneWire.blockID, 0, 9, -2, 4,
+ par3StructureBoundingBox);
+
+ if (!this.field_74946_k) {
+ this.field_74946_k = this.generateStructureDispenserContents(par1World, par3StructureBoundingBox,
+ par2Random, 9, -2, 3, 4, junglePyramidsDispenserContents, 2);
+ }
+
+ this.placeBlockAtCurrentPosition(par1World, Block.vine.blockID, 15, 8, -1, 3, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.vine.blockID, 15, 8, -2, 3, par3StructureBoundingBox);
+
+ if (!this.field_74947_h) {
+ this.field_74947_h = this.generateStructureChestContents(par1World, par3StructureBoundingBox,
+ par2Random, 8, -3, 3,
+ WeightedRandomChestContent.func_92080_a(junglePyramidsChestContents,
+ new WeightedRandomChestContent[] { Item.enchantedBook.func_92114_b(par2Random) }),
+ 2 + par2Random.nextInt(5));
+ }
+
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestoneMossy.blockID, 0, 9, -3, 2,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestoneMossy.blockID, 0, 8, -3, 1,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestoneMossy.blockID, 0, 4, -3, 5,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestoneMossy.blockID, 0, 5, -2, 5,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestoneMossy.blockID, 0, 5, -1, 5,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestoneMossy.blockID, 0, 6, -3, 5,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestoneMossy.blockID, 0, 7, -2, 5,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestoneMossy.blockID, 0, 7, -1, 5,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestoneMossy.blockID, 0, 8, -3, 5,
+ par3StructureBoundingBox);
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 9, -1, 1, 9, -1, 5, false, par2Random,
+ junglePyramidsRandomScatteredStones);
+ this.fillWithAir(par1World, par3StructureBoundingBox, 8, -3, 8, 10, -1, 10);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 3, 8, -2, 11,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 3, 9, -2, 11,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 3, 10, -2, 11,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.lever.blockID,
+ BlockLever.invertMetadata(this.getMetadataWithOffset(Block.lever.blockID, 2)), 8, -2, 12,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.lever.blockID,
+ BlockLever.invertMetadata(this.getMetadataWithOffset(Block.lever.blockID, 2)), 9, -2, 12,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.lever.blockID,
+ BlockLever.invertMetadata(this.getMetadataWithOffset(Block.lever.blockID, 2)), 10, -2, 12,
+ par3StructureBoundingBox);
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 8, -3, 8, 8, -3, 10, false, par2Random,
+ junglePyramidsRandomScatteredStones);
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 10, -3, 8, 10, -3, 10, false, par2Random,
+ junglePyramidsRandomScatteredStones);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestoneMossy.blockID, 0, 10, -2, 9,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.redstoneWire.blockID, 0, 8, -2, 9,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.redstoneWire.blockID, 0, 8, -2, 10,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.redstoneWire.blockID, 0, 10, -1, 9,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.pistonStickyBase.blockID, 1, 9, -2, 8,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.pistonStickyBase.blockID,
+ this.getMetadataWithOffset(Block.pistonStickyBase.blockID, 4), 10, -2, 8, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.pistonStickyBase.blockID,
+ this.getMetadataWithOffset(Block.pistonStickyBase.blockID, 4), 10, -1, 8, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.redstoneRepeaterIdle.blockID,
+ this.getMetadataWithOffset(Block.redstoneRepeaterIdle.blockID, 2), 10, -2, 10,
+ par3StructureBoundingBox);
+
+ if (!this.field_74948_i) {
+ this.field_74948_i = this.generateStructureChestContents(par1World, par3StructureBoundingBox,
+ par2Random, 9, -3, 10,
+ WeightedRandomChestContent.func_92080_a(junglePyramidsChestContents,
+ new WeightedRandomChestContent[] { Item.enchantedBook.func_92114_b(par2Random) }),
+ 2 + par2Random.nextInt(5));
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentScatteredFeaturePieces2.java b/sp-server/src/main/java/net/minecraft/src/ComponentScatteredFeaturePieces2.java
new file mode 100644
index 0000000..1db727b
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentScatteredFeaturePieces2.java
@@ -0,0 +1,4 @@
+package net.minecraft.src;
+
+class ComponentScatteredFeaturePieces2 {
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentScatteredFeatureSwampHut.java b/sp-server/src/main/java/net/minecraft/src/ComponentScatteredFeatureSwampHut.java
new file mode 100644
index 0000000..1b177ea
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentScatteredFeatureSwampHut.java
@@ -0,0 +1,93 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentScatteredFeatureSwampHut extends ComponentScatteredFeature {
+ /** Whether this swamp hut has a witch. */
+ private boolean hasWitch;
+
+ public ComponentScatteredFeatureSwampHut(EaglercraftRandom par1Random, int par2, int par3) {
+ super(par1Random, par2, 64, par3, 7, 5, 9);
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ if (!this.func_74935_a(par1World, par3StructureBoundingBox, 0)) {
+ return false;
+ } else {
+ this.fillWithMetadataBlocks(par1World, par3StructureBoundingBox, 1, 1, 1, 5, 1, 7, Block.planks.blockID, 1,
+ Block.planks.blockID, 1, false);
+ this.fillWithMetadataBlocks(par1World, par3StructureBoundingBox, 1, 4, 2, 5, 4, 7, Block.planks.blockID, 1,
+ Block.planks.blockID, 1, false);
+ this.fillWithMetadataBlocks(par1World, par3StructureBoundingBox, 2, 1, 0, 4, 1, 0, Block.planks.blockID, 1,
+ Block.planks.blockID, 1, false);
+ this.fillWithMetadataBlocks(par1World, par3StructureBoundingBox, 2, 2, 2, 3, 3, 2, Block.planks.blockID, 1,
+ Block.planks.blockID, 1, false);
+ this.fillWithMetadataBlocks(par1World, par3StructureBoundingBox, 1, 2, 3, 1, 3, 6, Block.planks.blockID, 1,
+ Block.planks.blockID, 1, false);
+ this.fillWithMetadataBlocks(par1World, par3StructureBoundingBox, 5, 2, 3, 5, 3, 6, Block.planks.blockID, 1,
+ Block.planks.blockID, 1, false);
+ this.fillWithMetadataBlocks(par1World, par3StructureBoundingBox, 2, 2, 7, 4, 3, 7, Block.planks.blockID, 1,
+ Block.planks.blockID, 1, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 0, 2, 1, 3, 2, Block.wood.blockID,
+ Block.wood.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 5, 0, 2, 5, 3, 2, Block.wood.blockID,
+ Block.wood.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 0, 7, 1, 3, 7, Block.wood.blockID,
+ Block.wood.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 5, 0, 7, 5, 3, 7, Block.wood.blockID,
+ Block.wood.blockID, false);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, 2, 3, 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, 3, 3, 7, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, 1, 3, 4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, 5, 3, 4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, 5, 3, 5, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.flowerPot.blockID, 7, 1, 3, 5, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.workbench.blockID, 0, 3, 2, 6, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cauldron.blockID, 0, 4, 2, 6, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, 1, 2, 1, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, 5, 2, 1, par3StructureBoundingBox);
+ int var4 = this.getMetadataWithOffset(Block.stairsWoodOak.blockID, 3);
+ int var5 = this.getMetadataWithOffset(Block.stairsWoodOak.blockID, 1);
+ int var6 = this.getMetadataWithOffset(Block.stairsWoodOak.blockID, 0);
+ int var7 = this.getMetadataWithOffset(Block.stairsWoodOak.blockID, 2);
+ this.fillWithMetadataBlocks(par1World, par3StructureBoundingBox, 0, 4, 1, 6, 4, 1,
+ Block.stairsWoodSpruce.blockID, var4, Block.stairsWoodSpruce.blockID, var4, false);
+ this.fillWithMetadataBlocks(par1World, par3StructureBoundingBox, 0, 4, 2, 0, 4, 7,
+ Block.stairsWoodSpruce.blockID, var6, Block.stairsWoodSpruce.blockID, var6, false);
+ this.fillWithMetadataBlocks(par1World, par3StructureBoundingBox, 6, 4, 2, 6, 4, 7,
+ Block.stairsWoodSpruce.blockID, var5, Block.stairsWoodSpruce.blockID, var5, false);
+ this.fillWithMetadataBlocks(par1World, par3StructureBoundingBox, 0, 4, 8, 6, 4, 8,
+ Block.stairsWoodSpruce.blockID, var7, Block.stairsWoodSpruce.blockID, var7, false);
+ int var8;
+ int var9;
+
+ for (var8 = 2; var8 <= 7; var8 += 5) {
+ for (var9 = 1; var9 <= 5; var9 += 4) {
+ this.fillCurrentPositionBlocksDownwards(par1World, Block.wood.blockID, 0, var9, -1, var8,
+ par3StructureBoundingBox);
+ }
+ }
+
+ if (!this.hasWitch) {
+ var8 = this.getXWithOffset(2, 5);
+ var9 = this.getYWithOffset(2);
+ int var10 = this.getZWithOffset(2, 5);
+
+ if (par3StructureBoundingBox.isVecInside(var8, var9, var10)) {
+ this.hasWitch = true;
+ EntityWitch var11 = new EntityWitch(par1World);
+ var11.setLocationAndAngles((double) var8 + 0.5D, (double) var9, (double) var10 + 0.5D, 0.0F, 0.0F);
+ var11.initCreature();
+ par1World.spawnEntityInWorld(var11);
+ }
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentStronghold.java b/sp-server/src/main/java/net/minecraft/src/ComponentStronghold.java
new file mode 100644
index 0000000..091544a
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentStronghold.java
@@ -0,0 +1,211 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+abstract class ComponentStronghold extends StructureComponent {
+ protected ComponentStronghold(int par1) {
+ super(par1);
+ }
+
+ /**
+ * builds a door of the enumerated types (empty opening is a door)
+ */
+ protected void placeDoor(World par1World, EaglercraftRandom par2Random, StructureBoundingBox par3StructureBoundingBox,
+ EnumDoor par4EnumDoor, int par5, int par6, int par7) {
+ switch (EnumDoorHelper.doorEnum[par4EnumDoor.ordinal()]) {
+ case 1:
+ default:
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, par5, par6, par7, par5 + 3 - 1, par6 + 3 - 1, par7,
+ 0, 0, false);
+ break;
+
+ case 2:
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, par5, par6, par7,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, par5, par6 + 1, par7,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, par5, par6 + 2, par7,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, par5 + 1, par6 + 2, par7,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, par5 + 2, par6 + 2, par7,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, par5 + 2, par6 + 1, par7,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, par5 + 2, par6, par7,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.doorWood.blockID, 0, par5 + 1, par6, par7,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.doorWood.blockID, 8, par5 + 1, par6 + 1, par7,
+ par3StructureBoundingBox);
+ break;
+
+ case 3:
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, par5 + 1, par6, par7, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, par5 + 1, par6 + 1, par7, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fenceIron.blockID, 0, par5, par6, par7,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fenceIron.blockID, 0, par5, par6 + 1, par7,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fenceIron.blockID, 0, par5, par6 + 2, par7,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fenceIron.blockID, 0, par5 + 1, par6 + 2, par7,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fenceIron.blockID, 0, par5 + 2, par6 + 2, par7,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fenceIron.blockID, 0, par5 + 2, par6 + 1, par7,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fenceIron.blockID, 0, par5 + 2, par6, par7,
+ par3StructureBoundingBox);
+ break;
+
+ case 4:
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, par5, par6, par7,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, par5, par6 + 1, par7,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, par5, par6 + 2, par7,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, par5 + 1, par6 + 2, par7,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, par5 + 2, par6 + 2, par7,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, par5 + 2, par6 + 1, par7,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, par5 + 2, par6, par7,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.doorIron.blockID, 0, par5 + 1, par6, par7,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.doorIron.blockID, 8, par5 + 1, par6 + 1, par7,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneButton.blockID,
+ this.getMetadataWithOffset(Block.stoneButton.blockID, 4), par5 + 2, par6 + 1, par7 + 1,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneButton.blockID,
+ this.getMetadataWithOffset(Block.stoneButton.blockID, 3), par5 + 2, par6 + 1, par7 - 1,
+ par3StructureBoundingBox);
+ }
+ }
+
+ protected EnumDoor getRandomDoor(EaglercraftRandom par1Random) {
+ int var2 = par1Random.nextInt(5);
+
+ switch (var2) {
+ case 0:
+ case 1:
+ default:
+ return EnumDoor.OPENING;
+
+ case 2:
+ return EnumDoor.WOOD_DOOR;
+
+ case 3:
+ return EnumDoor.GRATES;
+
+ case 4:
+ return EnumDoor.IRON_DOOR;
+ }
+ }
+
+ /**
+ * Gets the next component in any cardinal direction
+ */
+ protected StructureComponent getNextComponentNormal(ComponentStrongholdStairs2 par1ComponentStrongholdStairs2,
+ List par2List, EaglercraftRandom par3Random, int par4, int par5) {
+ switch (this.coordBaseMode) {
+ case 0:
+ return StructureStrongholdPieces.getNextValidComponentAccess(par1ComponentStrongholdStairs2, par2List,
+ par3Random, this.boundingBox.minX + par4, this.boundingBox.minY + par5, this.boundingBox.maxZ + 1,
+ this.coordBaseMode, this.getComponentType());
+
+ case 1:
+ return StructureStrongholdPieces.getNextValidComponentAccess(par1ComponentStrongholdStairs2, par2List,
+ par3Random, this.boundingBox.minX - 1, this.boundingBox.minY + par5, this.boundingBox.minZ + par4,
+ this.coordBaseMode, this.getComponentType());
+
+ case 2:
+ return StructureStrongholdPieces.getNextValidComponentAccess(par1ComponentStrongholdStairs2, par2List,
+ par3Random, this.boundingBox.minX + par4, this.boundingBox.minY + par5, this.boundingBox.minZ - 1,
+ this.coordBaseMode, this.getComponentType());
+
+ case 3:
+ return StructureStrongholdPieces.getNextValidComponentAccess(par1ComponentStrongholdStairs2, par2List,
+ par3Random, this.boundingBox.maxX + 1, this.boundingBox.minY + par5, this.boundingBox.minZ + par4,
+ this.coordBaseMode, this.getComponentType());
+
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Gets the next component in the +/- X direction
+ */
+ protected StructureComponent getNextComponentX(ComponentStrongholdStairs2 par1ComponentStrongholdStairs2,
+ List par2List, EaglercraftRandom par3Random, int par4, int par5) {
+ switch (this.coordBaseMode) {
+ case 0:
+ return StructureStrongholdPieces.getNextValidComponentAccess(par1ComponentStrongholdStairs2, par2List,
+ par3Random, this.boundingBox.minX - 1, this.boundingBox.minY + par4, this.boundingBox.minZ + par5,
+ 1, this.getComponentType());
+
+ case 1:
+ return StructureStrongholdPieces.getNextValidComponentAccess(par1ComponentStrongholdStairs2, par2List,
+ par3Random, this.boundingBox.minX + par5, this.boundingBox.minY + par4, this.boundingBox.minZ - 1,
+ 2, this.getComponentType());
+
+ case 2:
+ return StructureStrongholdPieces.getNextValidComponentAccess(par1ComponentStrongholdStairs2, par2List,
+ par3Random, this.boundingBox.minX - 1, this.boundingBox.minY + par4, this.boundingBox.minZ + par5,
+ 1, this.getComponentType());
+
+ case 3:
+ return StructureStrongholdPieces.getNextValidComponentAccess(par1ComponentStrongholdStairs2, par2List,
+ par3Random, this.boundingBox.minX + par5, this.boundingBox.minY + par4, this.boundingBox.minZ - 1,
+ 2, this.getComponentType());
+
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Gets the next component in the +/- Z direction
+ */
+ protected StructureComponent getNextComponentZ(ComponentStrongholdStairs2 par1ComponentStrongholdStairs2,
+ List par2List, EaglercraftRandom par3Random, int par4, int par5) {
+ switch (this.coordBaseMode) {
+ case 0:
+ return StructureStrongholdPieces.getNextValidComponentAccess(par1ComponentStrongholdStairs2, par2List,
+ par3Random, this.boundingBox.maxX + 1, this.boundingBox.minY + par4, this.boundingBox.minZ + par5,
+ 3, this.getComponentType());
+
+ case 1:
+ return StructureStrongholdPieces.getNextValidComponentAccess(par1ComponentStrongholdStairs2, par2List,
+ par3Random, this.boundingBox.minX + par5, this.boundingBox.minY + par4, this.boundingBox.maxZ + 1,
+ 0, this.getComponentType());
+
+ case 2:
+ return StructureStrongholdPieces.getNextValidComponentAccess(par1ComponentStrongholdStairs2, par2List,
+ par3Random, this.boundingBox.maxX + 1, this.boundingBox.minY + par4, this.boundingBox.minZ + par5,
+ 3, this.getComponentType());
+
+ case 3:
+ return StructureStrongholdPieces.getNextValidComponentAccess(par1ComponentStrongholdStairs2, par2List,
+ par3Random, this.boundingBox.minX + par5, this.boundingBox.minY + par4, this.boundingBox.maxZ + 1,
+ 0, this.getComponentType());
+
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * returns false if the Structure Bounding Box goes below 10
+ */
+ protected static boolean canStrongholdGoDeeper(StructureBoundingBox par0StructureBoundingBox) {
+ return par0StructureBoundingBox != null && par0StructureBoundingBox.minY > 10;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentStrongholdChestCorridor.java b/sp-server/src/main/java/net/minecraft/src/ComponentStrongholdChestCorridor.java
new file mode 100644
index 0000000..98242f9
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentStrongholdChestCorridor.java
@@ -0,0 +1,99 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentStrongholdChestCorridor extends ComponentStronghold {
+ /** List of items that Stronghold chests can contain. */
+ private static final WeightedRandomChestContent[] strongholdChestContents = new WeightedRandomChestContent[] {
+ new WeightedRandomChestContent(Item.enderPearl.itemID, 0, 1, 1, 10),
+ new WeightedRandomChestContent(Item.diamond.itemID, 0, 1, 3, 3),
+ new WeightedRandomChestContent(Item.ingotIron.itemID, 0, 1, 5, 10),
+ new WeightedRandomChestContent(Item.ingotGold.itemID, 0, 1, 3, 5),
+ new WeightedRandomChestContent(Item.redstone.itemID, 0, 4, 9, 5),
+ new WeightedRandomChestContent(Item.bread.itemID, 0, 1, 3, 15),
+ new WeightedRandomChestContent(Item.appleRed.itemID, 0, 1, 3, 15),
+ new WeightedRandomChestContent(Item.pickaxeIron.itemID, 0, 1, 1, 5),
+ new WeightedRandomChestContent(Item.swordIron.itemID, 0, 1, 1, 5),
+ new WeightedRandomChestContent(Item.plateIron.itemID, 0, 1, 1, 5),
+ new WeightedRandomChestContent(Item.helmetIron.itemID, 0, 1, 1, 5),
+ new WeightedRandomChestContent(Item.legsIron.itemID, 0, 1, 1, 5),
+ new WeightedRandomChestContent(Item.bootsIron.itemID, 0, 1, 1, 5),
+ new WeightedRandomChestContent(Item.appleGold.itemID, 0, 1, 1, 1) };
+ private final EnumDoor doorType;
+ private boolean hasMadeChest;
+
+ public ComponentStrongholdChestCorridor(int par1, EaglercraftRandom par2Random, StructureBoundingBox par3StructureBoundingBox,
+ int par4) {
+ super(par1);
+ this.coordBaseMode = par4;
+ this.doorType = this.getRandomDoor(par2Random);
+ this.boundingBox = par3StructureBoundingBox;
+ }
+
+ /**
+ * Initiates construction of the Structure Component picked, at the current
+ * Location of StructGen
+ */
+ public void buildComponent(StructureComponent par1StructureComponent, List par2List, EaglercraftRandom par3Random) {
+ this.getNextComponentNormal((ComponentStrongholdStairs2) par1StructureComponent, par2List, par3Random, 1, 1);
+ }
+
+ public static ComponentStrongholdChestCorridor findValidPlacement(List par0List, EaglercraftRandom par1Random, int par2,
+ int par3, int par4, int par5, int par6) {
+ StructureBoundingBox var7 = StructureBoundingBox.getComponentToAddBoundingBox(par2, par3, par4, -1, -1, 0, 5, 5,
+ 7, par5);
+ return canStrongholdGoDeeper(var7) && StructureComponent.findIntersecting(par0List, var7) == null
+ ? new ComponentStrongholdChestCorridor(par6, par1Random, var7, par5)
+ : null;
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ if (this.isLiquidInStructureBoundingBox(par1World, par3StructureBoundingBox)) {
+ return false;
+ } else {
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 0, 0, 0, 4, 4, 6, true, par2Random,
+ StructureStrongholdPieces.getStrongholdStones());
+ this.placeDoor(par1World, par2Random, par3StructureBoundingBox, this.doorType, 1, 1, 0);
+ this.placeDoor(par1World, par2Random, par3StructureBoundingBox, EnumDoor.OPENING, 1, 1, 6);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 3, 1, 2, 3, 1, 4, Block.stoneBrick.blockID,
+ Block.stoneBrick.blockID, false);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneSingleSlab.blockID, 5, 3, 1, 1,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneSingleSlab.blockID, 5, 3, 1, 5,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneSingleSlab.blockID, 5, 3, 2, 2,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneSingleSlab.blockID, 5, 3, 2, 4,
+ par3StructureBoundingBox);
+ int var4;
+
+ for (var4 = 2; var4 <= 4; ++var4) {
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneSingleSlab.blockID, 5, 2, 1, var4,
+ par3StructureBoundingBox);
+ }
+
+ if (!this.hasMadeChest) {
+ var4 = this.getYWithOffset(2);
+ int var5 = this.getXWithOffset(3, 3);
+ int var6 = this.getZWithOffset(3, 3);
+
+ if (par3StructureBoundingBox.isVecInside(var5, var4, var6)) {
+ this.hasMadeChest = true;
+ this.generateStructureChestContents(par1World, par3StructureBoundingBox, par2Random, 3, 2, 3,
+ WeightedRandomChestContent.func_92080_a(strongholdChestContents,
+ new WeightedRandomChestContent[] { Item.enchantedBook.func_92114_b(par2Random) }),
+ 2 + par2Random.nextInt(2));
+ }
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentStrongholdCorridor.java b/sp-server/src/main/java/net/minecraft/src/ComponentStrongholdCorridor.java
new file mode 100644
index 0000000..ee79452
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentStrongholdCorridor.java
@@ -0,0 +1,90 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentStrongholdCorridor extends ComponentStronghold {
+ private final int field_74993_a;
+
+ public ComponentStrongholdCorridor(int par1, EaglercraftRandom par2Random, StructureBoundingBox par3StructureBoundingBox,
+ int par4) {
+ super(par1);
+ this.coordBaseMode = par4;
+ this.boundingBox = par3StructureBoundingBox;
+ this.field_74993_a = par4 != 2 && par4 != 0 ? par3StructureBoundingBox.getXSize()
+ : par3StructureBoundingBox.getZSize();
+ }
+
+ public static StructureBoundingBox func_74992_a(List par0List, EaglercraftRandom par1Random, int par2, int par3, int par4,
+ int par5) {
+ StructureBoundingBox var7 = StructureBoundingBox.getComponentToAddBoundingBox(par2, par3, par4, -1, -1, 0, 5, 5,
+ 4, par5);
+ StructureComponent var8 = StructureComponent.findIntersecting(par0List, var7);
+
+ if (var8 == null) {
+ return null;
+ } else {
+ if (var8.getBoundingBox().minY == var7.minY) {
+ for (int var9 = 3; var9 >= 1; --var9) {
+ var7 = StructureBoundingBox.getComponentToAddBoundingBox(par2, par3, par4, -1, -1, 0, 5, 5,
+ var9 - 1, par5);
+
+ if (!var8.getBoundingBox().intersectsWith(var7)) {
+ return StructureBoundingBox.getComponentToAddBoundingBox(par2, par3, par4, -1, -1, 0, 5, 5,
+ var9, par5);
+ }
+ }
+ }
+
+ return null;
+ }
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ if (this.isLiquidInStructureBoundingBox(par1World, par3StructureBoundingBox)) {
+ return false;
+ } else {
+ for (int var4 = 0; var4 < this.field_74993_a; ++var4) {
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, 0, 0, var4,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, 1, 0, var4,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, 2, 0, var4,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, 3, 0, var4,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, 4, 0, var4,
+ par3StructureBoundingBox);
+
+ for (int var5 = 1; var5 <= 3; ++var5) {
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, 0, var5, var4,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, 1, var5, var4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, 2, var5, var4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, 3, var5, var4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, 4, var5, var4,
+ par3StructureBoundingBox);
+ }
+
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, 0, 4, var4,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, 1, 4, var4,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, 2, 4, var4,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, 3, 4, var4,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, 4, 4, var4,
+ par3StructureBoundingBox);
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentStrongholdCrossing.java b/sp-server/src/main/java/net/minecraft/src/ComponentStrongholdCrossing.java
new file mode 100644
index 0000000..4289f47
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentStrongholdCrossing.java
@@ -0,0 +1,127 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentStrongholdCrossing extends ComponentStronghold {
+ protected final EnumDoor doorType;
+ private boolean field_74996_b;
+ private boolean field_74997_c;
+ private boolean field_74995_d;
+ private boolean field_74999_h;
+
+ public ComponentStrongholdCrossing(int par1, EaglercraftRandom par2Random, StructureBoundingBox par3StructureBoundingBox,
+ int par4) {
+ super(par1);
+ this.coordBaseMode = par4;
+ this.doorType = this.getRandomDoor(par2Random);
+ this.boundingBox = par3StructureBoundingBox;
+ this.field_74996_b = par2Random.nextBoolean();
+ this.field_74997_c = par2Random.nextBoolean();
+ this.field_74995_d = par2Random.nextBoolean();
+ this.field_74999_h = par2Random.nextInt(3) > 0;
+ }
+
+ /**
+ * Initiates construction of the Structure Component picked, at the current
+ * Location of StructGen
+ */
+ public void buildComponent(StructureComponent par1StructureComponent, List par2List, EaglercraftRandom par3Random) {
+ int var4 = 3;
+ int var5 = 5;
+
+ if (this.coordBaseMode == 1 || this.coordBaseMode == 2) {
+ var4 = 8 - var4;
+ var5 = 8 - var5;
+ }
+
+ this.getNextComponentNormal((ComponentStrongholdStairs2) par1StructureComponent, par2List, par3Random, 5, 1);
+
+ if (this.field_74996_b) {
+ this.getNextComponentX((ComponentStrongholdStairs2) par1StructureComponent, par2List, par3Random, var4, 1);
+ }
+
+ if (this.field_74997_c) {
+ this.getNextComponentX((ComponentStrongholdStairs2) par1StructureComponent, par2List, par3Random, var5, 7);
+ }
+
+ if (this.field_74995_d) {
+ this.getNextComponentZ((ComponentStrongholdStairs2) par1StructureComponent, par2List, par3Random, var4, 1);
+ }
+
+ if (this.field_74999_h) {
+ this.getNextComponentZ((ComponentStrongholdStairs2) par1StructureComponent, par2List, par3Random, var5, 7);
+ }
+ }
+
+ public static ComponentStrongholdCrossing findValidPlacement(List par0List, EaglercraftRandom par1Random, int par2, int par3,
+ int par4, int par5, int par6) {
+ StructureBoundingBox var7 = StructureBoundingBox.getComponentToAddBoundingBox(par2, par3, par4, -4, -3, 0, 10,
+ 9, 11, par5);
+ return canStrongholdGoDeeper(var7) && StructureComponent.findIntersecting(par0List, var7) == null
+ ? new ComponentStrongholdCrossing(par6, par1Random, var7, par5)
+ : null;
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ if (this.isLiquidInStructureBoundingBox(par1World, par3StructureBoundingBox)) {
+ return false;
+ } else {
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 0, 0, 0, 9, 8, 10, true, par2Random,
+ StructureStrongholdPieces.getStrongholdStones());
+ this.placeDoor(par1World, par2Random, par3StructureBoundingBox, this.doorType, 4, 3, 0);
+
+ if (this.field_74996_b) {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 3, 1, 0, 5, 3, 0, 0, false);
+ }
+
+ if (this.field_74995_d) {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 9, 3, 1, 9, 5, 3, 0, 0, false);
+ }
+
+ if (this.field_74997_c) {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 5, 7, 0, 7, 9, 0, 0, false);
+ }
+
+ if (this.field_74999_h) {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 9, 5, 7, 9, 7, 9, 0, 0, false);
+ }
+
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 5, 1, 10, 7, 3, 10, 0, 0, false);
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 1, 2, 1, 8, 2, 6, false, par2Random,
+ StructureStrongholdPieces.getStrongholdStones());
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 4, 1, 5, 4, 4, 9, false, par2Random,
+ StructureStrongholdPieces.getStrongholdStones());
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 8, 1, 5, 8, 4, 9, false, par2Random,
+ StructureStrongholdPieces.getStrongholdStones());
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 1, 4, 7, 3, 4, 9, false, par2Random,
+ StructureStrongholdPieces.getStrongholdStones());
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 1, 3, 5, 3, 3, 6, false, par2Random,
+ StructureStrongholdPieces.getStrongholdStones());
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 3, 4, 3, 3, 4, Block.stoneSingleSlab.blockID,
+ Block.stoneSingleSlab.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 4, 6, 3, 4, 6, Block.stoneSingleSlab.blockID,
+ Block.stoneSingleSlab.blockID, false);
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 5, 1, 7, 7, 1, 8, false, par2Random,
+ StructureStrongholdPieces.getStrongholdStones());
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 5, 1, 9, 7, 1, 9, Block.stoneSingleSlab.blockID,
+ Block.stoneSingleSlab.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 5, 2, 7, 7, 2, 7, Block.stoneSingleSlab.blockID,
+ Block.stoneSingleSlab.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 5, 7, 4, 5, 9, Block.stoneSingleSlab.blockID,
+ Block.stoneSingleSlab.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 8, 5, 7, 8, 5, 9, Block.stoneSingleSlab.blockID,
+ Block.stoneSingleSlab.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 5, 5, 7, 7, 5, 9, Block.stoneDoubleSlab.blockID,
+ Block.stoneDoubleSlab.blockID, false);
+ this.placeBlockAtCurrentPosition(par1World, Block.torchWood.blockID, 0, 6, 5, 6, par3StructureBoundingBox);
+ return true;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentStrongholdLeftTurn.java b/sp-server/src/main/java/net/minecraft/src/ComponentStrongholdLeftTurn.java
new file mode 100644
index 0000000..b3c2ebc
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentStrongholdLeftTurn.java
@@ -0,0 +1,61 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentStrongholdLeftTurn extends ComponentStronghold {
+ protected final EnumDoor doorType;
+
+ public ComponentStrongholdLeftTurn(int par1, EaglercraftRandom par2Random, StructureBoundingBox par3StructureBoundingBox,
+ int par4) {
+ super(par1);
+ this.coordBaseMode = par4;
+ this.doorType = this.getRandomDoor(par2Random);
+ this.boundingBox = par3StructureBoundingBox;
+ }
+
+ /**
+ * Initiates construction of the Structure Component picked, at the current
+ * Location of StructGen
+ */
+ public void buildComponent(StructureComponent par1StructureComponent, List par2List, EaglercraftRandom par3Random) {
+ if (this.coordBaseMode != 2 && this.coordBaseMode != 3) {
+ this.getNextComponentZ((ComponentStrongholdStairs2) par1StructureComponent, par2List, par3Random, 1, 1);
+ } else {
+ this.getNextComponentX((ComponentStrongholdStairs2) par1StructureComponent, par2List, par3Random, 1, 1);
+ }
+ }
+
+ public static ComponentStrongholdLeftTurn findValidPlacement(List par0List, EaglercraftRandom par1Random, int par2, int par3,
+ int par4, int par5, int par6) {
+ StructureBoundingBox var7 = StructureBoundingBox.getComponentToAddBoundingBox(par2, par3, par4, -1, -1, 0, 5, 5,
+ 5, par5);
+ return canStrongholdGoDeeper(var7) && StructureComponent.findIntersecting(par0List, var7) == null
+ ? new ComponentStrongholdLeftTurn(par6, par1Random, var7, par5)
+ : null;
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ if (this.isLiquidInStructureBoundingBox(par1World, par3StructureBoundingBox)) {
+ return false;
+ } else {
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 0, 0, 0, 4, 4, 4, true, par2Random,
+ StructureStrongholdPieces.getStrongholdStones());
+ this.placeDoor(par1World, par2Random, par3StructureBoundingBox, this.doorType, 1, 1, 0);
+
+ if (this.coordBaseMode != 2 && this.coordBaseMode != 3) {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 1, 1, 4, 3, 3, 0, 0, false);
+ } else {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 1, 1, 0, 3, 3, 0, 0, false);
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentStrongholdLibrary.java b/sp-server/src/main/java/net/minecraft/src/ComponentStrongholdLibrary.java
new file mode 100644
index 0000000..0faffc9
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentStrongholdLibrary.java
@@ -0,0 +1,203 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentStrongholdLibrary extends ComponentStronghold {
+ /** List of items that Stronghold Library chests can contain. */
+ private static final WeightedRandomChestContent[] strongholdLibraryChestContents = new WeightedRandomChestContent[] {
+ new WeightedRandomChestContent(Item.book.itemID, 0, 1, 3, 20),
+ new WeightedRandomChestContent(Item.paper.itemID, 0, 2, 7, 20),
+ new WeightedRandomChestContent(Item.emptyMap.itemID, 0, 1, 1, 1),
+ new WeightedRandomChestContent(Item.compass.itemID, 0, 1, 1, 1) };
+ protected final EnumDoor doorType;
+ private final boolean isLargeRoom;
+
+ public ComponentStrongholdLibrary(int par1, EaglercraftRandom par2Random, StructureBoundingBox par3StructureBoundingBox,
+ int par4) {
+ super(par1);
+ this.coordBaseMode = par4;
+ this.doorType = this.getRandomDoor(par2Random);
+ this.boundingBox = par3StructureBoundingBox;
+ this.isLargeRoom = par3StructureBoundingBox.getYSize() > 6;
+ }
+
+ public static ComponentStrongholdLibrary findValidPlacement(List par0List, EaglercraftRandom par1Random, int par2, int par3,
+ int par4, int par5, int par6) {
+ StructureBoundingBox var7 = StructureBoundingBox.getComponentToAddBoundingBox(par2, par3, par4, -4, -1, 0, 14,
+ 11, 15, par5);
+
+ if (!canStrongholdGoDeeper(var7) || StructureComponent.findIntersecting(par0List, var7) != null) {
+ var7 = StructureBoundingBox.getComponentToAddBoundingBox(par2, par3, par4, -4, -1, 0, 14, 6, 15, par5);
+
+ if (!canStrongholdGoDeeper(var7) || StructureComponent.findIntersecting(par0List, var7) != null) {
+ return null;
+ }
+ }
+
+ return new ComponentStrongholdLibrary(par6, par1Random, var7, par5);
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ if (this.isLiquidInStructureBoundingBox(par1World, par3StructureBoundingBox)) {
+ return false;
+ } else {
+ byte var4 = 11;
+
+ if (!this.isLargeRoom) {
+ var4 = 6;
+ }
+
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 0, 0, 0, 13, var4 - 1, 14, true,
+ par2Random, StructureStrongholdPieces.getStrongholdStones());
+ this.placeDoor(par1World, par2Random, par3StructureBoundingBox, this.doorType, 4, 1, 0);
+ this.randomlyFillWithBlocks(par1World, par3StructureBoundingBox, par2Random, 0.07F, 2, 1, 1, 11, 4, 13,
+ Block.web.blockID, Block.web.blockID, false);
+ int var7;
+
+ for (var7 = 1; var7 <= 13; ++var7) {
+ if ((var7 - 1) % 4 == 0) {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 1, var7, 1, 4, var7,
+ Block.planks.blockID, Block.planks.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 12, 1, var7, 12, 4, var7,
+ Block.planks.blockID, Block.planks.blockID, false);
+ this.placeBlockAtCurrentPosition(par1World, Block.torchWood.blockID, 0, 2, 3, var7,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.torchWood.blockID, 0, 11, 3, var7,
+ par3StructureBoundingBox);
+
+ if (this.isLargeRoom) {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 6, var7, 1, 9, var7,
+ Block.planks.blockID, Block.planks.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 12, 6, var7, 12, 9, var7,
+ Block.planks.blockID, Block.planks.blockID, false);
+ }
+ } else {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 1, var7, 1, 4, var7,
+ Block.bookShelf.blockID, Block.bookShelf.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 12, 1, var7, 12, 4, var7,
+ Block.bookShelf.blockID, Block.bookShelf.blockID, false);
+
+ if (this.isLargeRoom) {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 6, var7, 1, 9, var7,
+ Block.bookShelf.blockID, Block.bookShelf.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 12, 6, var7, 12, 9, var7,
+ Block.bookShelf.blockID, Block.bookShelf.blockID, false);
+ }
+ }
+ }
+
+ for (var7 = 3; var7 < 12; var7 += 2) {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 3, 1, var7, 4, 3, var7,
+ Block.bookShelf.blockID, Block.bookShelf.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 6, 1, var7, 7, 3, var7,
+ Block.bookShelf.blockID, Block.bookShelf.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 9, 1, var7, 10, 3, var7,
+ Block.bookShelf.blockID, Block.bookShelf.blockID, false);
+ }
+
+ if (this.isLargeRoom) {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 5, 1, 3, 5, 13, Block.planks.blockID,
+ Block.planks.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 10, 5, 1, 12, 5, 13, Block.planks.blockID,
+ Block.planks.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 5, 1, 9, 5, 2, Block.planks.blockID,
+ Block.planks.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 5, 12, 9, 5, 13, Block.planks.blockID,
+ Block.planks.blockID, false);
+ this.placeBlockAtCurrentPosition(par1World, Block.planks.blockID, 0, 9, 5, 11,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.planks.blockID, 0, 8, 5, 11,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.planks.blockID, 0, 9, 5, 10,
+ par3StructureBoundingBox);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 3, 6, 2, 3, 6, 12, Block.fence.blockID,
+ Block.fence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 10, 6, 2, 10, 6, 10, Block.fence.blockID,
+ Block.fence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 6, 2, 9, 6, 2, Block.fence.blockID,
+ Block.fence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 6, 12, 8, 6, 12, Block.fence.blockID,
+ Block.fence.blockID, false);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, 9, 6, 11, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, 8, 6, 11, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, 9, 6, 10, par3StructureBoundingBox);
+ var7 = this.getMetadataWithOffset(Block.ladder.blockID, 3);
+ this.placeBlockAtCurrentPosition(par1World, Block.ladder.blockID, var7, 10, 1, 13,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.ladder.blockID, var7, 10, 2, 13,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.ladder.blockID, var7, 10, 3, 13,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.ladder.blockID, var7, 10, 4, 13,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.ladder.blockID, var7, 10, 5, 13,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.ladder.blockID, var7, 10, 6, 13,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.ladder.blockID, var7, 10, 7, 13,
+ par3StructureBoundingBox);
+ byte var8 = 7;
+ byte var9 = 7;
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, var8 - 1, 9, var9,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, var8, 9, var9,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, var8 - 1, 8, var9,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, var8, 8, var9,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, var8 - 1, 7, var9,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, var8, 7, var9,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, var8 - 2, 7, var9,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, var8 + 1, 7, var9,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, var8 - 1, 7, var9 - 1,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, var8 - 1, 7, var9 + 1,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, var8, 7, var9 - 1,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, var8, 7, var9 + 1,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.torchWood.blockID, 0, var8 - 2, 8, var9,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.torchWood.blockID, 0, var8 + 1, 8, var9,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.torchWood.blockID, 0, var8 - 1, 8, var9 - 1,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.torchWood.blockID, 0, var8 - 1, 8, var9 + 1,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.torchWood.blockID, 0, var8, 8, var9 - 1,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.torchWood.blockID, 0, var8, 8, var9 + 1,
+ par3StructureBoundingBox);
+ }
+
+ this.generateStructureChestContents(par1World, par3StructureBoundingBox, par2Random, 3, 3, 5,
+ WeightedRandomChestContent.func_92080_a(strongholdLibraryChestContents,
+ new WeightedRandomChestContent[] { Item.enchantedBook.func_92112_a(par2Random, 1, 5, 2) }),
+ 1 + par2Random.nextInt(4));
+
+ if (this.isLargeRoom) {
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, 12, 9, 1, par3StructureBoundingBox);
+ this.generateStructureChestContents(par1World, par3StructureBoundingBox, par2Random, 12, 8, 1,
+ WeightedRandomChestContent.func_92080_a(strongholdLibraryChestContents,
+ new WeightedRandomChestContent[] {
+ Item.enchantedBook.func_92112_a(par2Random, 1, 5, 2) }),
+ 1 + par2Random.nextInt(4));
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentStrongholdPortalRoom.java b/sp-server/src/main/java/net/minecraft/src/ComponentStrongholdPortalRoom.java
new file mode 100644
index 0000000..6f833fd
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentStrongholdPortalRoom.java
@@ -0,0 +1,168 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentStrongholdPortalRoom extends ComponentStronghold {
+ private boolean hasSpawner;
+
+ public ComponentStrongholdPortalRoom(int par1, EaglercraftRandom par2Random, StructureBoundingBox par3StructureBoundingBox,
+ int par4) {
+ super(par1);
+ this.coordBaseMode = par4;
+ this.boundingBox = par3StructureBoundingBox;
+ }
+
+ /**
+ * Initiates construction of the Structure Component picked, at the current
+ * Location of StructGen
+ */
+ public void buildComponent(StructureComponent par1StructureComponent, List par2List, EaglercraftRandom par3Random) {
+ if (par1StructureComponent != null) {
+ ((ComponentStrongholdStairs2) par1StructureComponent).strongholdPortalRoom = this;
+ }
+ }
+
+ public static ComponentStrongholdPortalRoom findValidPlacement(List par0List, EaglercraftRandom par1Random, int par2, int par3,
+ int par4, int par5, int par6) {
+ StructureBoundingBox var7 = StructureBoundingBox.getComponentToAddBoundingBox(par2, par3, par4, -4, -1, 0, 11,
+ 8, 16, par5);
+ return canStrongholdGoDeeper(var7) && StructureComponent.findIntersecting(par0List, var7) == null
+ ? new ComponentStrongholdPortalRoom(par6, par1Random, var7, par5)
+ : null;
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 0, 0, 0, 10, 7, 15, false, par2Random,
+ StructureStrongholdPieces.getStrongholdStones());
+ this.placeDoor(par1World, par2Random, par3StructureBoundingBox, EnumDoor.GRATES, 4, 1, 0);
+ byte var4 = 6;
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 1, var4, 1, 1, var4, 14, false, par2Random,
+ StructureStrongholdPieces.getStrongholdStones());
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 9, var4, 1, 9, var4, 14, false, par2Random,
+ StructureStrongholdPieces.getStrongholdStones());
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 2, var4, 1, 8, var4, 2, false, par2Random,
+ StructureStrongholdPieces.getStrongholdStones());
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 2, var4, 14, 8, var4, 14, false, par2Random,
+ StructureStrongholdPieces.getStrongholdStones());
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 1, 1, 1, 2, 1, 4, false, par2Random,
+ StructureStrongholdPieces.getStrongholdStones());
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 8, 1, 1, 9, 1, 4, false, par2Random,
+ StructureStrongholdPieces.getStrongholdStones());
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 1, 1, 1, 1, 3, Block.lavaMoving.blockID,
+ Block.lavaMoving.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 9, 1, 1, 9, 1, 3, Block.lavaMoving.blockID,
+ Block.lavaMoving.blockID, false);
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 3, 1, 8, 7, 1, 12, false, par2Random,
+ StructureStrongholdPieces.getStrongholdStones());
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 1, 9, 6, 1, 11, Block.lavaMoving.blockID,
+ Block.lavaMoving.blockID, false);
+ int var5;
+
+ for (var5 = 3; var5 < 14; var5 += 2) {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 3, var5, 0, 4, var5, Block.fenceIron.blockID,
+ Block.fenceIron.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 10, 3, var5, 10, 4, var5, Block.fenceIron.blockID,
+ Block.fenceIron.blockID, false);
+ }
+
+ for (var5 = 2; var5 < 9; var5 += 2) {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, var5, 3, 15, var5, 4, 15, Block.fenceIron.blockID,
+ Block.fenceIron.blockID, false);
+ }
+
+ var5 = this.getMetadataWithOffset(Block.stairsStoneBrick.blockID, 3);
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 4, 1, 5, 6, 1, 7, false, par2Random,
+ StructureStrongholdPieces.getStrongholdStones());
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 4, 2, 6, 6, 2, 7, false, par2Random,
+ StructureStrongholdPieces.getStrongholdStones());
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 4, 3, 7, 6, 3, 7, false, par2Random,
+ StructureStrongholdPieces.getStrongholdStones());
+
+ for (int var6 = 4; var6 <= 6; ++var6) {
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsStoneBrick.blockID, var5, var6, 1, 4,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsStoneBrick.blockID, var5, var6, 2, 5,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsStoneBrick.blockID, var5, var6, 3, 6,
+ par3StructureBoundingBox);
+ }
+
+ byte var14 = 2;
+ byte var7 = 0;
+ byte var8 = 3;
+ byte var9 = 1;
+
+ switch (this.coordBaseMode) {
+ case 0:
+ var14 = 0;
+ var7 = 2;
+ break;
+
+ case 1:
+ var14 = 1;
+ var7 = 3;
+ var8 = 0;
+ var9 = 2;
+
+ case 2:
+ default:
+ break;
+
+ case 3:
+ var14 = 3;
+ var7 = 1;
+ var8 = 0;
+ var9 = 2;
+ }
+
+ this.placeBlockAtCurrentPosition(par1World, Block.endPortalFrame.blockID,
+ var14 + (par2Random.nextFloat() > 0.9F ? 4 : 0), 4, 3, 8, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.endPortalFrame.blockID,
+ var14 + (par2Random.nextFloat() > 0.9F ? 4 : 0), 5, 3, 8, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.endPortalFrame.blockID,
+ var14 + (par2Random.nextFloat() > 0.9F ? 4 : 0), 6, 3, 8, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.endPortalFrame.blockID,
+ var7 + (par2Random.nextFloat() > 0.9F ? 4 : 0), 4, 3, 12, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.endPortalFrame.blockID,
+ var7 + (par2Random.nextFloat() > 0.9F ? 4 : 0), 5, 3, 12, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.endPortalFrame.blockID,
+ var7 + (par2Random.nextFloat() > 0.9F ? 4 : 0), 6, 3, 12, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.endPortalFrame.blockID,
+ var8 + (par2Random.nextFloat() > 0.9F ? 4 : 0), 3, 3, 9, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.endPortalFrame.blockID,
+ var8 + (par2Random.nextFloat() > 0.9F ? 4 : 0), 3, 3, 10, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.endPortalFrame.blockID,
+ var8 + (par2Random.nextFloat() > 0.9F ? 4 : 0), 3, 3, 11, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.endPortalFrame.blockID,
+ var9 + (par2Random.nextFloat() > 0.9F ? 4 : 0), 7, 3, 9, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.endPortalFrame.blockID,
+ var9 + (par2Random.nextFloat() > 0.9F ? 4 : 0), 7, 3, 10, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.endPortalFrame.blockID,
+ var9 + (par2Random.nextFloat() > 0.9F ? 4 : 0), 7, 3, 11, par3StructureBoundingBox);
+
+ if (!this.hasSpawner) {
+ int var13 = this.getYWithOffset(3);
+ int var10 = this.getXWithOffset(5, 6);
+ int var11 = this.getZWithOffset(5, 6);
+
+ if (par3StructureBoundingBox.isVecInside(var10, var13, var11)) {
+ this.hasSpawner = true;
+ par1World.setBlock(var10, var13, var11, Block.mobSpawner.blockID, 0, 2);
+ TileEntityMobSpawner var12 = (TileEntityMobSpawner) par1World.getBlockTileEntity(var10, var13, var11);
+
+ if (var12 != null) {
+ var12.func_98049_a().setMobID("Silverfish");
+ }
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentStrongholdPrison.java b/sp-server/src/main/java/net/minecraft/src/ComponentStrongholdPrison.java
new file mode 100644
index 0000000..3efe4fd
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentStrongholdPrison.java
@@ -0,0 +1,73 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentStrongholdPrison extends ComponentStronghold {
+ protected final EnumDoor doorType;
+
+ public ComponentStrongholdPrison(int par1, EaglercraftRandom par2Random, StructureBoundingBox par3StructureBoundingBox,
+ int par4) {
+ super(par1);
+ this.coordBaseMode = par4;
+ this.doorType = this.getRandomDoor(par2Random);
+ this.boundingBox = par3StructureBoundingBox;
+ }
+
+ /**
+ * Initiates construction of the Structure Component picked, at the current
+ * Location of StructGen
+ */
+ public void buildComponent(StructureComponent par1StructureComponent, List par2List, EaglercraftRandom par3Random) {
+ this.getNextComponentNormal((ComponentStrongholdStairs2) par1StructureComponent, par2List, par3Random, 1, 1);
+ }
+
+ public static ComponentStrongholdPrison findValidPlacement(List par0List, EaglercraftRandom par1Random, int par2, int par3,
+ int par4, int par5, int par6) {
+ StructureBoundingBox var7 = StructureBoundingBox.getComponentToAddBoundingBox(par2, par3, par4, -1, -1, 0, 9, 5,
+ 11, par5);
+ return canStrongholdGoDeeper(var7) && StructureComponent.findIntersecting(par0List, var7) == null
+ ? new ComponentStrongholdPrison(par6, par1Random, var7, par5)
+ : null;
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ if (this.isLiquidInStructureBoundingBox(par1World, par3StructureBoundingBox)) {
+ return false;
+ } else {
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 0, 0, 0, 8, 4, 10, true, par2Random,
+ StructureStrongholdPieces.getStrongholdStones());
+ this.placeDoor(par1World, par2Random, par3StructureBoundingBox, this.doorType, 1, 1, 0);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 1, 10, 3, 3, 10, 0, 0, false);
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 4, 1, 1, 4, 3, 1, false, par2Random,
+ StructureStrongholdPieces.getStrongholdStones());
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 4, 1, 3, 4, 3, 3, false, par2Random,
+ StructureStrongholdPieces.getStrongholdStones());
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 4, 1, 7, 4, 3, 7, false, par2Random,
+ StructureStrongholdPieces.getStrongholdStones());
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 4, 1, 9, 4, 3, 9, false, par2Random,
+ StructureStrongholdPieces.getStrongholdStones());
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 1, 4, 4, 3, 6, Block.fenceIron.blockID,
+ Block.fenceIron.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 5, 1, 5, 7, 3, 5, Block.fenceIron.blockID,
+ Block.fenceIron.blockID, false);
+ this.placeBlockAtCurrentPosition(par1World, Block.fenceIron.blockID, 0, 4, 3, 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fenceIron.blockID, 0, 4, 3, 8, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.doorIron.blockID,
+ this.getMetadataWithOffset(Block.doorIron.blockID, 3), 4, 1, 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.doorIron.blockID,
+ this.getMetadataWithOffset(Block.doorIron.blockID, 3) + 8, 4, 2, 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.doorIron.blockID,
+ this.getMetadataWithOffset(Block.doorIron.blockID, 3), 4, 1, 8, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.doorIron.blockID,
+ this.getMetadataWithOffset(Block.doorIron.blockID, 3) + 8, 4, 2, 8, par3StructureBoundingBox);
+ return true;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentStrongholdRightTurn.java b/sp-server/src/main/java/net/minecraft/src/ComponentStrongholdRightTurn.java
new file mode 100644
index 0000000..cf1b982
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentStrongholdRightTurn.java
@@ -0,0 +1,47 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentStrongholdRightTurn extends ComponentStrongholdLeftTurn {
+ public ComponentStrongholdRightTurn(int par1, EaglercraftRandom par2Random, StructureBoundingBox par3StructureBoundingBox,
+ int par4) {
+ super(par1, par2Random, par3StructureBoundingBox, par4);
+ }
+
+ /**
+ * Initiates construction of the Structure Component picked, at the current
+ * Location of StructGen
+ */
+ public void buildComponent(StructureComponent par1StructureComponent, List par2List, EaglercraftRandom par3Random) {
+ if (this.coordBaseMode != 2 && this.coordBaseMode != 3) {
+ this.getNextComponentX((ComponentStrongholdStairs2) par1StructureComponent, par2List, par3Random, 1, 1);
+ } else {
+ this.getNextComponentZ((ComponentStrongholdStairs2) par1StructureComponent, par2List, par3Random, 1, 1);
+ }
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ if (this.isLiquidInStructureBoundingBox(par1World, par3StructureBoundingBox)) {
+ return false;
+ } else {
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 0, 0, 0, 4, 4, 4, true, par2Random,
+ StructureStrongholdPieces.getStrongholdStones());
+ this.placeDoor(par1World, par2Random, par3StructureBoundingBox, this.doorType, 1, 1, 0);
+
+ if (this.coordBaseMode != 2 && this.coordBaseMode != 3) {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 1, 1, 0, 3, 3, 0, 0, false);
+ } else {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 1, 1, 4, 3, 3, 0, 0, false);
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentStrongholdRoomCrossing.java b/sp-server/src/main/java/net/minecraft/src/ComponentStrongholdRoomCrossing.java
new file mode 100644
index 0000000..e39d383
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentStrongholdRoomCrossing.java
@@ -0,0 +1,206 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentStrongholdRoomCrossing extends ComponentStronghold {
+ /**
+ * Items that could generate in the chest that is located in Stronghold Room
+ * Crossing.
+ */
+ private static final WeightedRandomChestContent[] strongholdRoomCrossingChestContents = new WeightedRandomChestContent[] {
+ new WeightedRandomChestContent(Item.ingotIron.itemID, 0, 1, 5, 10),
+ new WeightedRandomChestContent(Item.ingotGold.itemID, 0, 1, 3, 5),
+ new WeightedRandomChestContent(Item.redstone.itemID, 0, 4, 9, 5),
+ new WeightedRandomChestContent(Item.coal.itemID, 0, 3, 8, 10),
+ new WeightedRandomChestContent(Item.bread.itemID, 0, 1, 3, 15),
+ new WeightedRandomChestContent(Item.appleRed.itemID, 0, 1, 3, 15),
+ new WeightedRandomChestContent(Item.pickaxeIron.itemID, 0, 1, 1, 1) };
+ protected final EnumDoor doorType;
+ protected final int roomType;
+
+ public ComponentStrongholdRoomCrossing(int par1, EaglercraftRandom par2Random, StructureBoundingBox par3StructureBoundingBox,
+ int par4) {
+ super(par1);
+ this.coordBaseMode = par4;
+ this.doorType = this.getRandomDoor(par2Random);
+ this.boundingBox = par3StructureBoundingBox;
+ this.roomType = par2Random.nextInt(5);
+ }
+
+ /**
+ * Initiates construction of the Structure Component picked, at the current
+ * Location of StructGen
+ */
+ public void buildComponent(StructureComponent par1StructureComponent, List par2List, EaglercraftRandom par3Random) {
+ this.getNextComponentNormal((ComponentStrongholdStairs2) par1StructureComponent, par2List, par3Random, 4, 1);
+ this.getNextComponentX((ComponentStrongholdStairs2) par1StructureComponent, par2List, par3Random, 1, 4);
+ this.getNextComponentZ((ComponentStrongholdStairs2) par1StructureComponent, par2List, par3Random, 1, 4);
+ }
+
+ public static ComponentStrongholdRoomCrossing findValidPlacement(List par0List, EaglercraftRandom par1Random, int par2,
+ int par3, int par4, int par5, int par6) {
+ StructureBoundingBox var7 = StructureBoundingBox.getComponentToAddBoundingBox(par2, par3, par4, -4, -1, 0, 11,
+ 7, 11, par5);
+ return canStrongholdGoDeeper(var7) && StructureComponent.findIntersecting(par0List, var7) == null
+ ? new ComponentStrongholdRoomCrossing(par6, par1Random, var7, par5)
+ : null;
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ if (this.isLiquidInStructureBoundingBox(par1World, par3StructureBoundingBox)) {
+ return false;
+ } else {
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 0, 0, 0, 10, 6, 10, true, par2Random,
+ StructureStrongholdPieces.getStrongholdStones());
+ this.placeDoor(par1World, par2Random, par3StructureBoundingBox, this.doorType, 4, 1, 0);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 1, 10, 6, 3, 10, 0, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 1, 4, 0, 3, 6, 0, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 10, 1, 4, 10, 3, 6, 0, 0, false);
+ int var4;
+
+ switch (this.roomType) {
+ case 0:
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, 5, 1, 5,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, 5, 2, 5,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, 5, 3, 5,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.torchWood.blockID, 0, 4, 3, 5,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.torchWood.blockID, 0, 6, 3, 5,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.torchWood.blockID, 0, 5, 3, 4,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.torchWood.blockID, 0, 5, 3, 6,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneSingleSlab.blockID, 0, 4, 1, 4,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneSingleSlab.blockID, 0, 4, 1, 5,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneSingleSlab.blockID, 0, 4, 1, 6,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneSingleSlab.blockID, 0, 6, 1, 4,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneSingleSlab.blockID, 0, 6, 1, 5,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneSingleSlab.blockID, 0, 6, 1, 6,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneSingleSlab.blockID, 0, 5, 1, 4,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneSingleSlab.blockID, 0, 5, 1, 6,
+ par3StructureBoundingBox);
+ break;
+
+ case 1:
+ for (var4 = 0; var4 < 5; ++var4) {
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, 3, 1, 3 + var4,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, 7, 1, 3 + var4,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, 3 + var4, 1, 3,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, 3 + var4, 1, 7,
+ par3StructureBoundingBox);
+ }
+
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, 5, 1, 5,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, 5, 2, 5,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, 5, 3, 5,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.waterMoving.blockID, 0, 5, 4, 5,
+ par3StructureBoundingBox);
+ break;
+
+ case 2:
+ for (var4 = 1; var4 <= 9; ++var4) {
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestone.blockID, 0, 1, 3, var4,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestone.blockID, 0, 9, 3, var4,
+ par3StructureBoundingBox);
+ }
+
+ for (var4 = 1; var4 <= 9; ++var4) {
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestone.blockID, 0, var4, 3, 1,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestone.blockID, 0, var4, 3, 9,
+ par3StructureBoundingBox);
+ }
+
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestone.blockID, 0, 5, 1, 4,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestone.blockID, 0, 5, 1, 6,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestone.blockID, 0, 5, 3, 4,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestone.blockID, 0, 5, 3, 6,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestone.blockID, 0, 4, 1, 5,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestone.blockID, 0, 6, 1, 5,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestone.blockID, 0, 4, 3, 5,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestone.blockID, 0, 6, 3, 5,
+ par3StructureBoundingBox);
+
+ for (var4 = 1; var4 <= 3; ++var4) {
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestone.blockID, 0, 4, var4, 4,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestone.blockID, 0, 6, var4, 4,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestone.blockID, 0, 4, var4, 6,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestone.blockID, 0, 6, var4, 6,
+ par3StructureBoundingBox);
+ }
+
+ this.placeBlockAtCurrentPosition(par1World, Block.torchWood.blockID, 0, 5, 3, 5,
+ par3StructureBoundingBox);
+
+ for (var4 = 2; var4 <= 8; ++var4) {
+ this.placeBlockAtCurrentPosition(par1World, Block.planks.blockID, 0, 2, 3, var4,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.planks.blockID, 0, 3, 3, var4,
+ par3StructureBoundingBox);
+
+ if (var4 <= 3 || var4 >= 7) {
+ this.placeBlockAtCurrentPosition(par1World, Block.planks.blockID, 0, 4, 3, var4,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.planks.blockID, 0, 5, 3, var4,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.planks.blockID, 0, 6, 3, var4,
+ par3StructureBoundingBox);
+ }
+
+ this.placeBlockAtCurrentPosition(par1World, Block.planks.blockID, 0, 7, 3, var4,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.planks.blockID, 0, 8, 3, var4,
+ par3StructureBoundingBox);
+ }
+
+ this.placeBlockAtCurrentPosition(par1World, Block.ladder.blockID,
+ this.getMetadataWithOffset(Block.ladder.blockID, 4), 9, 1, 3, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.ladder.blockID,
+ this.getMetadataWithOffset(Block.ladder.blockID, 4), 9, 2, 3, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.ladder.blockID,
+ this.getMetadataWithOffset(Block.ladder.blockID, 4), 9, 3, 3, par3StructureBoundingBox);
+ this.generateStructureChestContents(par1World, par3StructureBoundingBox, par2Random, 3, 4, 8,
+ WeightedRandomChestContent.func_92080_a(strongholdRoomCrossingChestContents,
+ new WeightedRandomChestContent[] { Item.enchantedBook.func_92114_b(par2Random) }),
+ 1 + par2Random.nextInt(4));
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentStrongholdStairs.java b/sp-server/src/main/java/net/minecraft/src/ComponentStrongholdStairs.java
new file mode 100644
index 0000000..7c86c60
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentStrongholdStairs.java
@@ -0,0 +1,100 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentStrongholdStairs extends ComponentStronghold {
+ private final boolean field_75024_a;
+ private final EnumDoor doorType;
+
+ public ComponentStrongholdStairs(int par1, EaglercraftRandom par2Random, int par3, int par4) {
+ super(par1);
+ this.field_75024_a = true;
+ this.coordBaseMode = par2Random.nextInt(4);
+ this.doorType = EnumDoor.OPENING;
+
+ switch (this.coordBaseMode) {
+ case 0:
+ case 2:
+ this.boundingBox = new StructureBoundingBox(par3, 64, par4, par3 + 5 - 1, 74, par4 + 5 - 1);
+ break;
+
+ default:
+ this.boundingBox = new StructureBoundingBox(par3, 64, par4, par3 + 5 - 1, 74, par4 + 5 - 1);
+ }
+ }
+
+ public ComponentStrongholdStairs(int par1, EaglercraftRandom par2Random, StructureBoundingBox par3StructureBoundingBox,
+ int par4) {
+ super(par1);
+ this.field_75024_a = false;
+ this.coordBaseMode = par4;
+ this.doorType = this.getRandomDoor(par2Random);
+ this.boundingBox = par3StructureBoundingBox;
+ }
+
+ /**
+ * Initiates construction of the Structure Component picked, at the current
+ * Location of StructGen
+ */
+ public void buildComponent(StructureComponent par1StructureComponent, List par2List, EaglercraftRandom par3Random) {
+ if (this.field_75024_a) {
+ StructureStrongholdPieces.setComponentType(ComponentStrongholdCrossing.class);
+ }
+
+ this.getNextComponentNormal((ComponentStrongholdStairs2) par1StructureComponent, par2List, par3Random, 1, 1);
+ }
+
+ /**
+ * performs some checks, then gives out a fresh Stairs component
+ */
+ public static ComponentStrongholdStairs getStrongholdStairsComponent(List par0List, EaglercraftRandom par1Random, int par2,
+ int par3, int par4, int par5, int par6) {
+ StructureBoundingBox var7 = StructureBoundingBox.getComponentToAddBoundingBox(par2, par3, par4, -1, -7, 0, 5,
+ 11, 5, par5);
+ return canStrongholdGoDeeper(var7) && StructureComponent.findIntersecting(par0List, var7) == null
+ ? new ComponentStrongholdStairs(par6, par1Random, var7, par5)
+ : null;
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ if (this.isLiquidInStructureBoundingBox(par1World, par3StructureBoundingBox)) {
+ return false;
+ } else {
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 0, 0, 0, 4, 10, 4, true, par2Random,
+ StructureStrongholdPieces.getStrongholdStones());
+ this.placeDoor(par1World, par2Random, par3StructureBoundingBox, this.doorType, 1, 7, 0);
+ this.placeDoor(par1World, par2Random, par3StructureBoundingBox, EnumDoor.OPENING, 1, 1, 4);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, 2, 6, 1, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, 1, 5, 1, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneSingleSlab.blockID, 0, 1, 6, 1,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, 1, 5, 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, 1, 4, 3, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneSingleSlab.blockID, 0, 1, 5, 3,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, 2, 4, 3, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, 3, 3, 3, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneSingleSlab.blockID, 0, 3, 4, 3,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, 3, 3, 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, 3, 2, 1, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneSingleSlab.blockID, 0, 3, 3, 1,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, 2, 2, 1, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, 1, 1, 1, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneSingleSlab.blockID, 0, 1, 2, 1,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, 1, 1, 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneSingleSlab.blockID, 0, 1, 1, 3,
+ par3StructureBoundingBox);
+ return true;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentStrongholdStairs2.java b/sp-server/src/main/java/net/minecraft/src/ComponentStrongholdStairs2.java
new file mode 100644
index 0000000..84379ef
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentStrongholdStairs2.java
@@ -0,0 +1,19 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentStrongholdStairs2 extends ComponentStrongholdStairs {
+ public StructureStrongholdPieceWeight strongholdPieceWeight;
+ public ComponentStrongholdPortalRoom strongholdPortalRoom;
+ public ArrayList field_75026_c = new ArrayList();
+
+ public ComponentStrongholdStairs2(int par1, EaglercraftRandom par2Random, int par3, int par4) {
+ super(0, par2Random, par3, par4);
+ }
+
+ public ChunkPosition getCenter() {
+ return this.strongholdPortalRoom != null ? this.strongholdPortalRoom.getCenter() : super.getCenter();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentStrongholdStairsStraight.java b/sp-server/src/main/java/net/minecraft/src/ComponentStrongholdStairsStraight.java
new file mode 100644
index 0000000..1046ae3
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentStrongholdStairsStraight.java
@@ -0,0 +1,71 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentStrongholdStairsStraight extends ComponentStronghold {
+ private final EnumDoor doorType;
+
+ public ComponentStrongholdStairsStraight(int par1, EaglercraftRandom par2Random, StructureBoundingBox par3StructureBoundingBox,
+ int par4) {
+ super(par1);
+ this.coordBaseMode = par4;
+ this.doorType = this.getRandomDoor(par2Random);
+ this.boundingBox = par3StructureBoundingBox;
+ }
+
+ /**
+ * Initiates construction of the Structure Component picked, at the current
+ * Location of StructGen
+ */
+ public void buildComponent(StructureComponent par1StructureComponent, List par2List, EaglercraftRandom par3Random) {
+ this.getNextComponentNormal((ComponentStrongholdStairs2) par1StructureComponent, par2List, par3Random, 1, 1);
+ }
+
+ public static ComponentStrongholdStairsStraight findValidPlacement(List par0List, EaglercraftRandom par1Random, int par2,
+ int par3, int par4, int par5, int par6) {
+ StructureBoundingBox var7 = StructureBoundingBox.getComponentToAddBoundingBox(par2, par3, par4, -1, -7, 0, 5,
+ 11, 8, par5);
+ return canStrongholdGoDeeper(var7) && StructureComponent.findIntersecting(par0List, var7) == null
+ ? new ComponentStrongholdStairsStraight(par6, par1Random, var7, par5)
+ : null;
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ if (this.isLiquidInStructureBoundingBox(par1World, par3StructureBoundingBox)) {
+ return false;
+ } else {
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 0, 0, 0, 4, 10, 7, true, par2Random,
+ StructureStrongholdPieces.getStrongholdStones());
+ this.placeDoor(par1World, par2Random, par3StructureBoundingBox, this.doorType, 1, 7, 0);
+ this.placeDoor(par1World, par2Random, par3StructureBoundingBox, EnumDoor.OPENING, 1, 1, 7);
+ int var4 = this.getMetadataWithOffset(Block.stairsCobblestone.blockID, 2);
+
+ for (int var5 = 0; var5 < 6; ++var5) {
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsCobblestone.blockID, var4, 1, 6 - var5,
+ 1 + var5, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsCobblestone.blockID, var4, 2, 6 - var5,
+ 1 + var5, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsCobblestone.blockID, var4, 3, 6 - var5,
+ 1 + var5, par3StructureBoundingBox);
+
+ if (var5 < 5) {
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, 1, 5 - var5, 1 + var5,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, 2, 5 - var5, 1 + var5,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneBrick.blockID, 0, 3, 5 - var5, 1 + var5,
+ par3StructureBoundingBox);
+ }
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentStrongholdStraight.java b/sp-server/src/main/java/net/minecraft/src/ComponentStrongholdStraight.java
new file mode 100644
index 0000000..a8bc09f
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentStrongholdStraight.java
@@ -0,0 +1,80 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentStrongholdStraight extends ComponentStronghold {
+ private final EnumDoor doorType;
+ private final boolean expandsX;
+ private final boolean expandsZ;
+
+ public ComponentStrongholdStraight(int par1, EaglercraftRandom par2Random, StructureBoundingBox par3StructureBoundingBox,
+ int par4) {
+ super(par1);
+ this.coordBaseMode = par4;
+ this.doorType = this.getRandomDoor(par2Random);
+ this.boundingBox = par3StructureBoundingBox;
+ this.expandsX = par2Random.nextInt(2) == 0;
+ this.expandsZ = par2Random.nextInt(2) == 0;
+ }
+
+ /**
+ * Initiates construction of the Structure Component picked, at the current
+ * Location of StructGen
+ */
+ public void buildComponent(StructureComponent par1StructureComponent, List par2List, EaglercraftRandom par3Random) {
+ this.getNextComponentNormal((ComponentStrongholdStairs2) par1StructureComponent, par2List, par3Random, 1, 1);
+
+ if (this.expandsX) {
+ this.getNextComponentX((ComponentStrongholdStairs2) par1StructureComponent, par2List, par3Random, 1, 2);
+ }
+
+ if (this.expandsZ) {
+ this.getNextComponentZ((ComponentStrongholdStairs2) par1StructureComponent, par2List, par3Random, 1, 2);
+ }
+ }
+
+ public static ComponentStrongholdStraight findValidPlacement(List par0List, EaglercraftRandom par1Random, int par2, int par3,
+ int par4, int par5, int par6) {
+ StructureBoundingBox var7 = StructureBoundingBox.getComponentToAddBoundingBox(par2, par3, par4, -1, -1, 0, 5, 5,
+ 7, par5);
+ return canStrongholdGoDeeper(var7) && StructureComponent.findIntersecting(par0List, var7) == null
+ ? new ComponentStrongholdStraight(par6, par1Random, var7, par5)
+ : null;
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ if (this.isLiquidInStructureBoundingBox(par1World, par3StructureBoundingBox)) {
+ return false;
+ } else {
+ this.fillWithRandomizedBlocks(par1World, par3StructureBoundingBox, 0, 0, 0, 4, 4, 6, true, par2Random,
+ StructureStrongholdPieces.getStrongholdStones());
+ this.placeDoor(par1World, par2Random, par3StructureBoundingBox, this.doorType, 1, 1, 0);
+ this.placeDoor(par1World, par2Random, par3StructureBoundingBox, EnumDoor.OPENING, 1, 1, 6);
+ this.randomlyPlaceBlock(par1World, par3StructureBoundingBox, par2Random, 0.1F, 1, 2, 1,
+ Block.torchWood.blockID, 0);
+ this.randomlyPlaceBlock(par1World, par3StructureBoundingBox, par2Random, 0.1F, 3, 2, 1,
+ Block.torchWood.blockID, 0);
+ this.randomlyPlaceBlock(par1World, par3StructureBoundingBox, par2Random, 0.1F, 1, 2, 5,
+ Block.torchWood.blockID, 0);
+ this.randomlyPlaceBlock(par1World, par3StructureBoundingBox, par2Random, 0.1F, 3, 2, 5,
+ Block.torchWood.blockID, 0);
+
+ if (this.expandsX) {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 1, 2, 0, 3, 4, 0, 0, false);
+ }
+
+ if (this.expandsZ) {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 1, 2, 4, 3, 4, 0, 0, false);
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentVillage.java b/sp-server/src/main/java/net/minecraft/src/ComponentVillage.java
new file mode 100644
index 0000000..d434c74
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentVillage.java
@@ -0,0 +1,233 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+abstract class ComponentVillage extends StructureComponent {
+ /** The number of villagers that have been spawned in this component. */
+ private int villagersSpawned;
+
+ /** The starting piece of the village. */
+ protected ComponentVillageStartPiece startPiece;
+
+ protected ComponentVillage(ComponentVillageStartPiece par1ComponentVillageStartPiece, int par2) {
+ super(par2);
+ this.startPiece = par1ComponentVillageStartPiece;
+ }
+
+ /**
+ * Gets the next village component, with the bounding box shifted -1 in the X
+ * and Z direction.
+ */
+ protected StructureComponent getNextComponentNN(ComponentVillageStartPiece par1ComponentVillageStartPiece,
+ List par2List, EaglercraftRandom par3Random, int par4, int par5) {
+ switch (this.coordBaseMode) {
+ case 0:
+ return StructureVillagePieces.getNextStructureComponent(par1ComponentVillageStartPiece, par2List,
+ par3Random, this.boundingBox.minX - 1, this.boundingBox.minY + par4, this.boundingBox.minZ + par5,
+ 1, this.getComponentType());
+
+ case 1:
+ return StructureVillagePieces.getNextStructureComponent(par1ComponentVillageStartPiece, par2List,
+ par3Random, this.boundingBox.minX + par5, this.boundingBox.minY + par4, this.boundingBox.minZ - 1,
+ 2, this.getComponentType());
+
+ case 2:
+ return StructureVillagePieces.getNextStructureComponent(par1ComponentVillageStartPiece, par2List,
+ par3Random, this.boundingBox.minX - 1, this.boundingBox.minY + par4, this.boundingBox.minZ + par5,
+ 1, this.getComponentType());
+
+ case 3:
+ return StructureVillagePieces.getNextStructureComponent(par1ComponentVillageStartPiece, par2List,
+ par3Random, this.boundingBox.minX + par5, this.boundingBox.minY + par4, this.boundingBox.minZ - 1,
+ 2, this.getComponentType());
+
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Gets the next village component, with the bounding box shifted +1 in the X
+ * and Z direction.
+ */
+ protected StructureComponent getNextComponentPP(ComponentVillageStartPiece par1ComponentVillageStartPiece,
+ List par2List, EaglercraftRandom par3Random, int par4, int par5) {
+ switch (this.coordBaseMode) {
+ case 0:
+ return StructureVillagePieces.getNextStructureComponent(par1ComponentVillageStartPiece, par2List,
+ par3Random, this.boundingBox.maxX + 1, this.boundingBox.minY + par4, this.boundingBox.minZ + par5,
+ 3, this.getComponentType());
+
+ case 1:
+ return StructureVillagePieces.getNextStructureComponent(par1ComponentVillageStartPiece, par2List,
+ par3Random, this.boundingBox.minX + par5, this.boundingBox.minY + par4, this.boundingBox.maxZ + 1,
+ 0, this.getComponentType());
+
+ case 2:
+ return StructureVillagePieces.getNextStructureComponent(par1ComponentVillageStartPiece, par2List,
+ par3Random, this.boundingBox.maxX + 1, this.boundingBox.minY + par4, this.boundingBox.minZ + par5,
+ 3, this.getComponentType());
+
+ case 3:
+ return StructureVillagePieces.getNextStructureComponent(par1ComponentVillageStartPiece, par2List,
+ par3Random, this.boundingBox.minX + par5, this.boundingBox.minY + par4, this.boundingBox.maxZ + 1,
+ 0, this.getComponentType());
+
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Discover the y coordinate that will serve as the ground level of the supplied
+ * BoundingBox. (A median of all the levels in the BB's horizontal rectangle).
+ */
+ protected int getAverageGroundLevel(World par1World, StructureBoundingBox par2StructureBoundingBox) {
+ int var3 = 0;
+ int var4 = 0;
+
+ for (int var5 = this.boundingBox.minZ; var5 <= this.boundingBox.maxZ; ++var5) {
+ for (int var6 = this.boundingBox.minX; var6 <= this.boundingBox.maxX; ++var6) {
+ if (par2StructureBoundingBox.isVecInside(var6, 64, var5)) {
+ var3 += Math.max(par1World.getTopSolidOrLiquidBlock(var6, var5),
+ par1World.provider.getAverageGroundLevel());
+ ++var4;
+ }
+ }
+ }
+
+ if (var4 == 0) {
+ return -1;
+ } else {
+ return var3 / var4;
+ }
+ }
+
+ protected static boolean canVillageGoDeeper(StructureBoundingBox par0StructureBoundingBox) {
+ return par0StructureBoundingBox != null && par0StructureBoundingBox.minY > 10;
+ }
+
+ /**
+ * Spawns a number of villagers in this component. Parameters: world, component
+ * bounding box, x offset, y offset, z offset, number of villagers
+ */
+ protected void spawnVillagers(World par1World, StructureBoundingBox par2StructureBoundingBox, int par3, int par4,
+ int par5, int par6) {
+ if (this.villagersSpawned < par6) {
+ for (int var7 = this.villagersSpawned; var7 < par6; ++var7) {
+ int var8 = this.getXWithOffset(par3 + var7, par5);
+ int var9 = this.getYWithOffset(par4);
+ int var10 = this.getZWithOffset(par3 + var7, par5);
+
+ if (!par2StructureBoundingBox.isVecInside(var8, var9, var10)) {
+ break;
+ }
+
+ ++this.villagersSpawned;
+ EntityVillager var11 = new EntityVillager(par1World, this.getVillagerType(var7));
+ var11.setLocationAndAngles((double) var8 + 0.5D, (double) var9, (double) var10 + 0.5D, 0.0F, 0.0F);
+ par1World.spawnEntityInWorld(var11);
+ }
+ }
+ }
+
+ /**
+ * Returns the villager type to spawn in this component, based on the number of
+ * villagers already spawned.
+ */
+ protected int getVillagerType(int par1) {
+ return 0;
+ }
+
+ /**
+ * Gets the replacement block for the current biome
+ */
+ protected int getBiomeSpecificBlock(int par1, int par2) {
+ if (this.startPiece.inDesert) {
+ if (par1 == Block.wood.blockID) {
+ return Block.sandStone.blockID;
+ }
+
+ if (par1 == Block.cobblestone.blockID) {
+ return Block.sandStone.blockID;
+ }
+
+ if (par1 == Block.planks.blockID) {
+ return Block.sandStone.blockID;
+ }
+
+ if (par1 == Block.stairsWoodOak.blockID) {
+ return Block.stairsSandStone.blockID;
+ }
+
+ if (par1 == Block.stairsCobblestone.blockID) {
+ return Block.stairsSandStone.blockID;
+ }
+
+ if (par1 == Block.gravel.blockID) {
+ return Block.sandStone.blockID;
+ }
+ }
+
+ return par1;
+ }
+
+ /**
+ * Gets the replacement block metadata for the current biome
+ */
+ protected int getBiomeSpecificBlockMetadata(int par1, int par2) {
+ if (this.startPiece.inDesert) {
+ if (par1 == Block.wood.blockID) {
+ return 0;
+ }
+
+ if (par1 == Block.cobblestone.blockID) {
+ return 0;
+ }
+
+ if (par1 == Block.planks.blockID) {
+ return 2;
+ }
+ }
+
+ return par2;
+ }
+
+ /**
+ * current Position depends on currently set Coordinates mode, is computed here
+ */
+ protected void placeBlockAtCurrentPosition(World par1World, int par2, int par3, int par4, int par5, int par6,
+ StructureBoundingBox par7StructureBoundingBox) {
+ int var8 = this.getBiomeSpecificBlock(par2, par3);
+ int var9 = this.getBiomeSpecificBlockMetadata(par2, par3);
+ super.placeBlockAtCurrentPosition(par1World, var8, var9, par4, par5, par6, par7StructureBoundingBox);
+ }
+
+ /**
+ * arguments: (World worldObj, StructureBoundingBox structBB, int minX, int
+ * minY, int minZ, int maxX, int maxY, int maxZ, int placeBlockId, int
+ * replaceBlockId, boolean alwaysreplace)
+ */
+ protected void fillWithBlocks(World par1World, StructureBoundingBox par2StructureBoundingBox, int par3, int par4,
+ int par5, int par6, int par7, int par8, int par9, int par10, boolean par11) {
+ int var12 = this.getBiomeSpecificBlock(par9, 0);
+ int var13 = this.getBiomeSpecificBlockMetadata(par9, 0);
+ int var14 = this.getBiomeSpecificBlock(par10, 0);
+ int var15 = this.getBiomeSpecificBlockMetadata(par10, 0);
+ super.fillWithMetadataBlocks(par1World, par2StructureBoundingBox, par3, par4, par5, par6, par7, par8, var12,
+ var13, var14, var15, par11);
+ }
+
+ /**
+ * Overwrites air and liquids from selected position downwards, stops at hitting
+ * anything else.
+ */
+ protected void fillCurrentPositionBlocksDownwards(World par1World, int par2, int par3, int par4, int par5, int par6,
+ StructureBoundingBox par7StructureBoundingBox) {
+ int var8 = this.getBiomeSpecificBlock(par2, par3);
+ int var9 = this.getBiomeSpecificBlockMetadata(par2, par3);
+ super.fillCurrentPositionBlocksDownwards(par1World, var8, var9, par4, par5, par6, par7StructureBoundingBox);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentVillageChurch.java b/sp-server/src/main/java/net/minecraft/src/ComponentVillageChurch.java
new file mode 100644
index 0000000..ffbe906
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentVillageChurch.java
@@ -0,0 +1,142 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentVillageChurch extends ComponentVillage {
+ private int averageGroundLevel = -1;
+
+ public ComponentVillageChurch(ComponentVillageStartPiece par1ComponentVillageStartPiece, int par2,
+ EaglercraftRandom par3Random, StructureBoundingBox par4StructureBoundingBox, int par5) {
+ super(par1ComponentVillageStartPiece, par2);
+ this.coordBaseMode = par5;
+ this.boundingBox = par4StructureBoundingBox;
+ }
+
+ public static ComponentVillageChurch func_74919_a(ComponentVillageStartPiece par0ComponentVillageStartPiece,
+ List par1List, EaglercraftRandom par2Random, int par3, int par4, int par5, int par6, int par7) {
+ StructureBoundingBox var8 = StructureBoundingBox.getComponentToAddBoundingBox(par3, par4, par5, 0, 0, 0, 5, 12,
+ 9, par6);
+ return canVillageGoDeeper(var8) && StructureComponent.findIntersecting(par1List, var8) == null
+ ? new ComponentVillageChurch(par0ComponentVillageStartPiece, par7, par2Random, var8, par6)
+ : null;
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ if (this.averageGroundLevel < 0) {
+ this.averageGroundLevel = this.getAverageGroundLevel(par1World, par3StructureBoundingBox);
+
+ if (this.averageGroundLevel < 0) {
+ return true;
+ }
+
+ this.boundingBox.offset(0, this.averageGroundLevel - this.boundingBox.maxY + 12 - 1, 0);
+ }
+
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 1, 1, 3, 3, 7, 0, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 5, 1, 3, 9, 3, 0, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 0, 0, 3, 0, 8, Block.cobblestone.blockID,
+ Block.cobblestone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 1, 0, 3, 10, 0, Block.cobblestone.blockID,
+ Block.cobblestone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 1, 1, 0, 10, 3, Block.cobblestone.blockID,
+ Block.cobblestone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 1, 1, 4, 10, 3, Block.cobblestone.blockID,
+ Block.cobblestone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 0, 4, 0, 4, 7, Block.cobblestone.blockID,
+ Block.cobblestone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 0, 4, 4, 4, 7, Block.cobblestone.blockID,
+ Block.cobblestone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 1, 8, 3, 4, 8, Block.cobblestone.blockID,
+ Block.cobblestone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 5, 4, 3, 10, 4, Block.cobblestone.blockID,
+ Block.cobblestone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 5, 5, 3, 5, 7, Block.cobblestone.blockID,
+ Block.cobblestone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 9, 0, 4, 9, 4, Block.cobblestone.blockID,
+ Block.cobblestone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 4, 0, 4, 4, 4, Block.cobblestone.blockID,
+ Block.cobblestone.blockID, false);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestone.blockID, 0, 0, 11, 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestone.blockID, 0, 4, 11, 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestone.blockID, 0, 2, 11, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestone.blockID, 0, 2, 11, 4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestone.blockID, 0, 1, 1, 6, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestone.blockID, 0, 1, 1, 7, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestone.blockID, 0, 2, 1, 7, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestone.blockID, 0, 3, 1, 6, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestone.blockID, 0, 3, 1, 7, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsCobblestone.blockID,
+ this.getMetadataWithOffset(Block.stairsCobblestone.blockID, 3), 1, 1, 5, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsCobblestone.blockID,
+ this.getMetadataWithOffset(Block.stairsCobblestone.blockID, 3), 2, 1, 6, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsCobblestone.blockID,
+ this.getMetadataWithOffset(Block.stairsCobblestone.blockID, 3), 3, 1, 5, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsCobblestone.blockID,
+ this.getMetadataWithOffset(Block.stairsCobblestone.blockID, 1), 1, 2, 7, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsCobblestone.blockID,
+ this.getMetadataWithOffset(Block.stairsCobblestone.blockID, 0), 3, 2, 7, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 0, 2, 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 0, 3, 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 4, 2, 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 4, 3, 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 0, 6, 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 0, 7, 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 4, 6, 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 4, 7, 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 2, 6, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 2, 7, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 2, 6, 4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 2, 7, 4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 0, 3, 6, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 4, 3, 6, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 2, 3, 8, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.torchWood.blockID, 0, 2, 4, 7, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.torchWood.blockID, 0, 1, 4, 6, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.torchWood.blockID, 0, 3, 4, 6, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.torchWood.blockID, 0, 2, 4, 5, par3StructureBoundingBox);
+ int var4 = this.getMetadataWithOffset(Block.ladder.blockID, 4);
+ int var5;
+
+ for (var5 = 1; var5 <= 9; ++var5) {
+ this.placeBlockAtCurrentPosition(par1World, Block.ladder.blockID, var4, 3, var5, 3,
+ par3StructureBoundingBox);
+ }
+
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, 2, 1, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, 2, 2, 0, par3StructureBoundingBox);
+ this.placeDoorAtCurrentPosition(par1World, par3StructureBoundingBox, par2Random, 2, 1, 0,
+ this.getMetadataWithOffset(Block.doorWood.blockID, 1));
+
+ if (this.getBlockIdAtCurrentPosition(par1World, 2, 0, -1, par3StructureBoundingBox) == 0
+ && this.getBlockIdAtCurrentPosition(par1World, 2, -1, -1, par3StructureBoundingBox) != 0) {
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsCobblestone.blockID,
+ this.getMetadataWithOffset(Block.stairsCobblestone.blockID, 3), 2, 0, -1, par3StructureBoundingBox);
+ }
+
+ for (var5 = 0; var5 < 9; ++var5) {
+ for (int var6 = 0; var6 < 5; ++var6) {
+ this.clearCurrentPositionBlocksUpwards(par1World, var6, 12, var5, par3StructureBoundingBox);
+ this.fillCurrentPositionBlocksDownwards(par1World, Block.cobblestone.blockID, 0, var6, -1, var5,
+ par3StructureBoundingBox);
+ }
+ }
+
+ this.spawnVillagers(par1World, par3StructureBoundingBox, 2, 1, 2, 1);
+ return true;
+ }
+
+ /**
+ * Returns the villager type to spawn in this component, based on the number of
+ * villagers already spawned.
+ */
+ protected int getVillagerType(int par1) {
+ return 2;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentVillageField.java b/sp-server/src/main/java/net/minecraft/src/ComponentVillageField.java
new file mode 100644
index 0000000..9b144cd
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentVillageField.java
@@ -0,0 +1,128 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentVillageField extends ComponentVillage {
+ private int averageGroundLevel = -1;
+
+ /** First crop type for this field. */
+ private int cropTypeA;
+
+ /** Second crop type for this field. */
+ private int cropTypeB;
+
+ /** Third crop type for this field. */
+ private int cropTypeC;
+
+ /** Fourth crop type for this field. */
+ private int cropTypeD;
+
+ public ComponentVillageField(ComponentVillageStartPiece par1ComponentVillageStartPiece, int par2, EaglercraftRandom par3Random,
+ StructureBoundingBox par4StructureBoundingBox, int par5) {
+ super(par1ComponentVillageStartPiece, par2);
+ this.coordBaseMode = par5;
+ this.boundingBox = par4StructureBoundingBox;
+ this.cropTypeA = this.getRandomCrop(par3Random);
+ this.cropTypeB = this.getRandomCrop(par3Random);
+ this.cropTypeC = this.getRandomCrop(par3Random);
+ this.cropTypeD = this.getRandomCrop(par3Random);
+ }
+
+ /**
+ * Returns a crop type to be planted on this field.
+ */
+ private int getRandomCrop(EaglercraftRandom par1Random) {
+ switch (par1Random.nextInt(5)) {
+ case 0:
+ return Block.carrot.blockID;
+
+ case 1:
+ return Block.potato.blockID;
+
+ default:
+ return Block.crops.blockID;
+ }
+ }
+
+ public static ComponentVillageField func_74900_a(ComponentVillageStartPiece par0ComponentVillageStartPiece,
+ List par1List, EaglercraftRandom par2Random, int par3, int par4, int par5, int par6, int par7) {
+ StructureBoundingBox var8 = StructureBoundingBox.getComponentToAddBoundingBox(par3, par4, par5, 0, 0, 0, 13, 4,
+ 9, par6);
+ return canVillageGoDeeper(var8) && StructureComponent.findIntersecting(par1List, var8) == null
+ ? new ComponentVillageField(par0ComponentVillageStartPiece, par7, par2Random, var8, par6)
+ : null;
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ if (this.averageGroundLevel < 0) {
+ this.averageGroundLevel = this.getAverageGroundLevel(par1World, par3StructureBoundingBox);
+
+ if (this.averageGroundLevel < 0) {
+ return true;
+ }
+
+ this.boundingBox.offset(0, this.averageGroundLevel - this.boundingBox.maxY + 4 - 1, 0);
+ }
+
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 1, 0, 12, 4, 8, 0, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 0, 1, 2, 0, 7, Block.tilledField.blockID,
+ Block.tilledField.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 0, 1, 5, 0, 7, Block.tilledField.blockID,
+ Block.tilledField.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 7, 0, 1, 8, 0, 7, Block.tilledField.blockID,
+ Block.tilledField.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 10, 0, 1, 11, 0, 7, Block.tilledField.blockID,
+ Block.tilledField.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 0, 0, 0, 0, 8, Block.wood.blockID,
+ Block.wood.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 6, 0, 0, 6, 0, 8, Block.wood.blockID,
+ Block.wood.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 12, 0, 0, 12, 0, 8, Block.wood.blockID,
+ Block.wood.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 0, 0, 11, 0, 0, Block.wood.blockID,
+ Block.wood.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 0, 8, 11, 0, 8, Block.wood.blockID,
+ Block.wood.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 3, 0, 1, 3, 0, 7, Block.waterMoving.blockID,
+ Block.waterMoving.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 9, 0, 1, 9, 0, 7, Block.waterMoving.blockID,
+ Block.waterMoving.blockID, false);
+ int var4;
+
+ for (var4 = 1; var4 <= 7; ++var4) {
+ this.placeBlockAtCurrentPosition(par1World, this.cropTypeA,
+ MathHelper.getRandomIntegerInRange(par2Random, 2, 7), 1, 1, var4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, this.cropTypeA,
+ MathHelper.getRandomIntegerInRange(par2Random, 2, 7), 2, 1, var4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, this.cropTypeB,
+ MathHelper.getRandomIntegerInRange(par2Random, 2, 7), 4, 1, var4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, this.cropTypeB,
+ MathHelper.getRandomIntegerInRange(par2Random, 2, 7), 5, 1, var4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, this.cropTypeC,
+ MathHelper.getRandomIntegerInRange(par2Random, 2, 7), 7, 1, var4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, this.cropTypeC,
+ MathHelper.getRandomIntegerInRange(par2Random, 2, 7), 8, 1, var4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, this.cropTypeD,
+ MathHelper.getRandomIntegerInRange(par2Random, 2, 7), 10, 1, var4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, this.cropTypeD,
+ MathHelper.getRandomIntegerInRange(par2Random, 2, 7), 11, 1, var4, par3StructureBoundingBox);
+ }
+
+ for (var4 = 0; var4 < 9; ++var4) {
+ for (int var5 = 0; var5 < 13; ++var5) {
+ this.clearCurrentPositionBlocksUpwards(par1World, var5, 4, var4, par3StructureBoundingBox);
+ this.fillCurrentPositionBlocksDownwards(par1World, Block.dirt.blockID, 0, var5, -1, var4,
+ par3StructureBoundingBox);
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentVillageField2.java b/sp-server/src/main/java/net/minecraft/src/ComponentVillageField2.java
new file mode 100644
index 0000000..46cdb30
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentVillageField2.java
@@ -0,0 +1,104 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentVillageField2 extends ComponentVillage {
+ private int averageGroundLevel = -1;
+
+ /** First crop type for this field. */
+ private int cropTypeA;
+
+ /** Second crop type for this field. */
+ private int cropTypeB;
+
+ public ComponentVillageField2(ComponentVillageStartPiece par1ComponentVillageStartPiece, int par2,
+ EaglercraftRandom par3Random, StructureBoundingBox par4StructureBoundingBox, int par5) {
+ super(par1ComponentVillageStartPiece, par2);
+ this.coordBaseMode = par5;
+ this.boundingBox = par4StructureBoundingBox;
+ this.cropTypeA = this.pickRandomCrop(par3Random);
+ this.cropTypeB = this.pickRandomCrop(par3Random);
+ }
+
+ /**
+ * Returns a crop type to be planted on this field.
+ */
+ private int pickRandomCrop(EaglercraftRandom par1Random) {
+ switch (par1Random.nextInt(5)) {
+ case 0:
+ return Block.carrot.blockID;
+
+ case 1:
+ return Block.potato.blockID;
+
+ default:
+ return Block.crops.blockID;
+ }
+ }
+
+ public static ComponentVillageField2 func_74902_a(ComponentVillageStartPiece par0ComponentVillageStartPiece,
+ List par1List, EaglercraftRandom par2Random, int par3, int par4, int par5, int par6, int par7) {
+ StructureBoundingBox var8 = StructureBoundingBox.getComponentToAddBoundingBox(par3, par4, par5, 0, 0, 0, 7, 4,
+ 9, par6);
+ return canVillageGoDeeper(var8) && StructureComponent.findIntersecting(par1List, var8) == null
+ ? new ComponentVillageField2(par0ComponentVillageStartPiece, par7, par2Random, var8, par6)
+ : null;
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ if (this.averageGroundLevel < 0) {
+ this.averageGroundLevel = this.getAverageGroundLevel(par1World, par3StructureBoundingBox);
+
+ if (this.averageGroundLevel < 0) {
+ return true;
+ }
+
+ this.boundingBox.offset(0, this.averageGroundLevel - this.boundingBox.maxY + 4 - 1, 0);
+ }
+
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 1, 0, 6, 4, 8, 0, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 0, 1, 2, 0, 7, Block.tilledField.blockID,
+ Block.tilledField.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 0, 1, 5, 0, 7, Block.tilledField.blockID,
+ Block.tilledField.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 0, 0, 0, 0, 8, Block.wood.blockID,
+ Block.wood.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 6, 0, 0, 6, 0, 8, Block.wood.blockID,
+ Block.wood.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 0, 0, 5, 0, 0, Block.wood.blockID,
+ Block.wood.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 0, 8, 5, 0, 8, Block.wood.blockID,
+ Block.wood.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 3, 0, 1, 3, 0, 7, Block.waterMoving.blockID,
+ Block.waterMoving.blockID, false);
+ int var4;
+
+ for (var4 = 1; var4 <= 7; ++var4) {
+ this.placeBlockAtCurrentPosition(par1World, this.cropTypeA,
+ MathHelper.getRandomIntegerInRange(par2Random, 2, 7), 1, 1, var4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, this.cropTypeA,
+ MathHelper.getRandomIntegerInRange(par2Random, 2, 7), 2, 1, var4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, this.cropTypeB,
+ MathHelper.getRandomIntegerInRange(par2Random, 2, 7), 4, 1, var4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, this.cropTypeB,
+ MathHelper.getRandomIntegerInRange(par2Random, 2, 7), 5, 1, var4, par3StructureBoundingBox);
+ }
+
+ for (var4 = 0; var4 < 9; ++var4) {
+ for (int var5 = 0; var5 < 7; ++var5) {
+ this.clearCurrentPositionBlocksUpwards(par1World, var5, 4, var4, par3StructureBoundingBox);
+ this.fillCurrentPositionBlocksDownwards(par1World, Block.dirt.blockID, 0, var5, -1, var4,
+ par3StructureBoundingBox);
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentVillageHall.java b/sp-server/src/main/java/net/minecraft/src/ComponentVillageHall.java
new file mode 100644
index 0000000..506e462
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentVillageHall.java
@@ -0,0 +1,154 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentVillageHall extends ComponentVillage {
+ private int averageGroundLevel = -1;
+
+ public ComponentVillageHall(ComponentVillageStartPiece par1ComponentVillageStartPiece, int par2, EaglercraftRandom par3Random,
+ StructureBoundingBox par4StructureBoundingBox, int par5) {
+ super(par1ComponentVillageStartPiece, par2);
+ this.coordBaseMode = par5;
+ this.boundingBox = par4StructureBoundingBox;
+ }
+
+ public static ComponentVillageHall func_74906_a(ComponentVillageStartPiece par0ComponentVillageStartPiece,
+ List par1List, EaglercraftRandom par2Random, int par3, int par4, int par5, int par6, int par7) {
+ StructureBoundingBox var8 = StructureBoundingBox.getComponentToAddBoundingBox(par3, par4, par5, 0, 0, 0, 9, 7,
+ 11, par6);
+ return canVillageGoDeeper(var8) && StructureComponent.findIntersecting(par1List, var8) == null
+ ? new ComponentVillageHall(par0ComponentVillageStartPiece, par7, par2Random, var8, par6)
+ : null;
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ if (this.averageGroundLevel < 0) {
+ this.averageGroundLevel = this.getAverageGroundLevel(par1World, par3StructureBoundingBox);
+
+ if (this.averageGroundLevel < 0) {
+ return true;
+ }
+
+ this.boundingBox.offset(0, this.averageGroundLevel - this.boundingBox.maxY + 7 - 1, 0);
+ }
+
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 1, 1, 7, 4, 4, 0, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 2, 1, 6, 8, 4, 10, 0, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 2, 0, 6, 8, 0, 10, Block.dirt.blockID,
+ Block.dirt.blockID, false);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestone.blockID, 0, 6, 0, 6, par3StructureBoundingBox);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 2, 1, 6, 2, 1, 10, Block.fence.blockID,
+ Block.fence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 8, 1, 6, 8, 1, 10, Block.fence.blockID,
+ Block.fence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 3, 1, 10, 7, 1, 10, Block.fence.blockID,
+ Block.fence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 0, 1, 7, 0, 4, Block.planks.blockID,
+ Block.planks.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 0, 0, 0, 3, 5, Block.cobblestone.blockID,
+ Block.cobblestone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 8, 0, 0, 8, 3, 5, Block.cobblestone.blockID,
+ Block.cobblestone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 0, 0, 7, 1, 0, Block.cobblestone.blockID,
+ Block.cobblestone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 0, 5, 7, 1, 5, Block.cobblestone.blockID,
+ Block.cobblestone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 2, 0, 7, 3, 0, Block.planks.blockID,
+ Block.planks.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 2, 5, 7, 3, 5, Block.planks.blockID,
+ Block.planks.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 4, 1, 8, 4, 1, Block.planks.blockID,
+ Block.planks.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 4, 4, 8, 4, 4, Block.planks.blockID,
+ Block.planks.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 5, 2, 8, 5, 3, Block.planks.blockID,
+ Block.planks.blockID, false);
+ this.placeBlockAtCurrentPosition(par1World, Block.planks.blockID, 0, 0, 4, 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.planks.blockID, 0, 0, 4, 3, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.planks.blockID, 0, 8, 4, 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.planks.blockID, 0, 8, 4, 3, par3StructureBoundingBox);
+ int var4 = this.getMetadataWithOffset(Block.stairsWoodOak.blockID, 3);
+ int var5 = this.getMetadataWithOffset(Block.stairsWoodOak.blockID, 2);
+ int var6;
+ int var7;
+
+ for (var6 = -1; var6 <= 2; ++var6) {
+ for (var7 = 0; var7 <= 8; ++var7) {
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsWoodOak.blockID, var4, var7, 4 + var6, var6,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsWoodOak.blockID, var5, var7, 4 + var6, 5 - var6,
+ par3StructureBoundingBox);
+ }
+ }
+
+ this.placeBlockAtCurrentPosition(par1World, Block.wood.blockID, 0, 0, 2, 1, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.wood.blockID, 0, 0, 2, 4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.wood.blockID, 0, 8, 2, 1, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.wood.blockID, 0, 8, 2, 4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 0, 2, 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 0, 2, 3, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 8, 2, 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 8, 2, 3, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 2, 2, 5, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 3, 2, 5, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 5, 2, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 6, 2, 5, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, 2, 1, 3, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.pressurePlatePlanks.blockID, 0, 2, 2, 3,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.planks.blockID, 0, 1, 1, 4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsWoodOak.blockID,
+ this.getMetadataWithOffset(Block.stairsWoodOak.blockID, 3), 2, 1, 4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsWoodOak.blockID,
+ this.getMetadataWithOffset(Block.stairsWoodOak.blockID, 1), 1, 1, 3, par3StructureBoundingBox);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 5, 0, 1, 7, 0, 3, Block.stoneDoubleSlab.blockID,
+ Block.stoneDoubleSlab.blockID, false);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneDoubleSlab.blockID, 0, 6, 1, 1,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneDoubleSlab.blockID, 0, 6, 1, 2,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, 2, 1, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, 2, 2, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.torchWood.blockID, 0, 2, 3, 1, par3StructureBoundingBox);
+ this.placeDoorAtCurrentPosition(par1World, par3StructureBoundingBox, par2Random, 2, 1, 0,
+ this.getMetadataWithOffset(Block.doorWood.blockID, 1));
+
+ if (this.getBlockIdAtCurrentPosition(par1World, 2, 0, -1, par3StructureBoundingBox) == 0
+ && this.getBlockIdAtCurrentPosition(par1World, 2, -1, -1, par3StructureBoundingBox) != 0) {
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsCobblestone.blockID,
+ this.getMetadataWithOffset(Block.stairsCobblestone.blockID, 3), 2, 0, -1, par3StructureBoundingBox);
+ }
+
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, 6, 1, 5, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, 6, 2, 5, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.torchWood.blockID, 0, 6, 3, 4, par3StructureBoundingBox);
+ this.placeDoorAtCurrentPosition(par1World, par3StructureBoundingBox, par2Random, 6, 1, 5,
+ this.getMetadataWithOffset(Block.doorWood.blockID, 1));
+
+ for (var6 = 0; var6 < 5; ++var6) {
+ for (var7 = 0; var7 < 9; ++var7) {
+ this.clearCurrentPositionBlocksUpwards(par1World, var7, 7, var6, par3StructureBoundingBox);
+ this.fillCurrentPositionBlocksDownwards(par1World, Block.cobblestone.blockID, 0, var7, -1, var6,
+ par3StructureBoundingBox);
+ }
+ }
+
+ this.spawnVillagers(par1World, par3StructureBoundingBox, 4, 1, 2, 2);
+ return true;
+ }
+
+ /**
+ * Returns the villager type to spawn in this component, based on the number of
+ * villagers already spawned.
+ */
+ protected int getVillagerType(int par1) {
+ return par1 == 0 ? 4 : 0;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentVillageHouse1.java b/sp-server/src/main/java/net/minecraft/src/ComponentVillageHouse1.java
new file mode 100644
index 0000000..1af7ebe
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentVillageHouse1.java
@@ -0,0 +1,162 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentVillageHouse1 extends ComponentVillage {
+ private int averageGroundLevel = -1;
+
+ public ComponentVillageHouse1(ComponentVillageStartPiece par1ComponentVillageStartPiece, int par2,
+ EaglercraftRandom par3Random, StructureBoundingBox par4StructureBoundingBox, int par5) {
+ super(par1ComponentVillageStartPiece, par2);
+ this.coordBaseMode = par5;
+ this.boundingBox = par4StructureBoundingBox;
+ }
+
+ public static ComponentVillageHouse1 func_74898_a(ComponentVillageStartPiece par0ComponentVillageStartPiece,
+ List par1List, EaglercraftRandom par2Random, int par3, int par4, int par5, int par6, int par7) {
+ StructureBoundingBox var8 = StructureBoundingBox.getComponentToAddBoundingBox(par3, par4, par5, 0, 0, 0, 9, 9,
+ 6, par6);
+ return canVillageGoDeeper(var8) && StructureComponent.findIntersecting(par1List, var8) == null
+ ? new ComponentVillageHouse1(par0ComponentVillageStartPiece, par7, par2Random, var8, par6)
+ : null;
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ if (this.averageGroundLevel < 0) {
+ this.averageGroundLevel = this.getAverageGroundLevel(par1World, par3StructureBoundingBox);
+
+ if (this.averageGroundLevel < 0) {
+ return true;
+ }
+
+ this.boundingBox.offset(0, this.averageGroundLevel - this.boundingBox.maxY + 9 - 1, 0);
+ }
+
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 1, 1, 7, 5, 4, 0, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 0, 0, 8, 0, 5, Block.cobblestone.blockID,
+ Block.cobblestone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 5, 0, 8, 5, 5, Block.cobblestone.blockID,
+ Block.cobblestone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 6, 1, 8, 6, 4, Block.cobblestone.blockID,
+ Block.cobblestone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 7, 2, 8, 7, 3, Block.cobblestone.blockID,
+ Block.cobblestone.blockID, false);
+ int var4 = this.getMetadataWithOffset(Block.stairsWoodOak.blockID, 3);
+ int var5 = this.getMetadataWithOffset(Block.stairsWoodOak.blockID, 2);
+ int var6;
+ int var7;
+
+ for (var6 = -1; var6 <= 2; ++var6) {
+ for (var7 = 0; var7 <= 8; ++var7) {
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsWoodOak.blockID, var4, var7, 6 + var6, var6,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsWoodOak.blockID, var5, var7, 6 + var6, 5 - var6,
+ par3StructureBoundingBox);
+ }
+ }
+
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 1, 0, 0, 1, 5, Block.cobblestone.blockID,
+ Block.cobblestone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 1, 5, 8, 1, 5, Block.cobblestone.blockID,
+ Block.cobblestone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 8, 1, 0, 8, 1, 4, Block.cobblestone.blockID,
+ Block.cobblestone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 2, 1, 0, 7, 1, 0, Block.cobblestone.blockID,
+ Block.cobblestone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 2, 0, 0, 4, 0, Block.cobblestone.blockID,
+ Block.cobblestone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 2, 5, 0, 4, 5, Block.cobblestone.blockID,
+ Block.cobblestone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 8, 2, 5, 8, 4, 5, Block.cobblestone.blockID,
+ Block.cobblestone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 8, 2, 0, 8, 4, 0, Block.cobblestone.blockID,
+ Block.cobblestone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 2, 1, 0, 4, 4, Block.planks.blockID,
+ Block.planks.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 2, 5, 7, 4, 5, Block.planks.blockID,
+ Block.planks.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 8, 2, 1, 8, 4, 4, Block.planks.blockID,
+ Block.planks.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 2, 0, 7, 4, 0, Block.planks.blockID,
+ Block.planks.blockID, false);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 4, 2, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 5, 2, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 6, 2, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 4, 3, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 5, 3, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 6, 3, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 0, 2, 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 0, 2, 3, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 0, 3, 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 0, 3, 3, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 8, 2, 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 8, 2, 3, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 8, 3, 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 8, 3, 3, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 2, 2, 5, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 3, 2, 5, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 5, 2, 5, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 6, 2, 5, par3StructureBoundingBox);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 4, 1, 7, 4, 1, Block.planks.blockID,
+ Block.planks.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 4, 4, 7, 4, 4, Block.planks.blockID,
+ Block.planks.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 3, 4, 7, 3, 4, Block.bookShelf.blockID,
+ Block.bookShelf.blockID, false);
+ this.placeBlockAtCurrentPosition(par1World, Block.planks.blockID, 0, 7, 1, 4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsWoodOak.blockID,
+ this.getMetadataWithOffset(Block.stairsWoodOak.blockID, 0), 7, 1, 3, par3StructureBoundingBox);
+ var6 = this.getMetadataWithOffset(Block.stairsWoodOak.blockID, 3);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsWoodOak.blockID, var6, 6, 1, 4,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsWoodOak.blockID, var6, 5, 1, 4,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsWoodOak.blockID, var6, 4, 1, 4,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsWoodOak.blockID, var6, 3, 1, 4,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, 6, 1, 3, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.pressurePlatePlanks.blockID, 0, 6, 2, 3,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, 4, 1, 3, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.pressurePlatePlanks.blockID, 0, 4, 2, 3,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.workbench.blockID, 0, 7, 1, 1, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, 1, 1, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, 1, 2, 0, par3StructureBoundingBox);
+ this.placeDoorAtCurrentPosition(par1World, par3StructureBoundingBox, par2Random, 1, 1, 0,
+ this.getMetadataWithOffset(Block.doorWood.blockID, 1));
+
+ if (this.getBlockIdAtCurrentPosition(par1World, 1, 0, -1, par3StructureBoundingBox) == 0
+ && this.getBlockIdAtCurrentPosition(par1World, 1, -1, -1, par3StructureBoundingBox) != 0) {
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsCobblestone.blockID,
+ this.getMetadataWithOffset(Block.stairsCobblestone.blockID, 3), 1, 0, -1, par3StructureBoundingBox);
+ }
+
+ for (var7 = 0; var7 < 6; ++var7) {
+ for (int var8 = 0; var8 < 9; ++var8) {
+ this.clearCurrentPositionBlocksUpwards(par1World, var8, 9, var7, par3StructureBoundingBox);
+ this.fillCurrentPositionBlocksDownwards(par1World, Block.cobblestone.blockID, 0, var8, -1, var7,
+ par3StructureBoundingBox);
+ }
+ }
+
+ this.spawnVillagers(par1World, par3StructureBoundingBox, 2, 1, 2, 1);
+ return true;
+ }
+
+ /**
+ * Returns the villager type to spawn in this component, based on the number of
+ * villagers already spawned.
+ */
+ protected int getVillagerType(int par1) {
+ return 1;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentVillageHouse2.java b/sp-server/src/main/java/net/minecraft/src/ComponentVillageHouse2.java
new file mode 100644
index 0000000..f1e6d34
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentVillageHouse2.java
@@ -0,0 +1,154 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentVillageHouse2 extends ComponentVillage {
+ /** List of items that Village's Blacksmith chest can contain. */
+ private static final WeightedRandomChestContent[] villageBlacksmithChestContents = new WeightedRandomChestContent[] {
+ new WeightedRandomChestContent(Item.diamond.itemID, 0, 1, 3, 3),
+ new WeightedRandomChestContent(Item.ingotIron.itemID, 0, 1, 5, 10),
+ new WeightedRandomChestContent(Item.ingotGold.itemID, 0, 1, 3, 5),
+ new WeightedRandomChestContent(Item.bread.itemID, 0, 1, 3, 15),
+ new WeightedRandomChestContent(Item.appleRed.itemID, 0, 1, 3, 15),
+ new WeightedRandomChestContent(Item.pickaxeIron.itemID, 0, 1, 1, 5),
+ new WeightedRandomChestContent(Item.swordIron.itemID, 0, 1, 1, 5),
+ new WeightedRandomChestContent(Item.plateIron.itemID, 0, 1, 1, 5),
+ new WeightedRandomChestContent(Item.helmetIron.itemID, 0, 1, 1, 5),
+ new WeightedRandomChestContent(Item.legsIron.itemID, 0, 1, 1, 5),
+ new WeightedRandomChestContent(Item.bootsIron.itemID, 0, 1, 1, 5),
+ new WeightedRandomChestContent(Block.obsidian.blockID, 0, 3, 7, 5),
+ new WeightedRandomChestContent(Block.sapling.blockID, 0, 3, 7, 5) };
+ private int averageGroundLevel = -1;
+ private boolean hasMadeChest;
+
+ public ComponentVillageHouse2(ComponentVillageStartPiece par1ComponentVillageStartPiece, int par2,
+ EaglercraftRandom par3Random, StructureBoundingBox par4StructureBoundingBox, int par5) {
+ super(par1ComponentVillageStartPiece, par2);
+ this.coordBaseMode = par5;
+ this.boundingBox = par4StructureBoundingBox;
+ }
+
+ public static ComponentVillageHouse2 func_74915_a(ComponentVillageStartPiece par0ComponentVillageStartPiece,
+ List par1List, EaglercraftRandom par2Random, int par3, int par4, int par5, int par6, int par7) {
+ StructureBoundingBox var8 = StructureBoundingBox.getComponentToAddBoundingBox(par3, par4, par5, 0, 0, 0, 10, 6,
+ 7, par6);
+ return canVillageGoDeeper(var8) && StructureComponent.findIntersecting(par1List, var8) == null
+ ? new ComponentVillageHouse2(par0ComponentVillageStartPiece, par7, par2Random, var8, par6)
+ : null;
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ if (this.averageGroundLevel < 0) {
+ this.averageGroundLevel = this.getAverageGroundLevel(par1World, par3StructureBoundingBox);
+
+ if (this.averageGroundLevel < 0) {
+ return true;
+ }
+
+ this.boundingBox.offset(0, this.averageGroundLevel - this.boundingBox.maxY + 6 - 1, 0);
+ }
+
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 1, 0, 9, 4, 6, 0, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 0, 0, 9, 0, 6, Block.cobblestone.blockID,
+ Block.cobblestone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 4, 0, 9, 4, 6, Block.cobblestone.blockID,
+ Block.cobblestone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 5, 0, 9, 5, 6, Block.stoneSingleSlab.blockID,
+ Block.stoneSingleSlab.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 5, 1, 8, 5, 5, 0, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 1, 0, 2, 3, 0, Block.planks.blockID,
+ Block.planks.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 1, 0, 0, 4, 0, Block.wood.blockID,
+ Block.wood.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 3, 1, 0, 3, 4, 0, Block.wood.blockID,
+ Block.wood.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 1, 6, 0, 4, 6, Block.wood.blockID,
+ Block.wood.blockID, false);
+ this.placeBlockAtCurrentPosition(par1World, Block.planks.blockID, 0, 3, 3, 1, par3StructureBoundingBox);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 3, 1, 2, 3, 3, 2, Block.planks.blockID,
+ Block.planks.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 1, 3, 5, 3, 3, Block.planks.blockID,
+ Block.planks.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 1, 1, 0, 3, 5, Block.planks.blockID,
+ Block.planks.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 1, 6, 5, 3, 6, Block.planks.blockID,
+ Block.planks.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 5, 1, 0, 5, 3, 0, Block.fence.blockID,
+ Block.fence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 9, 1, 0, 9, 3, 0, Block.fence.blockID,
+ Block.fence.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 6, 1, 4, 9, 4, 6, Block.cobblestone.blockID,
+ Block.cobblestone.blockID, false);
+ this.placeBlockAtCurrentPosition(par1World, Block.lavaMoving.blockID, 0, 7, 1, 5, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.lavaMoving.blockID, 0, 8, 1, 5, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fenceIron.blockID, 0, 9, 2, 5, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fenceIron.blockID, 0, 9, 2, 4, par3StructureBoundingBox);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 7, 2, 4, 8, 2, 5, 0, 0, false);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestone.blockID, 0, 6, 1, 3, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.furnaceIdle.blockID, 0, 6, 2, 3, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.furnaceIdle.blockID, 0, 6, 3, 3, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stoneDoubleSlab.blockID, 0, 8, 1, 1,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 0, 2, 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 0, 2, 4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 2, 2, 6, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 4, 2, 6, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, 2, 1, 4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.pressurePlatePlanks.blockID, 0, 2, 2, 4,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.planks.blockID, 0, 1, 1, 5, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsWoodOak.blockID,
+ this.getMetadataWithOffset(Block.stairsWoodOak.blockID, 3), 2, 1, 5, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsWoodOak.blockID,
+ this.getMetadataWithOffset(Block.stairsWoodOak.blockID, 1), 1, 1, 4, par3StructureBoundingBox);
+ int var4;
+ int var5;
+
+ if (!this.hasMadeChest) {
+ var4 = this.getYWithOffset(1);
+ var5 = this.getXWithOffset(5, 5);
+ int var6 = this.getZWithOffset(5, 5);
+
+ if (par3StructureBoundingBox.isVecInside(var5, var4, var6)) {
+ this.hasMadeChest = true;
+ this.generateStructureChestContents(par1World, par3StructureBoundingBox, par2Random, 5, 1, 5,
+ villageBlacksmithChestContents, 3 + par2Random.nextInt(6));
+ }
+ }
+
+ for (var4 = 6; var4 <= 8; ++var4) {
+ if (this.getBlockIdAtCurrentPosition(par1World, var4, 0, -1, par3StructureBoundingBox) == 0
+ && this.getBlockIdAtCurrentPosition(par1World, var4, -1, -1, par3StructureBoundingBox) != 0) {
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsCobblestone.blockID,
+ this.getMetadataWithOffset(Block.stairsCobblestone.blockID, 3), var4, 0, -1,
+ par3StructureBoundingBox);
+ }
+ }
+
+ for (var4 = 0; var4 < 7; ++var4) {
+ for (var5 = 0; var5 < 10; ++var5) {
+ this.clearCurrentPositionBlocksUpwards(par1World, var5, 6, var4, par3StructureBoundingBox);
+ this.fillCurrentPositionBlocksDownwards(par1World, Block.cobblestone.blockID, 0, var5, -1, var4,
+ par3StructureBoundingBox);
+ }
+ }
+
+ this.spawnVillagers(par1World, par3StructureBoundingBox, 7, 1, 1, 1);
+ return true;
+ }
+
+ /**
+ * Returns the villager type to spawn in this component, based on the number of
+ * villagers already spawned.
+ */
+ protected int getVillagerType(int par1) {
+ return 3;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentVillageHouse3.java b/sp-server/src/main/java/net/minecraft/src/ComponentVillageHouse3.java
new file mode 100644
index 0000000..cb56094
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentVillageHouse3.java
@@ -0,0 +1,185 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentVillageHouse3 extends ComponentVillage {
+ private int averageGroundLevel = -1;
+
+ public ComponentVillageHouse3(ComponentVillageStartPiece par1ComponentVillageStartPiece, int par2,
+ EaglercraftRandom par3Random, StructureBoundingBox par4StructureBoundingBox, int par5) {
+ super(par1ComponentVillageStartPiece, par2);
+ this.coordBaseMode = par5;
+ this.boundingBox = par4StructureBoundingBox;
+ }
+
+ public static ComponentVillageHouse3 func_74921_a(ComponentVillageStartPiece par0ComponentVillageStartPiece,
+ List par1List, EaglercraftRandom par2Random, int par3, int par4, int par5, int par6, int par7) {
+ StructureBoundingBox var8 = StructureBoundingBox.getComponentToAddBoundingBox(par3, par4, par5, 0, 0, 0, 9, 7,
+ 12, par6);
+ return canVillageGoDeeper(var8) && StructureComponent.findIntersecting(par1List, var8) == null
+ ? new ComponentVillageHouse3(par0ComponentVillageStartPiece, par7, par2Random, var8, par6)
+ : null;
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ if (this.averageGroundLevel < 0) {
+ this.averageGroundLevel = this.getAverageGroundLevel(par1World, par3StructureBoundingBox);
+
+ if (this.averageGroundLevel < 0) {
+ return true;
+ }
+
+ this.boundingBox.offset(0, this.averageGroundLevel - this.boundingBox.maxY + 7 - 1, 0);
+ }
+
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 1, 1, 7, 4, 4, 0, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 2, 1, 6, 8, 4, 10, 0, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 2, 0, 5, 8, 0, 10, Block.planks.blockID,
+ Block.planks.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 0, 1, 7, 0, 4, Block.planks.blockID,
+ Block.planks.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 0, 0, 0, 3, 5, Block.cobblestone.blockID,
+ Block.cobblestone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 8, 0, 0, 8, 3, 10, Block.cobblestone.blockID,
+ Block.cobblestone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 0, 0, 7, 2, 0, Block.cobblestone.blockID,
+ Block.cobblestone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 0, 5, 2, 1, 5, Block.cobblestone.blockID,
+ Block.cobblestone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 2, 0, 6, 2, 3, 10, Block.cobblestone.blockID,
+ Block.cobblestone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 3, 0, 10, 7, 3, 10, Block.cobblestone.blockID,
+ Block.cobblestone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 2, 0, 7, 3, 0, Block.planks.blockID,
+ Block.planks.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 2, 5, 2, 3, 5, Block.planks.blockID,
+ Block.planks.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 4, 1, 8, 4, 1, Block.planks.blockID,
+ Block.planks.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 4, 4, 3, 4, 4, Block.planks.blockID,
+ Block.planks.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 5, 2, 8, 5, 3, Block.planks.blockID,
+ Block.planks.blockID, false);
+ this.placeBlockAtCurrentPosition(par1World, Block.planks.blockID, 0, 0, 4, 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.planks.blockID, 0, 0, 4, 3, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.planks.blockID, 0, 8, 4, 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.planks.blockID, 0, 8, 4, 3, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.planks.blockID, 0, 8, 4, 4, par3StructureBoundingBox);
+ int var4 = this.getMetadataWithOffset(Block.stairsWoodOak.blockID, 3);
+ int var5 = this.getMetadataWithOffset(Block.stairsWoodOak.blockID, 2);
+ int var6;
+ int var7;
+
+ for (var6 = -1; var6 <= 2; ++var6) {
+ for (var7 = 0; var7 <= 8; ++var7) {
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsWoodOak.blockID, var4, var7, 4 + var6, var6,
+ par3StructureBoundingBox);
+
+ if ((var6 > -1 || var7 <= 1) && (var6 > 0 || var7 <= 3) && (var6 > 1 || var7 <= 4 || var7 >= 6)) {
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsWoodOak.blockID, var5, var7, 4 + var6,
+ 5 - var6, par3StructureBoundingBox);
+ }
+ }
+ }
+
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 3, 4, 5, 3, 4, 10, Block.planks.blockID,
+ Block.planks.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 7, 4, 2, 7, 4, 10, Block.planks.blockID,
+ Block.planks.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 5, 4, 4, 5, 10, Block.planks.blockID,
+ Block.planks.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 6, 5, 4, 6, 5, 10, Block.planks.blockID,
+ Block.planks.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 5, 6, 3, 5, 6, 10, Block.planks.blockID,
+ Block.planks.blockID, false);
+ var6 = this.getMetadataWithOffset(Block.stairsWoodOak.blockID, 0);
+ int var8;
+
+ for (var7 = 4; var7 >= 1; --var7) {
+ this.placeBlockAtCurrentPosition(par1World, Block.planks.blockID, 0, var7, 2 + var7, 7 - var7,
+ par3StructureBoundingBox);
+
+ for (var8 = 8 - var7; var8 <= 10; ++var8) {
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsWoodOak.blockID, var6, var7, 2 + var7, var8,
+ par3StructureBoundingBox);
+ }
+ }
+
+ var7 = this.getMetadataWithOffset(Block.stairsWoodOak.blockID, 1);
+ this.placeBlockAtCurrentPosition(par1World, Block.planks.blockID, 0, 6, 6, 3, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.planks.blockID, 0, 7, 5, 4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsWoodOak.blockID, var7, 6, 6, 4,
+ par3StructureBoundingBox);
+ int var9;
+
+ for (var8 = 6; var8 <= 8; ++var8) {
+ for (var9 = 5; var9 <= 10; ++var9) {
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsWoodOak.blockID, var7, var8, 12 - var8, var9,
+ par3StructureBoundingBox);
+ }
+ }
+
+ this.placeBlockAtCurrentPosition(par1World, Block.wood.blockID, 0, 0, 2, 1, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.wood.blockID, 0, 0, 2, 4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 0, 2, 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 0, 2, 3, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.wood.blockID, 0, 4, 2, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 5, 2, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.wood.blockID, 0, 6, 2, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.wood.blockID, 0, 8, 2, 1, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 8, 2, 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 8, 2, 3, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.wood.blockID, 0, 8, 2, 4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.planks.blockID, 0, 8, 2, 5, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.wood.blockID, 0, 8, 2, 6, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 8, 2, 7, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 8, 2, 8, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.wood.blockID, 0, 8, 2, 9, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.wood.blockID, 0, 2, 2, 6, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 2, 2, 7, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 2, 2, 8, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.wood.blockID, 0, 2, 2, 9, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.wood.blockID, 0, 4, 4, 10, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 5, 4, 10, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.wood.blockID, 0, 6, 4, 10, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.planks.blockID, 0, 5, 5, 10, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, 2, 1, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, 2, 2, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.torchWood.blockID, 0, 2, 3, 1, par3StructureBoundingBox);
+ this.placeDoorAtCurrentPosition(par1World, par3StructureBoundingBox, par2Random, 2, 1, 0,
+ this.getMetadataWithOffset(Block.doorWood.blockID, 1));
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 0, -1, 3, 2, -1, 0, 0, false);
+
+ if (this.getBlockIdAtCurrentPosition(par1World, 2, 0, -1, par3StructureBoundingBox) == 0
+ && this.getBlockIdAtCurrentPosition(par1World, 2, -1, -1, par3StructureBoundingBox) != 0) {
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsCobblestone.blockID,
+ this.getMetadataWithOffset(Block.stairsCobblestone.blockID, 3), 2, 0, -1, par3StructureBoundingBox);
+ }
+
+ for (var8 = 0; var8 < 5; ++var8) {
+ for (var9 = 0; var9 < 9; ++var9) {
+ this.clearCurrentPositionBlocksUpwards(par1World, var9, 7, var8, par3StructureBoundingBox);
+ this.fillCurrentPositionBlocksDownwards(par1World, Block.cobblestone.blockID, 0, var9, -1, var8,
+ par3StructureBoundingBox);
+ }
+ }
+
+ for (var8 = 5; var8 < 11; ++var8) {
+ for (var9 = 2; var9 < 9; ++var9) {
+ this.clearCurrentPositionBlocksUpwards(par1World, var9, 7, var8, par3StructureBoundingBox);
+ this.fillCurrentPositionBlocksDownwards(par1World, Block.cobblestone.blockID, 0, var9, -1, var8,
+ par3StructureBoundingBox);
+ }
+ }
+
+ this.spawnVillagers(par1World, par3StructureBoundingBox, 4, 1, 2, 2);
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentVillageHouse4_Garden.java b/sp-server/src/main/java/net/minecraft/src/ComponentVillageHouse4_Garden.java
new file mode 100644
index 0000000..f85b82d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentVillageHouse4_Garden.java
@@ -0,0 +1,128 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentVillageHouse4_Garden extends ComponentVillage {
+ private int averageGroundLevel = -1;
+ private final boolean isRoofAccessible;
+
+ public ComponentVillageHouse4_Garden(ComponentVillageStartPiece par1ComponentVillageStartPiece, int par2,
+ EaglercraftRandom par3Random, StructureBoundingBox par4StructureBoundingBox, int par5) {
+ super(par1ComponentVillageStartPiece, par2);
+ this.coordBaseMode = par5;
+ this.boundingBox = par4StructureBoundingBox;
+ this.isRoofAccessible = par3Random.nextBoolean();
+ }
+
+ public static ComponentVillageHouse4_Garden func_74912_a(ComponentVillageStartPiece par0ComponentVillageStartPiece,
+ List par1List, EaglercraftRandom par2Random, int par3, int par4, int par5, int par6, int par7) {
+ StructureBoundingBox var8 = StructureBoundingBox.getComponentToAddBoundingBox(par3, par4, par5, 0, 0, 0, 5, 6,
+ 5, par6);
+ return StructureComponent.findIntersecting(par1List, var8) != null ? null
+ : new ComponentVillageHouse4_Garden(par0ComponentVillageStartPiece, par7, par2Random, var8, par6);
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ if (this.averageGroundLevel < 0) {
+ this.averageGroundLevel = this.getAverageGroundLevel(par1World, par3StructureBoundingBox);
+
+ if (this.averageGroundLevel < 0) {
+ return true;
+ }
+
+ this.boundingBox.offset(0, this.averageGroundLevel - this.boundingBox.maxY + 6 - 1, 0);
+ }
+
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 0, 0, 4, 0, 4, Block.cobblestone.blockID,
+ Block.cobblestone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 4, 0, 4, 4, 4, Block.wood.blockID,
+ Block.wood.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 4, 1, 3, 4, 3, Block.planks.blockID,
+ Block.planks.blockID, false);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestone.blockID, 0, 0, 1, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestone.blockID, 0, 0, 2, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestone.blockID, 0, 0, 3, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestone.blockID, 0, 4, 1, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestone.blockID, 0, 4, 2, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestone.blockID, 0, 4, 3, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestone.blockID, 0, 0, 1, 4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestone.blockID, 0, 0, 2, 4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestone.blockID, 0, 0, 3, 4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestone.blockID, 0, 4, 1, 4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestone.blockID, 0, 4, 2, 4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cobblestone.blockID, 0, 4, 3, 4, par3StructureBoundingBox);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 1, 1, 0, 3, 3, Block.planks.blockID,
+ Block.planks.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 4, 1, 1, 4, 3, 3, Block.planks.blockID,
+ Block.planks.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 1, 4, 3, 3, 4, Block.planks.blockID,
+ Block.planks.blockID, false);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 0, 2, 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 2, 2, 4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 4, 2, 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.planks.blockID, 0, 1, 1, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.planks.blockID, 0, 1, 2, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.planks.blockID, 0, 1, 3, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.planks.blockID, 0, 2, 3, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.planks.blockID, 0, 3, 3, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.planks.blockID, 0, 3, 2, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.planks.blockID, 0, 3, 1, 0, par3StructureBoundingBox);
+
+ if (this.getBlockIdAtCurrentPosition(par1World, 2, 0, -1, par3StructureBoundingBox) == 0
+ && this.getBlockIdAtCurrentPosition(par1World, 2, -1, -1, par3StructureBoundingBox) != 0) {
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsCobblestone.blockID,
+ this.getMetadataWithOffset(Block.stairsCobblestone.blockID, 3), 2, 0, -1, par3StructureBoundingBox);
+ }
+
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 1, 1, 3, 3, 3, 0, 0, false);
+
+ if (this.isRoofAccessible) {
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, 0, 5, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, 1, 5, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, 2, 5, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, 3, 5, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, 4, 5, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, 0, 5, 4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, 1, 5, 4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, 2, 5, 4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, 3, 5, 4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, 4, 5, 4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, 4, 5, 1, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, 4, 5, 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, 4, 5, 3, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, 0, 5, 1, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, 0, 5, 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, 0, 5, 3, par3StructureBoundingBox);
+ }
+
+ int var4;
+
+ if (this.isRoofAccessible) {
+ var4 = this.getMetadataWithOffset(Block.ladder.blockID, 3);
+ this.placeBlockAtCurrentPosition(par1World, Block.ladder.blockID, var4, 3, 1, 3, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.ladder.blockID, var4, 3, 2, 3, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.ladder.blockID, var4, 3, 3, 3, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.ladder.blockID, var4, 3, 4, 3, par3StructureBoundingBox);
+ }
+
+ this.placeBlockAtCurrentPosition(par1World, Block.torchWood.blockID, 0, 2, 3, 1, par3StructureBoundingBox);
+
+ for (var4 = 0; var4 < 5; ++var4) {
+ for (int var5 = 0; var5 < 5; ++var5) {
+ this.clearCurrentPositionBlocksUpwards(par1World, var5, 6, var4, par3StructureBoundingBox);
+ this.fillCurrentPositionBlocksDownwards(par1World, Block.cobblestone.blockID, 0, var5, -1, var4,
+ par3StructureBoundingBox);
+ }
+ }
+
+ this.spawnVillagers(par1World, par3StructureBoundingBox, 1, 1, 2, 1);
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentVillagePathGen.java b/sp-server/src/main/java/net/minecraft/src/ComponentVillagePathGen.java
new file mode 100644
index 0000000..e03c815
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentVillagePathGen.java
@@ -0,0 +1,143 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentVillagePathGen extends ComponentVillageRoadPiece {
+ private int averageGroundLevel;
+
+ public ComponentVillagePathGen(ComponentVillageStartPiece par1ComponentVillageStartPiece, int par2,
+ EaglercraftRandom par3Random, StructureBoundingBox par4StructureBoundingBox, int par5) {
+ super(par1ComponentVillageStartPiece, par2);
+ this.coordBaseMode = par5;
+ this.boundingBox = par4StructureBoundingBox;
+ this.averageGroundLevel = Math.max(par4StructureBoundingBox.getXSize(), par4StructureBoundingBox.getZSize());
+ }
+
+ /**
+ * Initiates construction of the Structure Component picked, at the current
+ * Location of StructGen
+ */
+ public void buildComponent(StructureComponent par1StructureComponent, List par2List, EaglercraftRandom par3Random) {
+ boolean var4 = false;
+ int var5;
+ StructureComponent var6;
+
+ for (var5 = par3Random.nextInt(5); var5 < this.averageGroundLevel - 8; var5 += 2 + par3Random.nextInt(5)) {
+ var6 = this.getNextComponentNN((ComponentVillageStartPiece) par1StructureComponent, par2List, par3Random, 0,
+ var5);
+
+ if (var6 != null) {
+ var5 += Math.max(var6.boundingBox.getXSize(), var6.boundingBox.getZSize());
+ var4 = true;
+ }
+ }
+
+ for (var5 = par3Random.nextInt(5); var5 < this.averageGroundLevel - 8; var5 += 2 + par3Random.nextInt(5)) {
+ var6 = this.getNextComponentPP((ComponentVillageStartPiece) par1StructureComponent, par2List, par3Random, 0,
+ var5);
+
+ if (var6 != null) {
+ var5 += Math.max(var6.boundingBox.getXSize(), var6.boundingBox.getZSize());
+ var4 = true;
+ }
+ }
+
+ if (var4 && par3Random.nextInt(3) > 0) {
+ switch (this.coordBaseMode) {
+ case 0:
+ StructureVillagePieces.getNextStructureComponentVillagePath(
+ (ComponentVillageStartPiece) par1StructureComponent, par2List, par3Random,
+ this.boundingBox.minX - 1, this.boundingBox.minY, this.boundingBox.maxZ - 2, 1,
+ this.getComponentType());
+ break;
+
+ case 1:
+ StructureVillagePieces.getNextStructureComponentVillagePath(
+ (ComponentVillageStartPiece) par1StructureComponent, par2List, par3Random,
+ this.boundingBox.minX, this.boundingBox.minY, this.boundingBox.minZ - 1, 2,
+ this.getComponentType());
+ break;
+
+ case 2:
+ StructureVillagePieces.getNextStructureComponentVillagePath(
+ (ComponentVillageStartPiece) par1StructureComponent, par2List, par3Random,
+ this.boundingBox.minX - 1, this.boundingBox.minY, this.boundingBox.minZ, 1,
+ this.getComponentType());
+ break;
+
+ case 3:
+ StructureVillagePieces.getNextStructureComponentVillagePath(
+ (ComponentVillageStartPiece) par1StructureComponent, par2List, par3Random,
+ this.boundingBox.maxX - 2, this.boundingBox.minY, this.boundingBox.minZ - 1, 2,
+ this.getComponentType());
+ }
+ }
+
+ if (var4 && par3Random.nextInt(3) > 0) {
+ switch (this.coordBaseMode) {
+ case 0:
+ StructureVillagePieces.getNextStructureComponentVillagePath(
+ (ComponentVillageStartPiece) par1StructureComponent, par2List, par3Random,
+ this.boundingBox.maxX + 1, this.boundingBox.minY, this.boundingBox.maxZ - 2, 3,
+ this.getComponentType());
+ break;
+
+ case 1:
+ StructureVillagePieces.getNextStructureComponentVillagePath(
+ (ComponentVillageStartPiece) par1StructureComponent, par2List, par3Random,
+ this.boundingBox.minX, this.boundingBox.minY, this.boundingBox.maxZ + 1, 0,
+ this.getComponentType());
+ break;
+
+ case 2:
+ StructureVillagePieces.getNextStructureComponentVillagePath(
+ (ComponentVillageStartPiece) par1StructureComponent, par2List, par3Random,
+ this.boundingBox.maxX + 1, this.boundingBox.minY, this.boundingBox.minZ, 3,
+ this.getComponentType());
+ break;
+
+ case 3:
+ StructureVillagePieces.getNextStructureComponentVillagePath(
+ (ComponentVillageStartPiece) par1StructureComponent, par2List, par3Random,
+ this.boundingBox.maxX - 2, this.boundingBox.minY, this.boundingBox.maxZ + 1, 0,
+ this.getComponentType());
+ }
+ }
+ }
+
+ public static StructureBoundingBox func_74933_a(ComponentVillageStartPiece par0ComponentVillageStartPiece,
+ List par1List, EaglercraftRandom par2Random, int par3, int par4, int par5, int par6) {
+ for (int var7 = 7 * MathHelper.getRandomIntegerInRange(par2Random, 3, 5); var7 >= 7; var7 -= 7) {
+ StructureBoundingBox var8 = StructureBoundingBox.getComponentToAddBoundingBox(par3, par4, par5, 0, 0, 0, 3,
+ 3, var7, par6);
+
+ if (StructureComponent.findIntersecting(par1List, var8) == null) {
+ return var8;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ int var4 = this.getBiomeSpecificBlock(Block.gravel.blockID, 0);
+
+ for (int var5 = this.boundingBox.minX; var5 <= this.boundingBox.maxX; ++var5) {
+ for (int var6 = this.boundingBox.minZ; var6 <= this.boundingBox.maxZ; ++var6) {
+ if (par3StructureBoundingBox.isVecInside(var5, 64, var6)) {
+ int var7 = par1World.getTopSolidOrLiquidBlock(var5, var6) - 1;
+ par1World.setBlock(var5, var7, var6, var4, 0, 2);
+ }
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentVillageRoadPiece.java b/sp-server/src/main/java/net/minecraft/src/ComponentVillageRoadPiece.java
new file mode 100644
index 0000000..636250e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentVillageRoadPiece.java
@@ -0,0 +1,7 @@
+package net.minecraft.src;
+
+public abstract class ComponentVillageRoadPiece extends ComponentVillage {
+ protected ComponentVillageRoadPiece(ComponentVillageStartPiece par1ComponentVillageStartPiece, int par2) {
+ super(par1ComponentVillageStartPiece, par2);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentVillageStartPiece.java b/sp-server/src/main/java/net/minecraft/src/ComponentVillageStartPiece.java
new file mode 100644
index 0000000..e30e8b8
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentVillageStartPiece.java
@@ -0,0 +1,39 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentVillageStartPiece extends ComponentVillageWell {
+ public final WorldChunkManager worldChunkMngr;
+
+ /** Boolean that determines if the village is in a desert or not. */
+ public final boolean inDesert;
+
+ /** World terrain type, 0 for normal, 1 for flap map */
+ public final int terrainType;
+ public StructureVillagePieceWeight structVillagePieceWeight;
+
+ /**
+ * Contains List of all spawnable Structure Piece Weights. If no more Pieces of
+ * a type can be spawned, they are removed from this list
+ */
+ public ArrayList structureVillageWeightedPieceList;
+ public ArrayList field_74932_i = new ArrayList();
+ public ArrayList field_74930_j = new ArrayList();
+
+ public ComponentVillageStartPiece(WorldChunkManager par1WorldChunkManager, int par2, EaglercraftRandom par3Random, int par4,
+ int par5, ArrayList par6ArrayList, int par7) {
+ super((ComponentVillageStartPiece) null, 0, par3Random, par4, par5);
+ this.worldChunkMngr = par1WorldChunkManager;
+ this.structureVillageWeightedPieceList = par6ArrayList;
+ this.terrainType = par7;
+ BiomeGenBase var8 = par1WorldChunkManager.getBiomeGenAt(par4, par5);
+ this.inDesert = var8 == BiomeGenBase.desert || var8 == BiomeGenBase.desertHills;
+ this.startPiece = this;
+ }
+
+ public WorldChunkManager getWorldChunkManager() {
+ return this.worldChunkMngr;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentVillageTorch.java b/sp-server/src/main/java/net/minecraft/src/ComponentVillageTorch.java
new file mode 100644
index 0000000..a860507
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentVillageTorch.java
@@ -0,0 +1,51 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentVillageTorch extends ComponentVillage {
+ private int averageGroundLevel = -1;
+
+ public ComponentVillageTorch(ComponentVillageStartPiece par1ComponentVillageStartPiece, int par2, EaglercraftRandom par3Random,
+ StructureBoundingBox par4StructureBoundingBox, int par5) {
+ super(par1ComponentVillageStartPiece, par2);
+ this.coordBaseMode = par5;
+ this.boundingBox = par4StructureBoundingBox;
+ }
+
+ public static StructureBoundingBox func_74904_a(ComponentVillageStartPiece par0ComponentVillageStartPiece,
+ List par1List, EaglercraftRandom par2Random, int par3, int par4, int par5, int par6) {
+ StructureBoundingBox var7 = StructureBoundingBox.getComponentToAddBoundingBox(par3, par4, par5, 0, 0, 0, 3, 4,
+ 2, par6);
+ return StructureComponent.findIntersecting(par1List, var7) != null ? null : var7;
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ if (this.averageGroundLevel < 0) {
+ this.averageGroundLevel = this.getAverageGroundLevel(par1World, par3StructureBoundingBox);
+
+ if (this.averageGroundLevel < 0) {
+ return true;
+ }
+
+ this.boundingBox.offset(0, this.averageGroundLevel - this.boundingBox.maxY + 4 - 1, 0);
+ }
+
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 0, 0, 2, 3, 1, 0, 0, false);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, 1, 0, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, 1, 1, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, 1, 2, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.cloth.blockID, 15, 1, 3, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.torchWood.blockID, 0, 0, 3, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.torchWood.blockID, 0, 1, 3, 1, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.torchWood.blockID, 0, 2, 3, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.torchWood.blockID, 0, 1, 3, -1, par3StructureBoundingBox);
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentVillageWell.java b/sp-server/src/main/java/net/minecraft/src/ComponentVillageWell.java
new file mode 100644
index 0000000..fd49b0e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentVillageWell.java
@@ -0,0 +1,91 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentVillageWell extends ComponentVillage {
+ private final boolean field_74924_a = true;
+ private int averageGroundLevel = -1;
+
+ public ComponentVillageWell(ComponentVillageStartPiece par1ComponentVillageStartPiece, int par2, EaglercraftRandom par3Random,
+ int par4, int par5) {
+ super(par1ComponentVillageStartPiece, par2);
+ this.coordBaseMode = par3Random.nextInt(4);
+
+ switch (this.coordBaseMode) {
+ case 0:
+ case 2:
+ this.boundingBox = new StructureBoundingBox(par4, 64, par5, par4 + 6 - 1, 78, par5 + 6 - 1);
+ break;
+
+ default:
+ this.boundingBox = new StructureBoundingBox(par4, 64, par5, par4 + 6 - 1, 78, par5 + 6 - 1);
+ }
+ }
+
+ /**
+ * Initiates construction of the Structure Component picked, at the current
+ * Location of StructGen
+ */
+ public void buildComponent(StructureComponent par1StructureComponent, List par2List, EaglercraftRandom par3Random) {
+ StructureVillagePieces.getNextStructureComponentVillagePath((ComponentVillageStartPiece) par1StructureComponent,
+ par2List, par3Random, this.boundingBox.minX - 1, this.boundingBox.maxY - 4, this.boundingBox.minZ + 1,
+ 1, this.getComponentType());
+ StructureVillagePieces.getNextStructureComponentVillagePath((ComponentVillageStartPiece) par1StructureComponent,
+ par2List, par3Random, this.boundingBox.maxX + 1, this.boundingBox.maxY - 4, this.boundingBox.minZ + 1,
+ 3, this.getComponentType());
+ StructureVillagePieces.getNextStructureComponentVillagePath((ComponentVillageStartPiece) par1StructureComponent,
+ par2List, par3Random, this.boundingBox.minX + 1, this.boundingBox.maxY - 4, this.boundingBox.minZ - 1,
+ 2, this.getComponentType());
+ StructureVillagePieces.getNextStructureComponentVillagePath((ComponentVillageStartPiece) par1StructureComponent,
+ par2List, par3Random, this.boundingBox.minX + 1, this.boundingBox.maxY - 4, this.boundingBox.maxZ + 1,
+ 0, this.getComponentType());
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ if (this.averageGroundLevel < 0) {
+ this.averageGroundLevel = this.getAverageGroundLevel(par1World, par3StructureBoundingBox);
+
+ if (this.averageGroundLevel < 0) {
+ return true;
+ }
+
+ this.boundingBox.offset(0, this.averageGroundLevel - this.boundingBox.maxY + 3, 0);
+ }
+
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 0, 1, 4, 12, 4, Block.cobblestone.blockID,
+ Block.waterMoving.blockID, false);
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, 2, 12, 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, 3, 12, 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, 2, 12, 3, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, 3, 12, 3, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, 1, 13, 1, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, 1, 14, 1, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, 4, 13, 1, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, 4, 14, 1, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, 1, 13, 4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, 1, 14, 4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, 4, 13, 4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, 4, 14, 4, par3StructureBoundingBox);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 15, 1, 4, 15, 4, Block.cobblestone.blockID,
+ Block.cobblestone.blockID, false);
+
+ for (int var4 = 0; var4 <= 5; ++var4) {
+ for (int var5 = 0; var5 <= 5; ++var5) {
+ if (var5 == 0 || var5 == 5 || var4 == 0 || var4 == 5) {
+ this.placeBlockAtCurrentPosition(par1World, Block.gravel.blockID, 0, var5, 11, var4,
+ par3StructureBoundingBox);
+ this.clearCurrentPositionBlocksUpwards(par1World, var5, 12, var4, par3StructureBoundingBox);
+ }
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ComponentVillageWoodHut.java b/sp-server/src/main/java/net/minecraft/src/ComponentVillageWoodHut.java
new file mode 100644
index 0000000..2a75fe8
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ComponentVillageWoodHut.java
@@ -0,0 +1,118 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ComponentVillageWoodHut extends ComponentVillage {
+ private int averageGroundLevel = -1;
+ private final boolean isTallHouse;
+ private final int tablePosition;
+
+ public ComponentVillageWoodHut(ComponentVillageStartPiece par1ComponentVillageStartPiece, int par2,
+ EaglercraftRandom par3Random, StructureBoundingBox par4StructureBoundingBox, int par5) {
+ super(par1ComponentVillageStartPiece, par2);
+ this.coordBaseMode = par5;
+ this.boundingBox = par4StructureBoundingBox;
+ this.isTallHouse = par3Random.nextBoolean();
+ this.tablePosition = par3Random.nextInt(3);
+ }
+
+ public static ComponentVillageWoodHut func_74908_a(ComponentVillageStartPiece par0ComponentVillageStartPiece,
+ List par1List, EaglercraftRandom par2Random, int par3, int par4, int par5, int par6, int par7) {
+ StructureBoundingBox var8 = StructureBoundingBox.getComponentToAddBoundingBox(par3, par4, par5, 0, 0, 0, 4, 6,
+ 5, par6);
+ return canVillageGoDeeper(var8) && StructureComponent.findIntersecting(par1List, var8) == null
+ ? new ComponentVillageWoodHut(par0ComponentVillageStartPiece, par7, par2Random, var8, par6)
+ : null;
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public boolean addComponentParts(World par1World, EaglercraftRandom par2Random,
+ StructureBoundingBox par3StructureBoundingBox) {
+ if (this.averageGroundLevel < 0) {
+ this.averageGroundLevel = this.getAverageGroundLevel(par1World, par3StructureBoundingBox);
+
+ if (this.averageGroundLevel < 0) {
+ return true;
+ }
+
+ this.boundingBox.offset(0, this.averageGroundLevel - this.boundingBox.maxY + 6 - 1, 0);
+ }
+
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 1, 1, 3, 5, 4, 0, 0, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 0, 0, 3, 0, 4, Block.cobblestone.blockID,
+ Block.cobblestone.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 0, 1, 2, 0, 3, Block.dirt.blockID,
+ Block.dirt.blockID, false);
+
+ if (this.isTallHouse) {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 4, 1, 2, 4, 3, Block.wood.blockID,
+ Block.wood.blockID, false);
+ } else {
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 5, 1, 2, 5, 3, Block.wood.blockID,
+ Block.wood.blockID, false);
+ }
+
+ this.placeBlockAtCurrentPosition(par1World, Block.wood.blockID, 0, 1, 4, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.wood.blockID, 0, 2, 4, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.wood.blockID, 0, 1, 4, 4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.wood.blockID, 0, 2, 4, 4, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.wood.blockID, 0, 0, 4, 1, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.wood.blockID, 0, 0, 4, 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.wood.blockID, 0, 0, 4, 3, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.wood.blockID, 0, 3, 4, 1, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.wood.blockID, 0, 3, 4, 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.wood.blockID, 0, 3, 4, 3, par3StructureBoundingBox);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 1, 0, 0, 3, 0, Block.wood.blockID,
+ Block.wood.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 3, 1, 0, 3, 3, 0, Block.wood.blockID,
+ Block.wood.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 1, 4, 0, 3, 4, Block.wood.blockID,
+ Block.wood.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 3, 1, 4, 3, 3, 4, Block.wood.blockID,
+ Block.wood.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 0, 1, 1, 0, 3, 3, Block.planks.blockID,
+ Block.planks.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 3, 1, 1, 3, 3, 3, Block.planks.blockID,
+ Block.planks.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 1, 0, 2, 3, 0, Block.planks.blockID,
+ Block.planks.blockID, false);
+ this.fillWithBlocks(par1World, par3StructureBoundingBox, 1, 1, 4, 2, 3, 4, Block.planks.blockID,
+ Block.planks.blockID, false);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 0, 2, 2, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.thinGlass.blockID, 0, 3, 2, 2, par3StructureBoundingBox);
+
+ if (this.tablePosition > 0) {
+ this.placeBlockAtCurrentPosition(par1World, Block.fence.blockID, 0, this.tablePosition, 1, 3,
+ par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, Block.pressurePlatePlanks.blockID, 0, this.tablePosition, 2, 3,
+ par3StructureBoundingBox);
+ }
+
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, 1, 1, 0, par3StructureBoundingBox);
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, 1, 2, 0, par3StructureBoundingBox);
+ this.placeDoorAtCurrentPosition(par1World, par3StructureBoundingBox, par2Random, 1, 1, 0,
+ this.getMetadataWithOffset(Block.doorWood.blockID, 1));
+
+ if (this.getBlockIdAtCurrentPosition(par1World, 1, 0, -1, par3StructureBoundingBox) == 0
+ && this.getBlockIdAtCurrentPosition(par1World, 1, -1, -1, par3StructureBoundingBox) != 0) {
+ this.placeBlockAtCurrentPosition(par1World, Block.stairsCobblestone.blockID,
+ this.getMetadataWithOffset(Block.stairsCobblestone.blockID, 3), 1, 0, -1, par3StructureBoundingBox);
+ }
+
+ for (int var4 = 0; var4 < 5; ++var4) {
+ for (int var5 = 0; var5 < 4; ++var5) {
+ this.clearCurrentPositionBlocksUpwards(par1World, var5, 6, var4, par3StructureBoundingBox);
+ this.fillCurrentPositionBlocksDownwards(par1World, Block.cobblestone.blockID, 0, var5, -1, var4,
+ par3StructureBoundingBox);
+ }
+ }
+
+ this.spawnVillagers(par1World, par3StructureBoundingBox, 1, 1, 2, 1);
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/CompressedStreamTools.java b/sp-server/src/main/java/net/minecraft/src/CompressedStreamTools.java
new file mode 100644
index 0000000..b7dbe58
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/CompressedStreamTools.java
@@ -0,0 +1,105 @@
+package net.minecraft.src;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInput;
+import java.io.DataInputStream;
+import java.io.DataOutput;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import com.jcraft.jzlib.Deflater;
+import com.jcraft.jzlib.GZIPInputStream;
+import com.jcraft.jzlib.GZIPOutputStream;
+
+public class CompressedStreamTools {
+ /**
+ * Load the gzipped compound from the inputstream.
+ */
+ public static NBTTagCompound readCompressed(InputStream par0InputStream) throws IOException {
+ DataInputStream var1 = new DataInputStream(new BufferedInputStream(new GZIPInputStream(par0InputStream)));
+ NBTTagCompound var2;
+
+ try {
+ var2 = read(var1);
+ } finally {
+ var1.close();
+ }
+
+ return var2;
+ }
+
+ /**
+ * Write the compound, gzipped, to the outputstream.
+ */
+ public static void writeCompressed(NBTTagCompound par0NBTTagCompound, OutputStream par1OutputStream)
+ throws IOException {
+ DataOutputStream var2 = new DataOutputStream(new GZIPOutputStream(par1OutputStream));
+
+ try {
+ write(par0NBTTagCompound, var2);
+ } finally {
+ var2.close();
+ }
+ }
+
+ public static NBTTagCompound decompress(byte[] par0ArrayOfByte) throws IOException {
+ DataInputStream var1 = new DataInputStream(
+ new BufferedInputStream(new GZIPInputStream(new ByteArrayInputStream(par0ArrayOfByte))));
+ NBTTagCompound var2;
+
+ try {
+ var2 = read(var1);
+ } finally {
+ var1.close();
+ }
+
+ return var2;
+ }
+
+ public static byte[] compress(NBTTagCompound par0NBTTagCompound) throws IOException {
+ ByteArrayOutputStream var1 = new ByteArrayOutputStream();
+ DataOutputStream var2 = new DataOutputStream(new GZIPOutputStream(var1));
+
+ try {
+ write(par0NBTTagCompound, var2);
+ } finally {
+ var2.close();
+ }
+
+ return var1.toByteArray();
+ }
+
+ public static byte[] compressChunk(NBTTagCompound par0NBTTagCompound) throws IOException {
+ ByteArrayOutputStream var1 = new ByteArrayOutputStream();
+ DataOutputStream var2 = new DataOutputStream(new GZIPOutputStream(var1, new Deflater(2, 15+16), 2048, true));
+
+ try {
+ write(par0NBTTagCompound, var2);
+ } finally {
+ var2.close();
+ }
+
+ return var1.toByteArray();
+ }
+
+ /**
+ * Reads from a CompressedStream.
+ */
+ public static NBTTagCompound read(DataInput par0DataInput) throws IOException {
+ NBTBase var1 = NBTBase.readNamedTag(par0DataInput);
+
+ if (var1 instanceof NBTTagCompound) {
+ return (NBTTagCompound) var1;
+ } else {
+ throw new IOException("Root tag must be a named compound tag");
+ }
+ }
+
+ public static void write(NBTTagCompound par0NBTTagCompound, DataOutput par1DataOutput) throws IOException {
+ NBTBase.writeNamedTag(par0NBTTagCompound, par1DataOutput);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Container.java b/sp-server/src/main/java/net/minecraft/src/Container.java
new file mode 100644
index 0000000..ffb2048
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Container.java
@@ -0,0 +1,600 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+public abstract class Container {
+ /** the list of all items(stacks) for the corresponding slot */
+ public List inventoryItemStacks = new ArrayList();
+
+ /** the list of all slots in the inventory */
+ public List inventorySlots = new ArrayList();
+ public int windowId = 0;
+ private short transactionID = 0;
+ private int field_94535_f = -1;
+ private int field_94536_g = 0;
+ private final Set field_94537_h = new HashSet();
+
+ /**
+ * list of all people that need to be notified when this craftinventory changes
+ */
+ protected List crafters = new ArrayList();
+ private Set playerList = new HashSet();
+
+ /**
+ * Adds an item slot to this container
+ */
+ protected Slot addSlotToContainer(Slot par1Slot) {
+ par1Slot.slotNumber = this.inventorySlots.size();
+ this.inventorySlots.add(par1Slot);
+ this.inventoryItemStacks.add((Object) null);
+ return par1Slot;
+ }
+
+ public void onCraftGuiOpened(ICrafting par1ICrafting) {
+ if (this.crafters.contains(par1ICrafting)) {
+ throw new IllegalArgumentException("Listener already listening");
+ } else {
+ this.crafters.add(par1ICrafting);
+ par1ICrafting.updateCraftingInventory(this, this.getInventory());
+ this.detectAndSendChanges();
+ }
+ }
+
+ /**
+ * returns a list if itemStacks, for each slot.
+ */
+ public List getInventory() {
+ ArrayList var1 = new ArrayList();
+
+ for (int var2 = 0; var2 < this.inventorySlots.size(); ++var2) {
+ var1.add(((Slot) this.inventorySlots.get(var2)).getStack());
+ }
+
+ return var1;
+ }
+
+ /**
+ * Looks for changes made in the container, sends them to every listener.
+ */
+ public void detectAndSendChanges() {
+ for (int var1 = 0; var1 < this.inventorySlots.size(); ++var1) {
+ ItemStack var2 = ((Slot) this.inventorySlots.get(var1)).getStack();
+ ItemStack var3 = (ItemStack) this.inventoryItemStacks.get(var1);
+
+ if (!ItemStack.areItemStacksEqual(var3, var2)) {
+ var3 = var2 == null ? null : var2.copy();
+ this.inventoryItemStacks.set(var1, var3);
+
+ for (int var4 = 0; var4 < this.crafters.size(); ++var4) {
+ ((ICrafting) this.crafters.get(var4)).sendSlotContents(this, var1, var3);
+ }
+ }
+ }
+ }
+
+ /**
+ * enchants the item on the table using the specified slot; also deducts XP from
+ * player
+ */
+ public boolean enchantItem(EntityPlayer par1EntityPlayer, int par2) {
+ return false;
+ }
+
+ public Slot getSlotFromInventory(IInventory par1IInventory, int par2) {
+ for (int var3 = 0; var3 < this.inventorySlots.size(); ++var3) {
+ Slot var4 = (Slot) this.inventorySlots.get(var3);
+
+ if (var4.isHere(par1IInventory, par2)) {
+ return var4;
+ }
+ }
+
+ return null;
+ }
+
+ public Slot getSlot(int par1) {
+ return (Slot) this.inventorySlots.get(par1);
+ }
+
+ /**
+ * Take a stack from the specified inventory slot.
+ */
+ public ItemStack transferStackInSlot(EntityPlayer par1EntityPlayer, int par2) {
+ Slot var3 = (Slot) this.inventorySlots.get(par2);
+ return var3 != null ? var3.getStack() : null;
+ }
+
+ public ItemStack slotClick(int par1, int par2, int par3, EntityPlayer par4EntityPlayer) {
+ ItemStack var5 = null;
+ InventoryPlayer var6 = par4EntityPlayer.inventory;
+ int var9;
+ ItemStack var17;
+
+ if (par3 == 5) {
+ int var7 = this.field_94536_g;
+ this.field_94536_g = func_94532_c(par2);
+
+ if ((var7 != 1 || this.field_94536_g != 2) && var7 != this.field_94536_g) {
+ this.func_94533_d();
+ } else if (var6.getItemStack() == null) {
+ this.func_94533_d();
+ } else if (this.field_94536_g == 0) {
+ this.field_94535_f = func_94529_b(par2);
+
+ if (func_94528_d(this.field_94535_f)) {
+ this.field_94536_g = 1;
+ this.field_94537_h.clear();
+ } else {
+ this.func_94533_d();
+ }
+ } else if (this.field_94536_g == 1) {
+ Slot var8 = (Slot) this.inventorySlots.get(par1);
+
+ if (var8 != null && func_94527_a(var8, var6.getItemStack(), true)
+ && var8.isItemValid(var6.getItemStack())
+ && var6.getItemStack().stackSize > this.field_94537_h.size() && this.func_94531_b(var8)) {
+ this.field_94537_h.add(var8);
+ }
+ } else if (this.field_94536_g == 2) {
+ if (!this.field_94537_h.isEmpty()) {
+ var17 = var6.getItemStack().copy();
+ var9 = var6.getItemStack().stackSize;
+ Iterator var10 = this.field_94537_h.iterator();
+
+ while (var10.hasNext()) {
+ Slot var11 = (Slot) var10.next();
+
+ if (var11 != null && func_94527_a(var11, var6.getItemStack(), true)
+ && var11.isItemValid(var6.getItemStack())
+ && var6.getItemStack().stackSize >= this.field_94537_h.size()
+ && this.func_94531_b(var11)) {
+ ItemStack var12 = var17.copy();
+ int var13 = var11.getHasStack() ? var11.getStack().stackSize : 0;
+ func_94525_a(this.field_94537_h, this.field_94535_f, var12, var13);
+
+ if (var12.stackSize > var12.getMaxStackSize()) {
+ var12.stackSize = var12.getMaxStackSize();
+ }
+
+ if (var12.stackSize > var11.getSlotStackLimit()) {
+ var12.stackSize = var11.getSlotStackLimit();
+ }
+
+ var9 -= var12.stackSize - var13;
+ var11.putStack(var12);
+ }
+ }
+
+ var17.stackSize = var9;
+
+ if (var17.stackSize <= 0) {
+ var17 = null;
+ }
+
+ var6.setItemStack(var17);
+ }
+
+ this.func_94533_d();
+ } else {
+ this.func_94533_d();
+ }
+ } else if (this.field_94536_g != 0) {
+ this.func_94533_d();
+ } else {
+ Slot var16;
+ int var19;
+ ItemStack var22;
+
+ if ((par3 == 0 || par3 == 1) && (par2 == 0 || par2 == 1)) {
+ if (par1 == -999) {
+ if (var6.getItemStack() != null && par1 == -999) {
+ if (par2 == 0) {
+ par4EntityPlayer.dropPlayerItem(var6.getItemStack());
+ var6.setItemStack((ItemStack) null);
+ }
+
+ if (par2 == 1) {
+ par4EntityPlayer.dropPlayerItem(var6.getItemStack().splitStack(1));
+
+ if (var6.getItemStack().stackSize == 0) {
+ var6.setItemStack((ItemStack) null);
+ }
+ }
+ }
+ } else if (par3 == 1) {
+ if (par1 < 0) {
+ return null;
+ }
+
+ var16 = (Slot) this.inventorySlots.get(par1);
+
+ if (var16 != null && var16.canTakeStack(par4EntityPlayer)) {
+ var17 = this.transferStackInSlot(par4EntityPlayer, par1);
+
+ if (var17 != null) {
+ var9 = var17.itemID;
+ var5 = var17.copy();
+
+ if (var16 != null && var16.getStack() != null && var16.getStack().itemID == var9) {
+ this.retrySlotClick(par1, par2, true, par4EntityPlayer);
+ }
+ }
+ }
+ } else {
+ if (par1 < 0) {
+ return null;
+ }
+
+ var16 = (Slot) this.inventorySlots.get(par1);
+
+ if (var16 != null) {
+ var17 = var16.getStack();
+ ItemStack var20 = var6.getItemStack();
+
+ if (var17 != null) {
+ var5 = var17.copy();
+ }
+
+ if (var17 == null) {
+ if (var20 != null && var16.isItemValid(var20)) {
+ var19 = par2 == 0 ? var20.stackSize : 1;
+
+ if (var19 > var16.getSlotStackLimit()) {
+ var19 = var16.getSlotStackLimit();
+ }
+
+ var16.putStack(var20.splitStack(var19));
+
+ if (var20.stackSize == 0) {
+ var6.setItemStack((ItemStack) null);
+ }
+ }
+ } else if (var16.canTakeStack(par4EntityPlayer)) {
+ if (var20 == null) {
+ var19 = par2 == 0 ? var17.stackSize : (var17.stackSize + 1) / 2;
+ var22 = var16.decrStackSize(var19);
+ var6.setItemStack(var22);
+
+ if (var17.stackSize == 0) {
+ var16.putStack((ItemStack) null);
+ }
+
+ var16.onPickupFromSlot(par4EntityPlayer, var6.getItemStack());
+ } else if (var16.isItemValid(var20)) {
+ if (var17.itemID == var20.itemID && var17.getItemDamage() == var20.getItemDamage()
+ && ItemStack.areItemStackTagsEqual(var17, var20)) {
+ var19 = par2 == 0 ? var20.stackSize : 1;
+
+ if (var19 > var16.getSlotStackLimit() - var17.stackSize) {
+ var19 = var16.getSlotStackLimit() - var17.stackSize;
+ }
+
+ if (var19 > var20.getMaxStackSize() - var17.stackSize) {
+ var19 = var20.getMaxStackSize() - var17.stackSize;
+ }
+
+ var20.splitStack(var19);
+
+ if (var20.stackSize == 0) {
+ var6.setItemStack((ItemStack) null);
+ }
+
+ var17.stackSize += var19;
+ } else if (var20.stackSize <= var16.getSlotStackLimit()) {
+ var16.putStack(var20);
+ var6.setItemStack(var17);
+ }
+ } else if (var17.itemID == var20.itemID && var20.getMaxStackSize() > 1
+ && (!var17.getHasSubtypes() || var17.getItemDamage() == var20.getItemDamage())
+ && ItemStack.areItemStackTagsEqual(var17, var20)) {
+ var19 = var17.stackSize;
+
+ if (var19 > 0 && var19 + var20.stackSize <= var20.getMaxStackSize()) {
+ var20.stackSize += var19;
+ var17 = var16.decrStackSize(var19);
+
+ if (var17.stackSize == 0) {
+ var16.putStack((ItemStack) null);
+ }
+
+ var16.onPickupFromSlot(par4EntityPlayer, var6.getItemStack());
+ }
+ }
+ }
+
+ var16.onSlotChanged();
+ }
+ }
+ } else if (par3 == 2 && par2 >= 0 && par2 < 9) {
+ var16 = (Slot) this.inventorySlots.get(par1);
+
+ if (var16.canTakeStack(par4EntityPlayer)) {
+ var17 = var6.getStackInSlot(par2);
+ boolean var18 = var17 == null || var16.inventory == var6 && var16.isItemValid(var17);
+ var19 = -1;
+
+ if (!var18) {
+ var19 = var6.getFirstEmptyStack();
+ var18 |= var19 > -1;
+ }
+
+ if (var16.getHasStack() && var18) {
+ var22 = var16.getStack();
+ var6.setInventorySlotContents(par2, var22.copy());
+
+ if ((var16.inventory != var6 || !var16.isItemValid(var17)) && var17 != null) {
+ if (var19 > -1) {
+ var6.addItemStackToInventory(var17);
+ var16.decrStackSize(var22.stackSize);
+ var16.putStack((ItemStack) null);
+ var16.onPickupFromSlot(par4EntityPlayer, var22);
+ }
+ } else {
+ var16.decrStackSize(var22.stackSize);
+ var16.putStack(var17);
+ var16.onPickupFromSlot(par4EntityPlayer, var22);
+ }
+ } else if (!var16.getHasStack() && var17 != null && var16.isItemValid(var17)) {
+ var6.setInventorySlotContents(par2, (ItemStack) null);
+ var16.putStack(var17);
+ }
+ }
+ } else if (par3 == 3 && par4EntityPlayer.capabilities.isCreativeMode && var6.getItemStack() == null
+ && par1 >= 0) {
+ var16 = (Slot) this.inventorySlots.get(par1);
+
+ if (var16 != null && var16.getHasStack()) {
+ var17 = var16.getStack().copy();
+ var17.stackSize = var17.getMaxStackSize();
+ var6.setItemStack(var17);
+ }
+ } else if (par3 == 4 && var6.getItemStack() == null && par1 >= 0) {
+ var16 = (Slot) this.inventorySlots.get(par1);
+
+ if (var16 != null && var16.getHasStack() && var16.canTakeStack(par4EntityPlayer)) {
+ var17 = var16.decrStackSize(par2 == 0 ? 1 : var16.getStack().stackSize);
+ var16.onPickupFromSlot(par4EntityPlayer, var17);
+ par4EntityPlayer.dropPlayerItem(var17);
+ }
+ } else if (par3 == 6 && par1 >= 0) {
+ var16 = (Slot) this.inventorySlots.get(par1);
+ var17 = var6.getItemStack();
+
+ if (var17 != null && (var16 == null || !var16.getHasStack() || !var16.canTakeStack(par4EntityPlayer))) {
+ var9 = par2 == 0 ? 0 : this.inventorySlots.size() - 1;
+ var19 = par2 == 0 ? 1 : -1;
+
+ for (int var21 = 0; var21 < 2; ++var21) {
+ for (int var23 = var9; var23 >= 0 && var23 < this.inventorySlots.size()
+ && var17.stackSize < var17.getMaxStackSize(); var23 += var19) {
+ Slot var24 = (Slot) this.inventorySlots.get(var23);
+
+ if (var24.getHasStack() && func_94527_a(var24, var17, true)
+ && var24.canTakeStack(par4EntityPlayer) && this.func_94530_a(var17, var24)
+ && (var21 != 0
+ || var24.getStack().stackSize != var24.getStack().getMaxStackSize())) {
+ int var14 = Math.min(var17.getMaxStackSize() - var17.stackSize,
+ var24.getStack().stackSize);
+ ItemStack var15 = var24.decrStackSize(var14);
+ var17.stackSize += var14;
+
+ if (var15.stackSize <= 0) {
+ var24.putStack((ItemStack) null);
+ }
+
+ var24.onPickupFromSlot(par4EntityPlayer, var15);
+ }
+ }
+ }
+ }
+
+ this.detectAndSendChanges();
+ }
+ }
+
+ return var5;
+ }
+
+ public boolean func_94530_a(ItemStack par1ItemStack, Slot par2Slot) {
+ return true;
+ }
+
+ protected void retrySlotClick(int par1, int par2, boolean par3, EntityPlayer par4EntityPlayer) {
+ this.slotClick(par1, par2, 1, par4EntityPlayer);
+ }
+
+ /**
+ * Callback for when the crafting gui is closed.
+ */
+ public void onCraftGuiClosed(EntityPlayer par1EntityPlayer) {
+ InventoryPlayer var2 = par1EntityPlayer.inventory;
+
+ if (var2.getItemStack() != null) {
+ par1EntityPlayer.dropPlayerItem(var2.getItemStack());
+ var2.setItemStack((ItemStack) null);
+ }
+ }
+
+ /**
+ * Callback for when the crafting matrix is changed.
+ */
+ public void onCraftMatrixChanged(IInventory par1IInventory) {
+ this.detectAndSendChanges();
+ }
+
+ /**
+ * args: slotID, itemStack to put in slot
+ */
+ public void putStackInSlot(int par1, ItemStack par2ItemStack) {
+ this.getSlot(par1).putStack(par2ItemStack);
+ }
+
+ /**
+ * gets whether or not the player can craft in this inventory or not
+ */
+ public boolean getCanCraft(EntityPlayer par1EntityPlayer) {
+ return !this.playerList.contains(par1EntityPlayer);
+ }
+
+ /**
+ * sets whether the player can craft in this inventory or not
+ */
+ public void setCanCraft(EntityPlayer par1EntityPlayer, boolean par2) {
+ if (par2) {
+ this.playerList.remove(par1EntityPlayer);
+ } else {
+ this.playerList.add(par1EntityPlayer);
+ }
+ }
+
+ public abstract boolean canInteractWith(EntityPlayer var1);
+
+ /**
+ * merges provided ItemStack with the first avaliable one in the
+ * container/player inventory
+ */
+ protected boolean mergeItemStack(ItemStack par1ItemStack, int par2, int par3, boolean par4) {
+ boolean var5 = false;
+ int var6 = par2;
+
+ if (par4) {
+ var6 = par3 - 1;
+ }
+
+ Slot var7;
+ ItemStack var8;
+
+ if (par1ItemStack.isStackable()) {
+ while (par1ItemStack.stackSize > 0 && (!par4 && var6 < par3 || par4 && var6 >= par2)) {
+ var7 = (Slot) this.inventorySlots.get(var6);
+ var8 = var7.getStack();
+
+ if (var8 != null && var8.itemID == par1ItemStack.itemID
+ && (!par1ItemStack.getHasSubtypes() || par1ItemStack.getItemDamage() == var8.getItemDamage())
+ && ItemStack.areItemStackTagsEqual(par1ItemStack, var8)) {
+ int var9 = var8.stackSize + par1ItemStack.stackSize;
+
+ if (var9 <= par1ItemStack.getMaxStackSize()) {
+ par1ItemStack.stackSize = 0;
+ var8.stackSize = var9;
+ var7.onSlotChanged();
+ var5 = true;
+ } else if (var8.stackSize < par1ItemStack.getMaxStackSize()) {
+ par1ItemStack.stackSize -= par1ItemStack.getMaxStackSize() - var8.stackSize;
+ var8.stackSize = par1ItemStack.getMaxStackSize();
+ var7.onSlotChanged();
+ var5 = true;
+ }
+ }
+
+ if (par4) {
+ --var6;
+ } else {
+ ++var6;
+ }
+ }
+ }
+
+ if (par1ItemStack.stackSize > 0) {
+ if (par4) {
+ var6 = par3 - 1;
+ } else {
+ var6 = par2;
+ }
+
+ while (!par4 && var6 < par3 || par4 && var6 >= par2) {
+ var7 = (Slot) this.inventorySlots.get(var6);
+ var8 = var7.getStack();
+
+ if (var8 == null) {
+ var7.putStack(par1ItemStack.copy());
+ var7.onSlotChanged();
+ par1ItemStack.stackSize = 0;
+ var5 = true;
+ break;
+ }
+
+ if (par4) {
+ --var6;
+ } else {
+ ++var6;
+ }
+ }
+ }
+
+ return var5;
+ }
+
+ public static int func_94529_b(int par0) {
+ return par0 >> 2 & 3;
+ }
+
+ public static int func_94532_c(int par0) {
+ return par0 & 3;
+ }
+
+ public static boolean func_94528_d(int par0) {
+ return par0 == 0 || par0 == 1;
+ }
+
+ protected void func_94533_d() {
+ this.field_94536_g = 0;
+ this.field_94537_h.clear();
+ }
+
+ public static boolean func_94527_a(Slot par0Slot, ItemStack par1ItemStack, boolean par2) {
+ boolean var3 = par0Slot == null || !par0Slot.getHasStack();
+
+ if (par0Slot != null && par0Slot.getHasStack() && par1ItemStack != null
+ && par1ItemStack.isItemEqual(par0Slot.getStack())
+ && ItemStack.areItemStackTagsEqual(par0Slot.getStack(), par1ItemStack)) {
+ int var10002 = par2 ? 0 : par1ItemStack.stackSize;
+ var3 |= par0Slot.getStack().stackSize + var10002 <= par1ItemStack.getMaxStackSize();
+ }
+
+ return var3;
+ }
+
+ public static void func_94525_a(Set par0Set, int par1, ItemStack par2ItemStack, int par3) {
+ switch (par1) {
+ case 0:
+ par2ItemStack.stackSize = MathHelper.floor_float((float) par2ItemStack.stackSize / (float) par0Set.size());
+ break;
+
+ case 1:
+ par2ItemStack.stackSize = 1;
+ }
+
+ par2ItemStack.stackSize += par3;
+ }
+
+ public boolean func_94531_b(Slot par1Slot) {
+ return true;
+ }
+
+ public static int calcRedstoneFromInventory(IInventory par0IInventory) {
+ if (par0IInventory == null) {
+ return 0;
+ } else {
+ int var1 = 0;
+ float var2 = 0.0F;
+
+ for (int var3 = 0; var3 < par0IInventory.getSizeInventory(); ++var3) {
+ ItemStack var4 = par0IInventory.getStackInSlot(var3);
+
+ if (var4 != null) {
+ var2 += (float) var4.stackSize
+ / (float) Math.min(par0IInventory.getInventoryStackLimit(), var4.getMaxStackSize());
+ ++var1;
+ }
+ }
+
+ var2 /= (float) par0IInventory.getSizeInventory();
+ return MathHelper.floor_float(var2 * 14.0F) + (var1 > 0 ? 1 : 0);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ContainerBeacon.java b/sp-server/src/main/java/net/minecraft/src/ContainerBeacon.java
new file mode 100644
index 0000000..c3f698e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ContainerBeacon.java
@@ -0,0 +1,110 @@
+package net.minecraft.src;
+
+public class ContainerBeacon extends Container {
+ private TileEntityBeacon theBeacon;
+
+ /**
+ * This beacon's slot where you put in Emerald, Diamond, Gold or Iron Ingot.
+ */
+ private final SlotBeacon beaconSlot;
+ private int field_82865_g;
+ private int field_82867_h;
+ private int field_82868_i;
+
+ public ContainerBeacon(InventoryPlayer par1InventoryPlayer, TileEntityBeacon par2TileEntityBeacon) {
+ this.theBeacon = par2TileEntityBeacon;
+ this.addSlotToContainer(this.beaconSlot = new SlotBeacon(this, par2TileEntityBeacon, 0, 136, 110));
+ byte var3 = 36;
+ short var4 = 137;
+ int var5;
+
+ for (var5 = 0; var5 < 3; ++var5) {
+ for (int var6 = 0; var6 < 9; ++var6) {
+ this.addSlotToContainer(
+ new Slot(par1InventoryPlayer, var6 + var5 * 9 + 9, var3 + var6 * 18, var4 + var5 * 18));
+ }
+ }
+
+ for (var5 = 0; var5 < 9; ++var5) {
+ this.addSlotToContainer(new Slot(par1InventoryPlayer, var5, var3 + var5 * 18, 58 + var4));
+ }
+
+ this.field_82865_g = par2TileEntityBeacon.getLevels();
+ this.field_82867_h = par2TileEntityBeacon.getPrimaryEffect();
+ this.field_82868_i = par2TileEntityBeacon.getSecondaryEffect();
+ }
+
+ public void onCraftGuiOpened(ICrafting par1ICrafting) {
+ super.onCraftGuiOpened(par1ICrafting);
+ par1ICrafting.sendProgressBarUpdate(this, 0, this.field_82865_g);
+ par1ICrafting.sendProgressBarUpdate(this, 1, this.field_82867_h);
+ par1ICrafting.sendProgressBarUpdate(this, 2, this.field_82868_i);
+ }
+
+ /**
+ * Looks for changes made in the container, sends them to every listener.
+ */
+ public void detectAndSendChanges() {
+ super.detectAndSendChanges();
+ }
+
+ /**
+ * Returns the Tile Entity behind this beacon inventory / container
+ */
+ public TileEntityBeacon getBeacon() {
+ return this.theBeacon;
+ }
+
+ public boolean canInteractWith(EntityPlayer par1EntityPlayer) {
+ return this.theBeacon.isUseableByPlayer(par1EntityPlayer);
+ }
+
+ /**
+ * Take a stack from the specified inventory slot.
+ */
+ public ItemStack transferStackInSlot(EntityPlayer par1EntityPlayer, int par2) {
+ ItemStack var3 = null;
+ Slot var4 = (Slot) this.inventorySlots.get(par2);
+
+ if (var4 != null && var4.getHasStack()) {
+ ItemStack var5 = var4.getStack();
+ var3 = var5.copy();
+
+ if (par2 == 0) {
+ if (!this.mergeItemStack(var5, 1, 37, true)) {
+ return null;
+ }
+
+ var4.onSlotChange(var5, var3);
+ } else if (!this.beaconSlot.getHasStack() && this.beaconSlot.isItemValid(var5) && var5.stackSize == 1) {
+ if (!this.mergeItemStack(var5, 0, 1, false)) {
+ return null;
+ }
+ } else if (par2 >= 1 && par2 < 28) {
+ if (!this.mergeItemStack(var5, 28, 37, false)) {
+ return null;
+ }
+ } else if (par2 >= 28 && par2 < 37) {
+ if (!this.mergeItemStack(var5, 1, 28, false)) {
+ return null;
+ }
+ } else if (!this.mergeItemStack(var5, 1, 37, false)) {
+ return null;
+ }
+
+ if (var5.stackSize == 0) {
+ var4.putStack((ItemStack) null);
+ } else {
+ var4.onSlotChanged();
+ }
+
+ if (var5.stackSize == var3.stackSize) {
+ return null;
+ }
+
+ var4.onPickupFromSlot(par1EntityPlayer, var5);
+ }
+
+ return var3;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ContainerBrewingStand.java b/sp-server/src/main/java/net/minecraft/src/ContainerBrewingStand.java
new file mode 100644
index 0000000..6f9c16d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ContainerBrewingStand.java
@@ -0,0 +1,115 @@
+package net.minecraft.src;
+
+public class ContainerBrewingStand extends Container {
+ private TileEntityBrewingStand tileBrewingStand;
+
+ /** Instance of Slot. */
+ private final Slot theSlot;
+ private int brewTime = 0;
+
+ public ContainerBrewingStand(InventoryPlayer par1InventoryPlayer,
+ TileEntityBrewingStand par2TileEntityBrewingStand) {
+ this.tileBrewingStand = par2TileEntityBrewingStand;
+ this.addSlotToContainer(
+ new SlotBrewingStandPotion(par1InventoryPlayer.player, par2TileEntityBrewingStand, 0, 56, 46));
+ this.addSlotToContainer(
+ new SlotBrewingStandPotion(par1InventoryPlayer.player, par2TileEntityBrewingStand, 1, 79, 53));
+ this.addSlotToContainer(
+ new SlotBrewingStandPotion(par1InventoryPlayer.player, par2TileEntityBrewingStand, 2, 102, 46));
+ this.theSlot = this
+ .addSlotToContainer(new SlotBrewingStandIngredient(this, par2TileEntityBrewingStand, 3, 79, 17));
+ int var3;
+
+ for (var3 = 0; var3 < 3; ++var3) {
+ for (int var4 = 0; var4 < 9; ++var4) {
+ this.addSlotToContainer(
+ new Slot(par1InventoryPlayer, var4 + var3 * 9 + 9, 8 + var4 * 18, 84 + var3 * 18));
+ }
+ }
+
+ for (var3 = 0; var3 < 9; ++var3) {
+ this.addSlotToContainer(new Slot(par1InventoryPlayer, var3, 8 + var3 * 18, 142));
+ }
+ }
+
+ public void onCraftGuiOpened(ICrafting par1ICrafting) {
+ super.onCraftGuiOpened(par1ICrafting);
+ par1ICrafting.sendProgressBarUpdate(this, 0, this.tileBrewingStand.getBrewTime());
+ }
+
+ /**
+ * Looks for changes made in the container, sends them to every listener.
+ */
+ public void detectAndSendChanges() {
+ super.detectAndSendChanges();
+
+ for (int var1 = 0; var1 < this.crafters.size(); ++var1) {
+ ICrafting var2 = (ICrafting) this.crafters.get(var1);
+
+ if (this.brewTime != this.tileBrewingStand.getBrewTime()) {
+ var2.sendProgressBarUpdate(this, 0, this.tileBrewingStand.getBrewTime());
+ }
+ }
+
+ this.brewTime = this.tileBrewingStand.getBrewTime();
+ }
+
+ public boolean canInteractWith(EntityPlayer par1EntityPlayer) {
+ return this.tileBrewingStand.isUseableByPlayer(par1EntityPlayer);
+ }
+
+ /**
+ * Take a stack from the specified inventory slot.
+ */
+ public ItemStack transferStackInSlot(EntityPlayer par1EntityPlayer, int par2) {
+ ItemStack var3 = null;
+ Slot var4 = (Slot) this.inventorySlots.get(par2);
+
+ if (var4 != null && var4.getHasStack()) {
+ ItemStack var5 = var4.getStack();
+ var3 = var5.copy();
+
+ if ((par2 < 0 || par2 > 2) && par2 != 3) {
+ if (!this.theSlot.getHasStack() && this.theSlot.isItemValid(var5)) {
+ if (!this.mergeItemStack(var5, 3, 4, false)) {
+ return null;
+ }
+ } else if (SlotBrewingStandPotion.canHoldPotion(var3)) {
+ if (!this.mergeItemStack(var5, 0, 3, false)) {
+ return null;
+ }
+ } else if (par2 >= 4 && par2 < 31) {
+ if (!this.mergeItemStack(var5, 31, 40, false)) {
+ return null;
+ }
+ } else if (par2 >= 31 && par2 < 40) {
+ if (!this.mergeItemStack(var5, 4, 31, false)) {
+ return null;
+ }
+ } else if (!this.mergeItemStack(var5, 4, 40, false)) {
+ return null;
+ }
+ } else {
+ if (!this.mergeItemStack(var5, 4, 40, true)) {
+ return null;
+ }
+
+ var4.onSlotChange(var5, var3);
+ }
+
+ if (var5.stackSize == 0) {
+ var4.putStack((ItemStack) null);
+ } else {
+ var4.onSlotChanged();
+ }
+
+ if (var5.stackSize == var3.stackSize) {
+ return null;
+ }
+
+ var4.onPickupFromSlot(par1EntityPlayer, var5);
+ }
+
+ return var3;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ContainerChest.java b/sp-server/src/main/java/net/minecraft/src/ContainerChest.java
new file mode 100644
index 0000000..be9d112
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ContainerChest.java
@@ -0,0 +1,80 @@
+package net.minecraft.src;
+
+public class ContainerChest extends Container {
+ private IInventory lowerChestInventory;
+ private int numRows;
+
+ public ContainerChest(IInventory par1IInventory, IInventory par2IInventory) {
+ this.lowerChestInventory = par2IInventory;
+ this.numRows = par2IInventory.getSizeInventory() / 9;
+ par2IInventory.openChest();
+ int var3 = (this.numRows - 4) * 18;
+ int var4;
+ int var5;
+
+ for (var4 = 0; var4 < this.numRows; ++var4) {
+ for (var5 = 0; var5 < 9; ++var5) {
+ this.addSlotToContainer(new Slot(par2IInventory, var5 + var4 * 9, 8 + var5 * 18, 18 + var4 * 18));
+ }
+ }
+
+ for (var4 = 0; var4 < 3; ++var4) {
+ for (var5 = 0; var5 < 9; ++var5) {
+ this.addSlotToContainer(
+ new Slot(par1IInventory, var5 + var4 * 9 + 9, 8 + var5 * 18, 103 + var4 * 18 + var3));
+ }
+ }
+
+ for (var4 = 0; var4 < 9; ++var4) {
+ this.addSlotToContainer(new Slot(par1IInventory, var4, 8 + var4 * 18, 161 + var3));
+ }
+ }
+
+ public boolean canInteractWith(EntityPlayer par1EntityPlayer) {
+ return this.lowerChestInventory.isUseableByPlayer(par1EntityPlayer);
+ }
+
+ /**
+ * Take a stack from the specified inventory slot.
+ */
+ public ItemStack transferStackInSlot(EntityPlayer par1EntityPlayer, int par2) {
+ ItemStack var3 = null;
+ Slot var4 = (Slot) this.inventorySlots.get(par2);
+
+ if (var4 != null && var4.getHasStack()) {
+ ItemStack var5 = var4.getStack();
+ var3 = var5.copy();
+
+ if (par2 < this.numRows * 9) {
+ if (!this.mergeItemStack(var5, this.numRows * 9, this.inventorySlots.size(), true)) {
+ return null;
+ }
+ } else if (!this.mergeItemStack(var5, 0, this.numRows * 9, false)) {
+ return null;
+ }
+
+ if (var5.stackSize == 0) {
+ var4.putStack((ItemStack) null);
+ } else {
+ var4.onSlotChanged();
+ }
+ }
+
+ return var3;
+ }
+
+ /**
+ * Callback for when the crafting gui is closed.
+ */
+ public void onCraftGuiClosed(EntityPlayer par1EntityPlayer) {
+ super.onCraftGuiClosed(par1EntityPlayer);
+ this.lowerChestInventory.closeChest();
+ }
+
+ /**
+ * Return this chest container's lower chest inventory.
+ */
+ public IInventory getLowerChestInventory() {
+ return this.lowerChestInventory;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ContainerDispenser.java b/sp-server/src/main/java/net/minecraft/src/ContainerDispenser.java
new file mode 100644
index 0000000..c7405ed
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ContainerDispenser.java
@@ -0,0 +1,67 @@
+package net.minecraft.src;
+
+public class ContainerDispenser extends Container {
+ private TileEntityDispenser tileEntityDispenser;
+
+ public ContainerDispenser(IInventory par1IInventory, TileEntityDispenser par2TileEntityDispenser) {
+ this.tileEntityDispenser = par2TileEntityDispenser;
+ int var3;
+ int var4;
+
+ for (var3 = 0; var3 < 3; ++var3) {
+ for (var4 = 0; var4 < 3; ++var4) {
+ this.addSlotToContainer(
+ new Slot(par2TileEntityDispenser, var4 + var3 * 3, 62 + var4 * 18, 17 + var3 * 18));
+ }
+ }
+
+ for (var3 = 0; var3 < 3; ++var3) {
+ for (var4 = 0; var4 < 9; ++var4) {
+ this.addSlotToContainer(new Slot(par1IInventory, var4 + var3 * 9 + 9, 8 + var4 * 18, 84 + var3 * 18));
+ }
+ }
+
+ for (var3 = 0; var3 < 9; ++var3) {
+ this.addSlotToContainer(new Slot(par1IInventory, var3, 8 + var3 * 18, 142));
+ }
+ }
+
+ public boolean canInteractWith(EntityPlayer par1EntityPlayer) {
+ return this.tileEntityDispenser.isUseableByPlayer(par1EntityPlayer);
+ }
+
+ /**
+ * Take a stack from the specified inventory slot.
+ */
+ public ItemStack transferStackInSlot(EntityPlayer par1EntityPlayer, int par2) {
+ ItemStack var3 = null;
+ Slot var4 = (Slot) this.inventorySlots.get(par2);
+
+ if (var4 != null && var4.getHasStack()) {
+ ItemStack var5 = var4.getStack();
+ var3 = var5.copy();
+
+ if (par2 < 9) {
+ if (!this.mergeItemStack(var5, 9, 45, true)) {
+ return null;
+ }
+ } else if (!this.mergeItemStack(var5, 0, 9, false)) {
+ return null;
+ }
+
+ if (var5.stackSize == 0) {
+ var4.putStack((ItemStack) null);
+ } else {
+ var4.onSlotChanged();
+ }
+
+ if (var5.stackSize == var3.stackSize) {
+ return null;
+ }
+
+ var4.onPickupFromSlot(par1EntityPlayer, var5);
+ }
+
+ return var3;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ContainerEnchantment.java b/sp-server/src/main/java/net/minecraft/src/ContainerEnchantment.java
new file mode 100644
index 0000000..bdb03ba
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ContainerEnchantment.java
@@ -0,0 +1,247 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ContainerEnchantment extends Container {
+ /** SlotEnchantmentTable object with ItemStack to be enchanted */
+ public IInventory tableInventory = new SlotEnchantmentTable(this, "Enchant", true, 1);
+
+ /** current world (for bookshelf counting) */
+ private World worldPointer;
+ private int posX;
+ private int posY;
+ private int posZ;
+ private EaglercraftRandom rand = new EaglercraftRandom();
+
+ /** used as seed for EnchantmentNameParts (see GuiEnchantment) */
+ public long nameSeed;
+
+ /** 3-member array storing the enchantment levels of each slot */
+ public int[] enchantLevels = new int[3];
+
+ public ContainerEnchantment(InventoryPlayer par1InventoryPlayer, World par2World, int par3, int par4, int par5) {
+ this.worldPointer = par2World;
+ this.posX = par3;
+ this.posY = par4;
+ this.posZ = par5;
+ this.addSlotToContainer(new SlotEnchantment(this, this.tableInventory, 0, 25, 47));
+ int var6;
+
+ for (var6 = 0; var6 < 3; ++var6) {
+ for (int var7 = 0; var7 < 9; ++var7) {
+ this.addSlotToContainer(
+ new Slot(par1InventoryPlayer, var7 + var6 * 9 + 9, 8 + var7 * 18, 84 + var6 * 18));
+ }
+ }
+
+ for (var6 = 0; var6 < 9; ++var6) {
+ this.addSlotToContainer(new Slot(par1InventoryPlayer, var6, 8 + var6 * 18, 142));
+ }
+ }
+
+ public void onCraftGuiOpened(ICrafting par1ICrafting) {
+ super.onCraftGuiOpened(par1ICrafting);
+ par1ICrafting.sendProgressBarUpdate(this, 0, this.enchantLevels[0]);
+ par1ICrafting.sendProgressBarUpdate(this, 1, this.enchantLevels[1]);
+ par1ICrafting.sendProgressBarUpdate(this, 2, this.enchantLevels[2]);
+ }
+
+ /**
+ * Looks for changes made in the container, sends them to every listener.
+ */
+ public void detectAndSendChanges() {
+ super.detectAndSendChanges();
+
+ for (int var1 = 0; var1 < this.crafters.size(); ++var1) {
+ ICrafting var2 = (ICrafting) this.crafters.get(var1);
+ var2.sendProgressBarUpdate(this, 0, this.enchantLevels[0]);
+ var2.sendProgressBarUpdate(this, 1, this.enchantLevels[1]);
+ var2.sendProgressBarUpdate(this, 2, this.enchantLevels[2]);
+ }
+ }
+
+ /**
+ * Callback for when the crafting matrix is changed.
+ */
+ public void onCraftMatrixChanged(IInventory par1IInventory) {
+ if (par1IInventory == this.tableInventory) {
+ ItemStack var2 = par1IInventory.getStackInSlot(0);
+ int var3;
+
+ if (var2 != null && var2.isItemEnchantable()) {
+ this.nameSeed = this.rand.nextLong();
+
+ if (!this.worldPointer.isRemote) {
+ var3 = 0;
+ int var4;
+
+ for (var4 = -1; var4 <= 1; ++var4) {
+ for (int var5 = -1; var5 <= 1; ++var5) {
+ if ((var4 != 0 || var5 != 0)
+ && this.worldPointer.isAirBlock(this.posX + var5, this.posY, this.posZ + var4)
+ && this.worldPointer.isAirBlock(this.posX + var5, this.posY + 1,
+ this.posZ + var4)) {
+ if (this.worldPointer.getBlockId(this.posX + var5 * 2, this.posY,
+ this.posZ + var4 * 2) == Block.bookShelf.blockID) {
+ ++var3;
+ }
+
+ if (this.worldPointer.getBlockId(this.posX + var5 * 2, this.posY + 1,
+ this.posZ + var4 * 2) == Block.bookShelf.blockID) {
+ ++var3;
+ }
+
+ if (var5 != 0 && var4 != 0) {
+ if (this.worldPointer.getBlockId(this.posX + var5 * 2, this.posY,
+ this.posZ + var4) == Block.bookShelf.blockID) {
+ ++var3;
+ }
+
+ if (this.worldPointer.getBlockId(this.posX + var5 * 2, this.posY + 1,
+ this.posZ + var4) == Block.bookShelf.blockID) {
+ ++var3;
+ }
+
+ if (this.worldPointer.getBlockId(this.posX + var5, this.posY,
+ this.posZ + var4 * 2) == Block.bookShelf.blockID) {
+ ++var3;
+ }
+
+ if (this.worldPointer.getBlockId(this.posX + var5, this.posY + 1,
+ this.posZ + var4 * 2) == Block.bookShelf.blockID) {
+ ++var3;
+ }
+ }
+ }
+ }
+ }
+
+ for (var4 = 0; var4 < 3; ++var4) {
+ this.enchantLevels[var4] = EnchantmentHelper.calcItemStackEnchantability(this.rand, var4, var3,
+ var2);
+ }
+
+ this.detectAndSendChanges();
+ }
+ } else {
+ for (var3 = 0; var3 < 3; ++var3) {
+ this.enchantLevels[var3] = 0;
+ }
+ }
+ }
+ }
+
+ /**
+ * enchants the item on the table using the specified slot; also deducts XP from
+ * player
+ */
+ public boolean enchantItem(EntityPlayer par1EntityPlayer, int par2) {
+ ItemStack var3 = this.tableInventory.getStackInSlot(0);
+
+ if (this.enchantLevels[par2] > 0 && var3 != null
+ && (par1EntityPlayer.experienceLevel >= this.enchantLevels[par2]
+ || par1EntityPlayer.capabilities.isCreativeMode)) {
+ if (!this.worldPointer.isRemote) {
+ List var4 = EnchantmentHelper.buildEnchantmentList(this.rand, var3, this.enchantLevels[par2]);
+ boolean var5 = var3.itemID == Item.book.itemID;
+
+ if (var4 != null) {
+ par1EntityPlayer.addExperienceLevel(-this.enchantLevels[par2]);
+
+ if (var5) {
+ var3.itemID = Item.enchantedBook.itemID;
+ }
+
+ int var6 = var5 ? this.rand.nextInt(var4.size()) : -1;
+
+ for (int var7 = 0; var7 < var4.size(); ++var7) {
+ EnchantmentData var8 = (EnchantmentData) var4.get(var7);
+
+ if (!var5 || var7 == var6) {
+ if (var5) {
+ Item.enchantedBook.func_92115_a(var3, var8);
+ } else {
+ var3.addEnchantment(var8.enchantmentobj, var8.enchantmentLevel);
+ }
+ }
+ }
+
+ this.onCraftMatrixChanged(this.tableInventory);
+ }
+ }
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Callback for when the crafting gui is closed.
+ */
+ public void onCraftGuiClosed(EntityPlayer par1EntityPlayer) {
+ super.onCraftGuiClosed(par1EntityPlayer);
+
+ if (!this.worldPointer.isRemote) {
+ ItemStack var2 = this.tableInventory.getStackInSlotOnClosing(0);
+
+ if (var2 != null) {
+ par1EntityPlayer.dropPlayerItem(var2);
+ }
+ }
+ }
+
+ public boolean canInteractWith(EntityPlayer par1EntityPlayer) {
+ return this.worldPointer.getBlockId(this.posX, this.posY, this.posZ) != Block.enchantmentTable.blockID ? false
+ : par1EntityPlayer.getDistanceSq((double) this.posX + 0.5D, (double) this.posY + 0.5D,
+ (double) this.posZ + 0.5D) <= 64.0D;
+ }
+
+ /**
+ * Take a stack from the specified inventory slot.
+ */
+ public ItemStack transferStackInSlot(EntityPlayer par1EntityPlayer, int par2) {
+ ItemStack var3 = null;
+ Slot var4 = (Slot) this.inventorySlots.get(par2);
+
+ if (var4 != null && var4.getHasStack()) {
+ ItemStack var5 = var4.getStack();
+ var3 = var5.copy();
+
+ if (par2 == 0) {
+ if (!this.mergeItemStack(var5, 1, 37, true)) {
+ return null;
+ }
+ } else {
+ if (((Slot) this.inventorySlots.get(0)).getHasStack()
+ || !((Slot) this.inventorySlots.get(0)).isItemValid(var5)) {
+ return null;
+ }
+
+ if (var5.hasTagCompound() && var5.stackSize == 1) {
+ ((Slot) this.inventorySlots.get(0)).putStack(var5.copy());
+ var5.stackSize = 0;
+ } else if (var5.stackSize >= 1) {
+ ((Slot) this.inventorySlots.get(0)).putStack(new ItemStack(var5.itemID, 1, var5.getItemDamage()));
+ --var5.stackSize;
+ }
+ }
+
+ if (var5.stackSize == 0) {
+ var4.putStack((ItemStack) null);
+ } else {
+ var4.onSlotChanged();
+ }
+
+ if (var5.stackSize == var3.stackSize) {
+ return null;
+ }
+
+ var4.onPickupFromSlot(par1EntityPlayer, var5);
+ }
+
+ return var3;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ContainerFurnace.java b/sp-server/src/main/java/net/minecraft/src/ContainerFurnace.java
new file mode 100644
index 0000000..408b11c
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ContainerFurnace.java
@@ -0,0 +1,118 @@
+package net.minecraft.src;
+
+public class ContainerFurnace extends Container {
+ private TileEntityFurnace furnace;
+ private int lastCookTime = 0;
+ private int lastBurnTime = 0;
+ private int lastItemBurnTime = 0;
+
+ public ContainerFurnace(InventoryPlayer par1InventoryPlayer, TileEntityFurnace par2TileEntityFurnace) {
+ this.furnace = par2TileEntityFurnace;
+ this.addSlotToContainer(new Slot(par2TileEntityFurnace, 0, 56, 17));
+ this.addSlotToContainer(new Slot(par2TileEntityFurnace, 1, 56, 53));
+ this.addSlotToContainer(new SlotFurnace(par1InventoryPlayer.player, par2TileEntityFurnace, 2, 116, 35));
+ int var3;
+
+ for (var3 = 0; var3 < 3; ++var3) {
+ for (int var4 = 0; var4 < 9; ++var4) {
+ this.addSlotToContainer(
+ new Slot(par1InventoryPlayer, var4 + var3 * 9 + 9, 8 + var4 * 18, 84 + var3 * 18));
+ }
+ }
+
+ for (var3 = 0; var3 < 9; ++var3) {
+ this.addSlotToContainer(new Slot(par1InventoryPlayer, var3, 8 + var3 * 18, 142));
+ }
+ }
+
+ public void onCraftGuiOpened(ICrafting par1ICrafting) {
+ super.onCraftGuiOpened(par1ICrafting);
+ par1ICrafting.sendProgressBarUpdate(this, 0, this.furnace.furnaceCookTime);
+ par1ICrafting.sendProgressBarUpdate(this, 1, this.furnace.furnaceBurnTime);
+ par1ICrafting.sendProgressBarUpdate(this, 2, this.furnace.currentItemBurnTime);
+ }
+
+ /**
+ * Looks for changes made in the container, sends them to every listener.
+ */
+ public void detectAndSendChanges() {
+ super.detectAndSendChanges();
+
+ for (int var1 = 0; var1 < this.crafters.size(); ++var1) {
+ ICrafting var2 = (ICrafting) this.crafters.get(var1);
+
+ if (this.lastCookTime != this.furnace.furnaceCookTime) {
+ var2.sendProgressBarUpdate(this, 0, this.furnace.furnaceCookTime);
+ }
+
+ if (this.lastBurnTime != this.furnace.furnaceBurnTime) {
+ var2.sendProgressBarUpdate(this, 1, this.furnace.furnaceBurnTime);
+ }
+
+ if (this.lastItemBurnTime != this.furnace.currentItemBurnTime) {
+ var2.sendProgressBarUpdate(this, 2, this.furnace.currentItemBurnTime);
+ }
+ }
+
+ this.lastCookTime = this.furnace.furnaceCookTime;
+ this.lastBurnTime = this.furnace.furnaceBurnTime;
+ this.lastItemBurnTime = this.furnace.currentItemBurnTime;
+ }
+
+ public boolean canInteractWith(EntityPlayer par1EntityPlayer) {
+ return this.furnace.isUseableByPlayer(par1EntityPlayer);
+ }
+
+ /**
+ * Take a stack from the specified inventory slot.
+ */
+ public ItemStack transferStackInSlot(EntityPlayer par1EntityPlayer, int par2) {
+ ItemStack var3 = null;
+ Slot var4 = (Slot) this.inventorySlots.get(par2);
+
+ if (var4 != null && var4.getHasStack()) {
+ ItemStack var5 = var4.getStack();
+ var3 = var5.copy();
+
+ if (par2 == 2) {
+ if (!this.mergeItemStack(var5, 3, 39, true)) {
+ return null;
+ }
+
+ var4.onSlotChange(var5, var3);
+ } else if (par2 != 1 && par2 != 0) {
+ if (FurnaceRecipes.smelting().getSmeltingResult(var5.getItem().itemID) != null) {
+ if (!this.mergeItemStack(var5, 0, 1, false)) {
+ return null;
+ }
+ } else if (TileEntityFurnace.isItemFuel(var5)) {
+ if (!this.mergeItemStack(var5, 1, 2, false)) {
+ return null;
+ }
+ } else if (par2 >= 3 && par2 < 30) {
+ if (!this.mergeItemStack(var5, 30, 39, false)) {
+ return null;
+ }
+ } else if (par2 >= 30 && par2 < 39 && !this.mergeItemStack(var5, 3, 30, false)) {
+ return null;
+ }
+ } else if (!this.mergeItemStack(var5, 3, 39, false)) {
+ return null;
+ }
+
+ if (var5.stackSize == 0) {
+ var4.putStack((ItemStack) null);
+ } else {
+ var4.onSlotChanged();
+ }
+
+ if (var5.stackSize == var3.stackSize) {
+ return null;
+ }
+
+ var4.onPickupFromSlot(par1EntityPlayer, var5);
+ }
+
+ return var3;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ContainerHopper.java b/sp-server/src/main/java/net/minecraft/src/ContainerHopper.java
new file mode 100644
index 0000000..dc2c73c
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ContainerHopper.java
@@ -0,0 +1,69 @@
+package net.minecraft.src;
+
+public class ContainerHopper extends Container {
+ private final IInventory field_94538_a;
+
+ public ContainerHopper(InventoryPlayer par1InventoryPlayer, IInventory par2IInventory) {
+ this.field_94538_a = par2IInventory;
+ par2IInventory.openChest();
+ byte var3 = 51;
+ int var4;
+
+ for (var4 = 0; var4 < par2IInventory.getSizeInventory(); ++var4) {
+ this.addSlotToContainer(new Slot(par2IInventory, var4, 44 + var4 * 18, 20));
+ }
+
+ for (var4 = 0; var4 < 3; ++var4) {
+ for (int var5 = 0; var5 < 9; ++var5) {
+ this.addSlotToContainer(
+ new Slot(par1InventoryPlayer, var5 + var4 * 9 + 9, 8 + var5 * 18, var4 * 18 + var3));
+ }
+ }
+
+ for (var4 = 0; var4 < 9; ++var4) {
+ this.addSlotToContainer(new Slot(par1InventoryPlayer, var4, 8 + var4 * 18, 58 + var3));
+ }
+ }
+
+ public boolean canInteractWith(EntityPlayer par1EntityPlayer) {
+ return this.field_94538_a.isUseableByPlayer(par1EntityPlayer);
+ }
+
+ /**
+ * Take a stack from the specified inventory slot.
+ */
+ public ItemStack transferStackInSlot(EntityPlayer par1EntityPlayer, int par2) {
+ ItemStack var3 = null;
+ Slot var4 = (Slot) this.inventorySlots.get(par2);
+
+ if (var4 != null && var4.getHasStack()) {
+ ItemStack var5 = var4.getStack();
+ var3 = var5.copy();
+
+ if (par2 < this.field_94538_a.getSizeInventory()) {
+ if (!this.mergeItemStack(var5, this.field_94538_a.getSizeInventory(), this.inventorySlots.size(),
+ true)) {
+ return null;
+ }
+ } else if (!this.mergeItemStack(var5, 0, this.field_94538_a.getSizeInventory(), false)) {
+ return null;
+ }
+
+ if (var5.stackSize == 0) {
+ var4.putStack((ItemStack) null);
+ } else {
+ var4.onSlotChanged();
+ }
+ }
+
+ return var3;
+ }
+
+ /**
+ * Callback for when the crafting gui is closed.
+ */
+ public void onCraftGuiClosed(EntityPlayer par1EntityPlayer) {
+ super.onCraftGuiClosed(par1EntityPlayer);
+ this.field_94538_a.closeChest();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ContainerMerchant.java b/sp-server/src/main/java/net/minecraft/src/ContainerMerchant.java
new file mode 100644
index 0000000..705a421
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ContainerMerchant.java
@@ -0,0 +1,131 @@
+package net.minecraft.src;
+
+public class ContainerMerchant extends Container {
+ /** Instance of Merchant. */
+ private IMerchant theMerchant;
+ private InventoryMerchant merchantInventory;
+
+ /** Instance of World. */
+ private final World theWorld;
+
+ public ContainerMerchant(InventoryPlayer par1InventoryPlayer, IMerchant par2IMerchant, World par3World) {
+ this.theMerchant = par2IMerchant;
+ this.theWorld = par3World;
+ this.merchantInventory = new InventoryMerchant(par1InventoryPlayer.player, par2IMerchant);
+ this.addSlotToContainer(new Slot(this.merchantInventory, 0, 36, 53));
+ this.addSlotToContainer(new Slot(this.merchantInventory, 1, 62, 53));
+ this.addSlotToContainer(
+ new SlotMerchantResult(par1InventoryPlayer.player, par2IMerchant, this.merchantInventory, 2, 120, 53));
+ int var4;
+
+ for (var4 = 0; var4 < 3; ++var4) {
+ for (int var5 = 0; var5 < 9; ++var5) {
+ this.addSlotToContainer(
+ new Slot(par1InventoryPlayer, var5 + var4 * 9 + 9, 8 + var5 * 18, 84 + var4 * 18));
+ }
+ }
+
+ for (var4 = 0; var4 < 9; ++var4) {
+ this.addSlotToContainer(new Slot(par1InventoryPlayer, var4, 8 + var4 * 18, 142));
+ }
+ }
+
+ public InventoryMerchant getMerchantInventory() {
+ return this.merchantInventory;
+ }
+
+ public void onCraftGuiOpened(ICrafting par1ICrafting) {
+ super.onCraftGuiOpened(par1ICrafting);
+ }
+
+ /**
+ * Looks for changes made in the container, sends them to every listener.
+ */
+ public void detectAndSendChanges() {
+ super.detectAndSendChanges();
+ }
+
+ /**
+ * Callback for when the crafting matrix is changed.
+ */
+ public void onCraftMatrixChanged(IInventory par1IInventory) {
+ this.merchantInventory.resetRecipeAndSlots();
+ super.onCraftMatrixChanged(par1IInventory);
+ }
+
+ public void setCurrentRecipeIndex(int par1) {
+ this.merchantInventory.setCurrentRecipeIndex(par1);
+ }
+
+ public boolean canInteractWith(EntityPlayer par1EntityPlayer) {
+ return this.theMerchant.getCustomer() == par1EntityPlayer;
+ }
+
+ /**
+ * Take a stack from the specified inventory slot.
+ */
+ public ItemStack transferStackInSlot(EntityPlayer par1EntityPlayer, int par2) {
+ ItemStack var3 = null;
+ Slot var4 = (Slot) this.inventorySlots.get(par2);
+
+ if (var4 != null && var4.getHasStack()) {
+ ItemStack var5 = var4.getStack();
+ var3 = var5.copy();
+
+ if (par2 == 2) {
+ if (!this.mergeItemStack(var5, 3, 39, true)) {
+ return null;
+ }
+
+ var4.onSlotChange(var5, var3);
+ } else if (par2 != 0 && par2 != 1) {
+ if (par2 >= 3 && par2 < 30) {
+ if (!this.mergeItemStack(var5, 30, 39, false)) {
+ return null;
+ }
+ } else if (par2 >= 30 && par2 < 39 && !this.mergeItemStack(var5, 3, 30, false)) {
+ return null;
+ }
+ } else if (!this.mergeItemStack(var5, 3, 39, false)) {
+ return null;
+ }
+
+ if (var5.stackSize == 0) {
+ var4.putStack((ItemStack) null);
+ } else {
+ var4.onSlotChanged();
+ }
+
+ if (var5.stackSize == var3.stackSize) {
+ return null;
+ }
+
+ var4.onPickupFromSlot(par1EntityPlayer, var5);
+ }
+
+ return var3;
+ }
+
+ /**
+ * Callback for when the crafting gui is closed.
+ */
+ public void onCraftGuiClosed(EntityPlayer par1EntityPlayer) {
+ super.onCraftGuiClosed(par1EntityPlayer);
+ this.theMerchant.setCustomer((EntityPlayer) null);
+ super.onCraftGuiClosed(par1EntityPlayer);
+
+ if (!this.theWorld.isRemote) {
+ ItemStack var2 = this.merchantInventory.getStackInSlotOnClosing(0);
+
+ if (var2 != null) {
+ par1EntityPlayer.dropPlayerItem(var2);
+ }
+
+ var2 = this.merchantInventory.getStackInSlotOnClosing(1);
+
+ if (var2 != null) {
+ par1EntityPlayer.dropPlayerItem(var2);
+ }
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ContainerPlayer.java b/sp-server/src/main/java/net/minecraft/src/ContainerPlayer.java
new file mode 100644
index 0000000..a283323
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ContainerPlayer.java
@@ -0,0 +1,137 @@
+package net.minecraft.src;
+
+public class ContainerPlayer extends Container {
+ /** The crafting matrix inventory. */
+ public InventoryCrafting craftMatrix = new InventoryCrafting(this, 2, 2);
+ public IInventory craftResult = new InventoryCraftResult();
+
+ /** Determines if inventory manipulation should be handled. */
+ public boolean isLocalWorld = false;
+ private final EntityPlayer thePlayer;
+
+ public ContainerPlayer(InventoryPlayer par1InventoryPlayer, boolean par2, EntityPlayer par3EntityPlayer) {
+ this.isLocalWorld = par2;
+ this.thePlayer = par3EntityPlayer;
+ this.addSlotToContainer(
+ new SlotCrafting(par1InventoryPlayer.player, this.craftMatrix, this.craftResult, 0, 144, 36));
+ int var4;
+ int var5;
+
+ for (var4 = 0; var4 < 2; ++var4) {
+ for (var5 = 0; var5 < 2; ++var5) {
+ this.addSlotToContainer(new Slot(this.craftMatrix, var5 + var4 * 2, 88 + var5 * 18, 26 + var4 * 18));
+ }
+ }
+
+ for (var4 = 0; var4 < 4; ++var4) {
+ this.addSlotToContainer(new SlotArmor(this, par1InventoryPlayer,
+ par1InventoryPlayer.getSizeInventory() - 1 - var4, 8, 8 + var4 * 18, var4));
+ }
+
+ for (var4 = 0; var4 < 3; ++var4) {
+ for (var5 = 0; var5 < 9; ++var5) {
+ this.addSlotToContainer(
+ new Slot(par1InventoryPlayer, var5 + (var4 + 1) * 9, 8 + var5 * 18, 84 + var4 * 18));
+ }
+ }
+
+ for (var4 = 0; var4 < 9; ++var4) {
+ this.addSlotToContainer(new Slot(par1InventoryPlayer, var4, 8 + var4 * 18, 142));
+ }
+
+ this.onCraftMatrixChanged(this.craftMatrix);
+ }
+
+ /**
+ * Callback for when the crafting matrix is changed.
+ */
+ public void onCraftMatrixChanged(IInventory par1IInventory) {
+ this.craftResult.setInventorySlotContents(0,
+ CraftingManager.getInstance().findMatchingRecipe(this.craftMatrix, this.thePlayer.worldObj));
+ }
+
+ /**
+ * Callback for when the crafting gui is closed.
+ */
+ public void onCraftGuiClosed(EntityPlayer par1EntityPlayer) {
+ super.onCraftGuiClosed(par1EntityPlayer);
+
+ for (int var2 = 0; var2 < 4; ++var2) {
+ ItemStack var3 = this.craftMatrix.getStackInSlotOnClosing(var2);
+
+ if (var3 != null) {
+ par1EntityPlayer.dropPlayerItem(var3);
+ }
+ }
+
+ this.craftResult.setInventorySlotContents(0, (ItemStack) null);
+ }
+
+ public boolean canInteractWith(EntityPlayer par1EntityPlayer) {
+ return true;
+ }
+
+ /**
+ * Take a stack from the specified inventory slot.
+ */
+ public ItemStack transferStackInSlot(EntityPlayer par1EntityPlayer, int par2) {
+ ItemStack var3 = null;
+ Slot var4 = (Slot) this.inventorySlots.get(par2);
+
+ if (var4 != null && var4.getHasStack()) {
+ ItemStack var5 = var4.getStack();
+ var3 = var5.copy();
+
+ if (par2 == 0) {
+ if (!this.mergeItemStack(var5, 9, 45, true)) {
+ return null;
+ }
+
+ var4.onSlotChange(var5, var3);
+ } else if (par2 >= 1 && par2 < 5) {
+ if (!this.mergeItemStack(var5, 9, 45, false)) {
+ return null;
+ }
+ } else if (par2 >= 5 && par2 < 9) {
+ if (!this.mergeItemStack(var5, 9, 45, false)) {
+ return null;
+ }
+ } else if (var3.getItem() instanceof ItemArmor
+ && !((Slot) this.inventorySlots.get(5 + ((ItemArmor) var3.getItem()).armorType)).getHasStack()) {
+ int var6 = 5 + ((ItemArmor) var3.getItem()).armorType;
+
+ if (!this.mergeItemStack(var5, var6, var6 + 1, false)) {
+ return null;
+ }
+ } else if (par2 >= 9 && par2 < 36) {
+ if (!this.mergeItemStack(var5, 36, 45, false)) {
+ return null;
+ }
+ } else if (par2 >= 36 && par2 < 45) {
+ if (!this.mergeItemStack(var5, 9, 36, false)) {
+ return null;
+ }
+ } else if (!this.mergeItemStack(var5, 9, 45, false)) {
+ return null;
+ }
+
+ if (var5.stackSize == 0) {
+ var4.putStack((ItemStack) null);
+ } else {
+ var4.onSlotChanged();
+ }
+
+ if (var5.stackSize == var3.stackSize) {
+ return null;
+ }
+
+ var4.onPickupFromSlot(par1EntityPlayer, var5);
+ }
+
+ return var3;
+ }
+
+ public boolean func_94530_a(ItemStack par1ItemStack, Slot par2Slot) {
+ return par2Slot.inventory != this.craftResult && super.func_94530_a(par1ItemStack, par2Slot);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ContainerRepair.java b/sp-server/src/main/java/net/minecraft/src/ContainerRepair.java
new file mode 100644
index 0000000..0256e1b
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ContainerRepair.java
@@ -0,0 +1,407 @@
+package net.minecraft.src;
+
+import java.util.Iterator;
+import java.util.Map;
+
+public class ContainerRepair extends Container {
+ /** Here comes out item you merged and/or renamed. */
+ private IInventory outputSlot = new InventoryCraftResult();
+
+ /**
+ * The 2slots where you put your items in that you want to merge and/or rename.
+ */
+ private IInventory inputSlots = new InventoryRepair(this, "Repair", true, 2);
+ private World theWorld;
+ private int field_82861_i;
+ private int field_82858_j;
+ private int field_82859_k;
+
+ /** The maximum cost of repairing/renaming in the anvil. */
+ public int maximumCost = 0;
+
+ /** determined by damage of input item and stackSize of repair materials */
+ private int stackSizeToBeUsedInRepair = 0;
+ private String repairedItemName;
+
+ /** The player that has this container open. */
+ private final EntityPlayer thePlayer;
+
+ public ContainerRepair(InventoryPlayer par1InventoryPlayer, World par2World, int par3, int par4, int par5,
+ EntityPlayer par6EntityPlayer) {
+ this.theWorld = par2World;
+ this.field_82861_i = par3;
+ this.field_82858_j = par4;
+ this.field_82859_k = par5;
+ this.thePlayer = par6EntityPlayer;
+ this.addSlotToContainer(new Slot(this.inputSlots, 0, 27, 47));
+ this.addSlotToContainer(new Slot(this.inputSlots, 1, 76, 47));
+ this.addSlotToContainer(new SlotRepair(this, this.outputSlot, 2, 134, 47, par2World, par3, par4, par5));
+ int var7;
+
+ for (var7 = 0; var7 < 3; ++var7) {
+ for (int var8 = 0; var8 < 9; ++var8) {
+ this.addSlotToContainer(
+ new Slot(par1InventoryPlayer, var8 + var7 * 9 + 9, 8 + var8 * 18, 84 + var7 * 18));
+ }
+ }
+
+ for (var7 = 0; var7 < 9; ++var7) {
+ this.addSlotToContainer(new Slot(par1InventoryPlayer, var7, 8 + var7 * 18, 142));
+ }
+ }
+
+ /**
+ * Callback for when the crafting matrix is changed.
+ */
+ public void onCraftMatrixChanged(IInventory par1IInventory) {
+ super.onCraftMatrixChanged(par1IInventory);
+
+ if (par1IInventory == this.inputSlots) {
+ this.updateRepairOutput();
+ }
+ }
+
+ /**
+ * called when the Anvil Input Slot changes, calculates the new result and puts
+ * it in the output slot
+ */
+ public void updateRepairOutput() {
+ ItemStack var1 = this.inputSlots.getStackInSlot(0);
+ this.maximumCost = 0;
+ int var2 = 0;
+ byte var3 = 0;
+ int var4 = 0;
+
+ if (var1 == null) {
+ this.outputSlot.setInventorySlotContents(0, (ItemStack) null);
+ this.maximumCost = 0;
+ } else {
+ ItemStack var5 = var1.copy();
+ ItemStack var6 = this.inputSlots.getStackInSlot(1);
+ Map var7 = EnchantmentHelper.getEnchantments(var5);
+ boolean var8 = false;
+ int var19 = var3 + var1.getRepairCost() + (var6 == null ? 0 : var6.getRepairCost());
+ this.stackSizeToBeUsedInRepair = 0;
+ int var9;
+ int var10;
+ int var11;
+ int var13;
+ int var14;
+ Iterator var21;
+ Enchantment var22;
+
+ if (var6 != null) {
+ var8 = var6.itemID == Item.enchantedBook.itemID && Item.enchantedBook.func_92110_g(var6).tagCount() > 0;
+
+ if (var5.isItemStackDamageable() && Item.itemsList[var5.itemID].getIsRepairable(var1, var6)) {
+ var9 = Math.min(var5.getItemDamageForDisplay(), var5.getMaxDamage() / 4);
+
+ if (var9 <= 0) {
+ this.outputSlot.setInventorySlotContents(0, (ItemStack) null);
+ this.maximumCost = 0;
+ return;
+ }
+
+ for (var10 = 0; var9 > 0 && var10 < var6.stackSize; ++var10) {
+ var11 = var5.getItemDamageForDisplay() - var9;
+ var5.setItemDamage(var11);
+ var2 += Math.max(1, var9 / 100) + var7.size();
+ var9 = Math.min(var5.getItemDamageForDisplay(), var5.getMaxDamage() / 4);
+ }
+
+ this.stackSizeToBeUsedInRepair = var10;
+ } else {
+ if (!var8 && (var5.itemID != var6.itemID || !var5.isItemStackDamageable())) {
+ this.outputSlot.setInventorySlotContents(0, (ItemStack) null);
+ this.maximumCost = 0;
+ return;
+ }
+
+ if (var5.isItemStackDamageable() && !var8) {
+ var9 = var1.getMaxDamage() - var1.getItemDamageForDisplay();
+ var10 = var6.getMaxDamage() - var6.getItemDamageForDisplay();
+ var11 = var10 + var5.getMaxDamage() * 12 / 100;
+ int var12 = var9 + var11;
+ var13 = var5.getMaxDamage() - var12;
+
+ if (var13 < 0) {
+ var13 = 0;
+ }
+
+ if (var13 < var5.getItemDamage()) {
+ var5.setItemDamage(var13);
+ var2 += Math.max(1, var11 / 100);
+ }
+ }
+
+ Map var20 = EnchantmentHelper.getEnchantments(var6);
+ var21 = var20.keySet().iterator();
+
+ while (var21.hasNext()) {
+ var11 = ((Integer) var21.next()).intValue();
+ var22 = Enchantment.enchantmentsList[var11];
+ var13 = var7.containsKey(Integer.valueOf(var11))
+ ? ((Integer) var7.get(Integer.valueOf(var11))).intValue()
+ : 0;
+ var14 = ((Integer) var20.get(Integer.valueOf(var11))).intValue();
+ int var10000;
+
+ if (var13 == var14) {
+ ++var14;
+ var10000 = var14;
+ } else {
+ var10000 = Math.max(var14, var13);
+ }
+
+ var14 = var10000;
+ int var15 = var14 - var13;
+ boolean var16 = var22.func_92089_a(var1);
+
+ if (this.thePlayer.capabilities.isCreativeMode
+ || var1.itemID == ItemEnchantedBook.enchantedBook.itemID) {
+ var16 = true;
+ }
+
+ Iterator var17 = var7.keySet().iterator();
+
+ while (var17.hasNext()) {
+ int var18 = ((Integer) var17.next()).intValue();
+
+ if (var18 != var11 && !var22.canApplyTogether(Enchantment.enchantmentsList[var18])) {
+ var16 = false;
+ var2 += var15;
+ }
+ }
+
+ if (var16) {
+ if (var14 > var22.getMaxLevel()) {
+ var14 = var22.getMaxLevel();
+ }
+
+ var7.put(Integer.valueOf(var11), Integer.valueOf(var14));
+ int var23 = 0;
+
+ switch (var22.getWeight()) {
+ case 1:
+ var23 = 8;
+ break;
+
+ case 2:
+ var23 = 4;
+
+ case 3:
+ case 4:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ default:
+ break;
+
+ case 5:
+ var23 = 2;
+ break;
+
+ case 10:
+ var23 = 1;
+ }
+
+ if (var8) {
+ var23 = Math.max(1, var23 / 2);
+ }
+
+ var2 += var23 * var15;
+ }
+ }
+ }
+ }
+
+ if (this.repairedItemName != null && this.repairedItemName.length() > 0
+ && !this.repairedItemName
+ .equalsIgnoreCase(this.thePlayer.getTranslator().translateNamedKey(var1.getItemName()))
+ && !this.repairedItemName.equals(var1.getDisplayName())) {
+ var4 = var1.isItemStackDamageable() ? 7 : var1.stackSize * 5;
+ var2 += var4;
+
+ if (var1.hasDisplayName()) {
+ var19 += var4 / 2;
+ }
+
+ var5.setItemName(this.repairedItemName);
+ }
+
+ var9 = 0;
+
+ for (var21 = var7.keySet().iterator(); var21.hasNext(); var19 += var9 + var13 * var14) {
+ var11 = ((Integer) var21.next()).intValue();
+ var22 = Enchantment.enchantmentsList[var11];
+ var13 = ((Integer) var7.get(Integer.valueOf(var11))).intValue();
+ var14 = 0;
+ ++var9;
+
+ switch (var22.getWeight()) {
+ case 1:
+ var14 = 8;
+ break;
+
+ case 2:
+ var14 = 4;
+
+ case 3:
+ case 4:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ default:
+ break;
+
+ case 5:
+ var14 = 2;
+ break;
+
+ case 10:
+ var14 = 1;
+ }
+
+ if (var8) {
+ var14 = Math.max(1, var14 / 2);
+ }
+ }
+
+ if (var8) {
+ var19 = Math.max(1, var19 / 2);
+ }
+
+ this.maximumCost = var19 + var2;
+
+ if (var2 <= 0) {
+ var5 = null;
+ }
+
+ if (var4 == var2 && var4 > 0 && this.maximumCost >= 40) {
+ this.theWorld.getWorldLogAgent()
+ .func_98233_a("Naming an item only, cost too high; giving discount to cap cost to 39 levels");
+ this.maximumCost = 39;
+ }
+
+ if (this.maximumCost >= 40 && !this.thePlayer.capabilities.isCreativeMode) {
+ var5 = null;
+ }
+
+ if (var5 != null) {
+ var10 = var5.getRepairCost();
+
+ if (var6 != null && var10 < var6.getRepairCost()) {
+ var10 = var6.getRepairCost();
+ }
+
+ if (var5.hasDisplayName()) {
+ var10 -= 9;
+ }
+
+ if (var10 < 0) {
+ var10 = 0;
+ }
+
+ var10 += 2;
+ var5.setRepairCost(var10);
+ EnchantmentHelper.setEnchantments(var7, var5);
+ }
+
+ this.outputSlot.setInventorySlotContents(0, var5);
+ this.detectAndSendChanges();
+ }
+ }
+
+ public void onCraftGuiOpened(ICrafting par1ICrafting) {
+ super.onCraftGuiOpened(par1ICrafting);
+ par1ICrafting.sendProgressBarUpdate(this, 0, this.maximumCost);
+ }
+
+ /**
+ * Callback for when the crafting gui is closed.
+ */
+ public void onCraftGuiClosed(EntityPlayer par1EntityPlayer) {
+ super.onCraftGuiClosed(par1EntityPlayer);
+
+ if (!this.theWorld.isRemote) {
+ for (int var2 = 0; var2 < this.inputSlots.getSizeInventory(); ++var2) {
+ ItemStack var3 = this.inputSlots.getStackInSlotOnClosing(var2);
+
+ if (var3 != null) {
+ par1EntityPlayer.dropPlayerItem(var3);
+ }
+ }
+ }
+ }
+
+ public boolean canInteractWith(EntityPlayer par1EntityPlayer) {
+ return this.theWorld.getBlockId(this.field_82861_i, this.field_82858_j,
+ this.field_82859_k) != Block.anvil.blockID ? false
+ : par1EntityPlayer.getDistanceSq((double) this.field_82861_i + 0.5D,
+ (double) this.field_82858_j + 0.5D, (double) this.field_82859_k + 0.5D) <= 64.0D;
+ }
+
+ /**
+ * Take a stack from the specified inventory slot.
+ */
+ public ItemStack transferStackInSlot(EntityPlayer par1EntityPlayer, int par2) {
+ ItemStack var3 = null;
+ Slot var4 = (Slot) this.inventorySlots.get(par2);
+
+ if (var4 != null && var4.getHasStack()) {
+ ItemStack var5 = var4.getStack();
+ var3 = var5.copy();
+
+ if (par2 == 2) {
+ if (!this.mergeItemStack(var5, 3, 39, true)) {
+ return null;
+ }
+
+ var4.onSlotChange(var5, var3);
+ } else if (par2 != 0 && par2 != 1) {
+ if (par2 >= 3 && par2 < 39 && !this.mergeItemStack(var5, 0, 2, false)) {
+ return null;
+ }
+ } else if (!this.mergeItemStack(var5, 3, 39, false)) {
+ return null;
+ }
+
+ if (var5.stackSize == 0) {
+ var4.putStack((ItemStack) null);
+ } else {
+ var4.onSlotChanged();
+ }
+
+ if (var5.stackSize == var3.stackSize) {
+ return null;
+ }
+
+ var4.onPickupFromSlot(par1EntityPlayer, var5);
+ }
+
+ return var3;
+ }
+
+ /**
+ * used by the Anvil GUI to update the Item Name being typed by the player
+ */
+ public void updateItemName(String par1Str) {
+ this.repairedItemName = par1Str;
+
+ if (this.getSlot(2).getHasStack()) {
+ this.getSlot(2).getStack().setItemName(this.repairedItemName);
+ }
+
+ this.updateRepairOutput();
+ }
+
+ static IInventory getRepairInputInventory(ContainerRepair par0ContainerRepair) {
+ return par0ContainerRepair.inputSlots;
+ }
+
+ static int getStackSizeUsedInRepair(ContainerRepair par0ContainerRepair) {
+ return par0ContainerRepair.stackSizeToBeUsedInRepair;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ContainerSheep.java b/sp-server/src/main/java/net/minecraft/src/ContainerSheep.java
new file mode 100644
index 0000000..51f8979
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ContainerSheep.java
@@ -0,0 +1,13 @@
+package net.minecraft.src;
+
+class ContainerSheep extends Container {
+ final EntitySheep field_90034_a;
+
+ ContainerSheep(EntitySheep par1EntitySheep) {
+ this.field_90034_a = par1EntitySheep;
+ }
+
+ public boolean canInteractWith(EntityPlayer par1EntityPlayer) {
+ return false;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ContainerWorkbench.java b/sp-server/src/main/java/net/minecraft/src/ContainerWorkbench.java
new file mode 100644
index 0000000..3842597
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ContainerWorkbench.java
@@ -0,0 +1,121 @@
+package net.minecraft.src;
+
+public class ContainerWorkbench extends Container {
+ /** The crafting matrix inventory (3x3). */
+ public InventoryCrafting craftMatrix = new InventoryCrafting(this, 3, 3);
+ public IInventory craftResult = new InventoryCraftResult();
+ private World worldObj;
+ private int posX;
+ private int posY;
+ private int posZ;
+
+ public ContainerWorkbench(InventoryPlayer par1InventoryPlayer, World par2World, int par3, int par4, int par5) {
+ this.worldObj = par2World;
+ this.posX = par3;
+ this.posY = par4;
+ this.posZ = par5;
+ this.addSlotToContainer(
+ new SlotCrafting(par1InventoryPlayer.player, this.craftMatrix, this.craftResult, 0, 124, 35));
+ int var6;
+ int var7;
+
+ for (var6 = 0; var6 < 3; ++var6) {
+ for (var7 = 0; var7 < 3; ++var7) {
+ this.addSlotToContainer(new Slot(this.craftMatrix, var7 + var6 * 3, 30 + var7 * 18, 17 + var6 * 18));
+ }
+ }
+
+ for (var6 = 0; var6 < 3; ++var6) {
+ for (var7 = 0; var7 < 9; ++var7) {
+ this.addSlotToContainer(
+ new Slot(par1InventoryPlayer, var7 + var6 * 9 + 9, 8 + var7 * 18, 84 + var6 * 18));
+ }
+ }
+
+ for (var6 = 0; var6 < 9; ++var6) {
+ this.addSlotToContainer(new Slot(par1InventoryPlayer, var6, 8 + var6 * 18, 142));
+ }
+
+ this.onCraftMatrixChanged(this.craftMatrix);
+ }
+
+ /**
+ * Callback for when the crafting matrix is changed.
+ */
+ public void onCraftMatrixChanged(IInventory par1IInventory) {
+ this.craftResult.setInventorySlotContents(0,
+ CraftingManager.getInstance().findMatchingRecipe(this.craftMatrix, this.worldObj));
+ }
+
+ /**
+ * Callback for when the crafting gui is closed.
+ */
+ public void onCraftGuiClosed(EntityPlayer par1EntityPlayer) {
+ super.onCraftGuiClosed(par1EntityPlayer);
+
+ if (!this.worldObj.isRemote) {
+ for (int var2 = 0; var2 < 9; ++var2) {
+ ItemStack var3 = this.craftMatrix.getStackInSlotOnClosing(var2);
+
+ if (var3 != null) {
+ par1EntityPlayer.dropPlayerItem(var3);
+ }
+ }
+ }
+ }
+
+ public boolean canInteractWith(EntityPlayer par1EntityPlayer) {
+ return this.worldObj.getBlockId(this.posX, this.posY, this.posZ) != Block.workbench.blockID ? false
+ : par1EntityPlayer.getDistanceSq((double) this.posX + 0.5D, (double) this.posY + 0.5D,
+ (double) this.posZ + 0.5D) <= 64.0D;
+ }
+
+ /**
+ * Take a stack from the specified inventory slot.
+ */
+ public ItemStack transferStackInSlot(EntityPlayer par1EntityPlayer, int par2) {
+ ItemStack var3 = null;
+ Slot var4 = (Slot) this.inventorySlots.get(par2);
+
+ if (var4 != null && var4.getHasStack()) {
+ ItemStack var5 = var4.getStack();
+ var3 = var5.copy();
+
+ if (par2 == 0) {
+ if (!this.mergeItemStack(var5, 10, 46, true)) {
+ return null;
+ }
+
+ var4.onSlotChange(var5, var3);
+ } else if (par2 >= 10 && par2 < 37) {
+ if (!this.mergeItemStack(var5, 37, 46, false)) {
+ return null;
+ }
+ } else if (par2 >= 37 && par2 < 46) {
+ if (!this.mergeItemStack(var5, 10, 37, false)) {
+ return null;
+ }
+ } else if (!this.mergeItemStack(var5, 10, 46, false)) {
+ return null;
+ }
+
+ if (var5.stackSize == 0) {
+ var4.putStack((ItemStack) null);
+ } else {
+ var4.onSlotChanged();
+ }
+
+ if (var5.stackSize == var3.stackSize) {
+ return null;
+ }
+
+ var4.onPickupFromSlot(par1EntityPlayer, var5);
+ }
+
+ return var3;
+ }
+
+ public boolean func_94530_a(ItemStack par1ItemStack, Slot par2Slot) {
+ return par2Slot.inventory != this.craftResult && super.func_94530_a(par1ItemStack, par2Slot);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ConvertingProgressUpdate.java b/sp-server/src/main/java/net/minecraft/src/ConvertingProgressUpdate.java
new file mode 100644
index 0000000..ada3d1d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ConvertingProgressUpdate.java
@@ -0,0 +1,41 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.SysUtil;
+import net.minecraft.server.MinecraftServer;
+
+public class ConvertingProgressUpdate implements IProgressUpdate {
+ private long field_96245_b;
+
+ /** Reference to the MinecraftServer object. */
+ final MinecraftServer mcServer;
+
+ public ConvertingProgressUpdate(MinecraftServer par1) {
+ this.mcServer = par1;
+ this.field_96245_b = SysUtil.steadyTimeMillis();
+ }
+
+ /**
+ * Shows the 'Saving level' string.
+ */
+ public void displaySavingString(String par1Str) {
+ }
+
+ /**
+ * Updates the progress bar on the loading screen to the specified amount. Args:
+ * loadProgress
+ */
+ public void setLoadingProgress(int par1) {
+ long l = SysUtil.steadyTimeMillis();
+ if (l - this.field_96245_b >= 1000L) {
+ this.field_96245_b = l;
+ this.mcServer.getLogAgent().func_98233_a("Converting... " + par1 + "%");
+ }
+ }
+
+ /**
+ * Displays a string on the loading screen supposed to indicate what is being
+ * done currently.
+ */
+ public void displayLoadingString(String par1Str) {
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/CraftingManager.java b/sp-server/src/main/java/net/minecraft/src/CraftingManager.java
new file mode 100644
index 0000000..6126440
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/CraftingManager.java
@@ -0,0 +1,342 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+
+public class CraftingManager {
+ /** The static instance of this class */
+ private static final CraftingManager instance = new CraftingManager();
+
+ /** A list of all the recipes added */
+ private List recipes = new ArrayList();
+
+ /**
+ * Returns the static instance of this class
+ */
+ public static final CraftingManager getInstance() {
+ return instance;
+ }
+
+ private CraftingManager() {
+ (new RecipesTools()).addRecipes(this);
+ (new RecipesWeapons()).addRecipes(this);
+ (new RecipesIngots()).addRecipes(this);
+ (new RecipesFood()).addRecipes(this);
+ (new RecipesCrafting()).addRecipes(this);
+ (new RecipesArmor()).addRecipes(this);
+ (new RecipesDyes()).addRecipes(this);
+ this.recipes.add(new RecipesArmorDyes());
+ this.recipes.add(new RecipesMapCloning());
+ this.recipes.add(new RecipesMapExtending());
+ this.recipes.add(new RecipeFireworks());
+ this.addRecipe(new ItemStack(Item.paper, 3), new Object[] { "###", '#', Item.reed });
+ this.addShapelessRecipe(new ItemStack(Item.book, 1),
+ new Object[] { Item.paper, Item.paper, Item.paper, Item.leather });
+ this.addShapelessRecipe(new ItemStack(Item.writableBook, 1),
+ new Object[] { Item.book, new ItemStack(Item.dyePowder, 1, 0), Item.feather });
+ this.addRecipe(new ItemStack(Block.fence, 2), new Object[] { "###", "###", '#', Item.stick });
+ this.addRecipe(new ItemStack(Block.cobblestoneWall, 6, 0),
+ new Object[] { "###", "###", '#', Block.cobblestone });
+ this.addRecipe(new ItemStack(Block.cobblestoneWall, 6, 1),
+ new Object[] { "###", "###", '#', Block.cobblestoneMossy });
+ this.addRecipe(new ItemStack(Block.netherFence, 6), new Object[] { "###", "###", '#', Block.netherBrick });
+ this.addRecipe(new ItemStack(Block.fenceGate, 1),
+ new Object[] { "#W#", "#W#", '#', Item.stick, 'W', Block.planks });
+ this.addRecipe(new ItemStack(Block.jukebox, 1),
+ new Object[] { "###", "#X#", "###", '#', Block.planks, 'X', Item.diamond });
+ this.addRecipe(new ItemStack(Block.music, 1),
+ new Object[] { "###", "#X#", "###", '#', Block.planks, 'X', Item.redstone });
+ this.addRecipe(new ItemStack(Block.bookShelf, 1),
+ new Object[] { "###", "XXX", "###", '#', Block.planks, 'X', Item.book });
+ this.addRecipe(new ItemStack(Block.blockSnow, 1), new Object[] { "##", "##", '#', Item.snowball });
+ this.addRecipe(new ItemStack(Block.snow, 6), new Object[] { "###", '#', Block.blockSnow });
+ this.addRecipe(new ItemStack(Block.blockClay, 1), new Object[] { "##", "##", '#', Item.clay });
+ this.addRecipe(new ItemStack(Block.brick, 1), new Object[] { "##", "##", '#', Item.brick });
+ this.addRecipe(new ItemStack(Block.glowStone, 1), new Object[] { "##", "##", '#', Item.lightStoneDust });
+ this.addRecipe(new ItemStack(Block.blockNetherQuartz, 1), new Object[] { "##", "##", '#', Item.netherQuartz });
+ this.addRecipe(new ItemStack(Block.cloth, 1), new Object[] { "##", "##", '#', Item.silk });
+ this.addRecipe(new ItemStack(Block.tnt, 1),
+ new Object[] { "X#X", "#X#", "X#X", 'X', Item.gunpowder, '#', Block.sand });
+ this.addRecipe(new ItemStack(Block.stoneSingleSlab, 6, 3), new Object[] { "###", '#', Block.cobblestone });
+ this.addRecipe(new ItemStack(Block.stoneSingleSlab, 6, 0), new Object[] { "###", '#', Block.stone });
+ this.addRecipe(new ItemStack(Block.stoneSingleSlab, 6, 1), new Object[] { "###", '#', Block.sandStone });
+ this.addRecipe(new ItemStack(Block.stoneSingleSlab, 6, 4), new Object[] { "###", '#', Block.brick });
+ this.addRecipe(new ItemStack(Block.stoneSingleSlab, 6, 5), new Object[] { "###", '#', Block.stoneBrick });
+ this.addRecipe(new ItemStack(Block.stoneSingleSlab, 6, 6), new Object[] { "###", '#', Block.netherBrick });
+ this.addRecipe(new ItemStack(Block.stoneSingleSlab, 6, 7),
+ new Object[] { "###", '#', Block.blockNetherQuartz });
+ this.addRecipe(new ItemStack(Block.woodSingleSlab, 6, 0),
+ new Object[] { "###", '#', new ItemStack(Block.planks, 1, 0) });
+ this.addRecipe(new ItemStack(Block.woodSingleSlab, 6, 2),
+ new Object[] { "###", '#', new ItemStack(Block.planks, 1, 2) });
+ this.addRecipe(new ItemStack(Block.woodSingleSlab, 6, 1),
+ new Object[] { "###", '#', new ItemStack(Block.planks, 1, 1) });
+ this.addRecipe(new ItemStack(Block.woodSingleSlab, 6, 3),
+ new Object[] { "###", '#', new ItemStack(Block.planks, 1, 3) });
+ this.addRecipe(new ItemStack(Block.ladder, 3), new Object[] { "# #", "###", "# #", '#', Item.stick });
+ this.addRecipe(new ItemStack(Item.doorWood, 1), new Object[] { "##", "##", "##", '#', Block.planks });
+ this.addRecipe(new ItemStack(Block.trapdoor, 2), new Object[] { "###", "###", '#', Block.planks });
+ this.addRecipe(new ItemStack(Item.doorIron, 1), new Object[] { "##", "##", "##", '#', Item.ingotIron });
+ this.addRecipe(new ItemStack(Item.sign, 3),
+ new Object[] { "###", "###", " X ", '#', Block.planks, 'X', Item.stick });
+ this.addRecipe(new ItemStack(Item.cake, 1), new Object[] { "AAA", "BEB", "CCC", 'A', Item.bucketMilk, 'B',
+ Item.sugar, 'C', Item.wheat, 'E', Item.egg });
+ this.addRecipe(new ItemStack(Item.sugar, 1), new Object[] { "#", '#', Item.reed });
+ this.addRecipe(new ItemStack(Block.planks, 4, 0), new Object[] { "#", '#', new ItemStack(Block.wood, 1, 0) });
+ this.addRecipe(new ItemStack(Block.planks, 4, 1), new Object[] { "#", '#', new ItemStack(Block.wood, 1, 1) });
+ this.addRecipe(new ItemStack(Block.planks, 4, 2), new Object[] { "#", '#', new ItemStack(Block.wood, 1, 2) });
+ this.addRecipe(new ItemStack(Block.planks, 4, 3), new Object[] { "#", '#', new ItemStack(Block.wood, 1, 3) });
+ this.addRecipe(new ItemStack(Item.stick, 4), new Object[] { "#", "#", '#', Block.planks });
+ this.addRecipe(new ItemStack(Block.torchWood, 4), new Object[] { "X", "#", 'X', Item.coal, '#', Item.stick });
+ this.addRecipe(new ItemStack(Block.torchWood, 4),
+ new Object[] { "X", "#", 'X', new ItemStack(Item.coal, 1, 1), '#', Item.stick });
+ this.addRecipe(new ItemStack(Item.bowlEmpty, 4), new Object[] { "# #", " # ", '#', Block.planks });
+ this.addRecipe(new ItemStack(Item.glassBottle, 3), new Object[] { "# #", " # ", '#', Block.glass });
+ this.addRecipe(new ItemStack(Block.rail, 16),
+ new Object[] { "X X", "X#X", "X X", 'X', Item.ingotIron, '#', Item.stick });
+ this.addRecipe(new ItemStack(Block.railPowered, 6),
+ new Object[] { "X X", "X#X", "XRX", 'X', Item.ingotGold, 'R', Item.redstone, '#', Item.stick });
+ this.addRecipe(new ItemStack(Block.railActivator, 6), new Object[] { "XSX", "X#X", "XSX", 'X', Item.ingotIron,
+ '#', Block.torchRedstoneActive, 'S', Item.stick });
+ this.addRecipe(new ItemStack(Block.railDetector, 6), new Object[] { "X X", "X#X", "XRX", 'X', Item.ingotIron,
+ 'R', Item.redstone, '#', Block.pressurePlateStone });
+ this.addRecipe(new ItemStack(Item.minecartEmpty, 1), new Object[] { "# #", "###", '#', Item.ingotIron });
+ this.addRecipe(new ItemStack(Item.cauldron, 1), new Object[] { "# #", "# #", "###", '#', Item.ingotIron });
+ this.addRecipe(new ItemStack(Item.brewingStand, 1),
+ new Object[] { " B ", "###", '#', Block.cobblestone, 'B', Item.blazeRod });
+ this.addRecipe(new ItemStack(Block.pumpkinLantern, 1),
+ new Object[] { "A", "B", 'A', Block.pumpkin, 'B', Block.torchWood });
+ this.addRecipe(new ItemStack(Item.minecartCrate, 1),
+ new Object[] { "A", "B", 'A', Block.chest, 'B', Item.minecartEmpty });
+ this.addRecipe(new ItemStack(Item.minecartPowered, 1),
+ new Object[] { "A", "B", 'A', Block.furnaceIdle, 'B', Item.minecartEmpty });
+ this.addRecipe(new ItemStack(Item.tntMinecart, 1),
+ new Object[] { "A", "B", 'A', Block.tnt, 'B', Item.minecartEmpty });
+ this.addRecipe(new ItemStack(Item.hopperMinecart, 1),
+ new Object[] { "A", "B", 'A', Block.hopperBlock, 'B', Item.minecartEmpty });
+ this.addRecipe(new ItemStack(Item.boat, 1), new Object[] { "# #", "###", '#', Block.planks });
+ this.addRecipe(new ItemStack(Item.bucketEmpty, 1), new Object[] { "# #", " # ", '#', Item.ingotIron });
+ this.addRecipe(new ItemStack(Item.flowerPot, 1), new Object[] { "# #", " # ", '#', Item.brick });
+ this.addRecipe(new ItemStack(Item.flintAndSteel, 1),
+ new Object[] { "A ", " B", 'A', Item.ingotIron, 'B', Item.flint });
+ this.addRecipe(new ItemStack(Item.bread, 1), new Object[] { "###", '#', Item.wheat });
+ this.addRecipe(new ItemStack(Block.stairsWoodOak, 4),
+ new Object[] { "# ", "## ", "###", '#', new ItemStack(Block.planks, 1, 0) });
+ this.addRecipe(new ItemStack(Block.stairsWoodBirch, 4),
+ new Object[] { "# ", "## ", "###", '#', new ItemStack(Block.planks, 1, 2) });
+ this.addRecipe(new ItemStack(Block.stairsWoodSpruce, 4),
+ new Object[] { "# ", "## ", "###", '#', new ItemStack(Block.planks, 1, 1) });
+ this.addRecipe(new ItemStack(Block.stairsWoodJungle, 4),
+ new Object[] { "# ", "## ", "###", '#', new ItemStack(Block.planks, 1, 3) });
+ this.addRecipe(new ItemStack(Item.fishingRod, 1),
+ new Object[] { " #", " #X", "# X", '#', Item.stick, 'X', Item.silk });
+ this.addRecipe(new ItemStack(Item.carrotOnAStick, 1),
+ new Object[] { "# ", " X", '#', Item.fishingRod, 'X', Item.carrot }).func_92100_c();
+ this.addRecipe(new ItemStack(Block.stairsCobblestone, 4),
+ new Object[] { "# ", "## ", "###", '#', Block.cobblestone });
+ this.addRecipe(new ItemStack(Block.stairsBrick, 4), new Object[] { "# ", "## ", "###", '#', Block.brick });
+ this.addRecipe(new ItemStack(Block.stairsStoneBrick, 4),
+ new Object[] { "# ", "## ", "###", '#', Block.stoneBrick });
+ this.addRecipe(new ItemStack(Block.stairsNetherBrick, 4),
+ new Object[] { "# ", "## ", "###", '#', Block.netherBrick });
+ this.addRecipe(new ItemStack(Block.stairsSandStone, 4),
+ new Object[] { "# ", "## ", "###", '#', Block.sandStone });
+ this.addRecipe(new ItemStack(Block.stairsNetherQuartz, 4),
+ new Object[] { "# ", "## ", "###", '#', Block.blockNetherQuartz });
+ this.addRecipe(new ItemStack(Item.painting, 1),
+ new Object[] { "###", "#X#", "###", '#', Item.stick, 'X', Block.cloth });
+ this.addRecipe(new ItemStack(Item.itemFrame, 1),
+ new Object[] { "###", "#X#", "###", '#', Item.stick, 'X', Item.leather });
+ this.addRecipe(new ItemStack(Item.appleGold, 1, 0),
+ new Object[] { "###", "#X#", "###", '#', Item.goldNugget, 'X', Item.appleRed });
+ this.addRecipe(new ItemStack(Item.appleGold, 1, 1),
+ new Object[] { "###", "#X#", "###", '#', Block.blockGold, 'X', Item.appleRed });
+ this.addRecipe(new ItemStack(Item.goldenCarrot, 1, 0),
+ new Object[] { "###", "#X#", "###", '#', Item.goldNugget, 'X', Item.carrot });
+ this.addRecipe(new ItemStack(Block.lever, 1),
+ new Object[] { "X", "#", '#', Block.cobblestone, 'X', Item.stick });
+ this.addRecipe(new ItemStack(Block.tripWireSource, 2),
+ new Object[] { "I", "S", "#", '#', Block.planks, 'S', Item.stick, 'I', Item.ingotIron });
+ this.addRecipe(new ItemStack(Block.torchRedstoneActive, 1),
+ new Object[] { "X", "#", '#', Item.stick, 'X', Item.redstone });
+ this.addRecipe(new ItemStack(Item.redstoneRepeater, 1),
+ new Object[] { "#X#", "III", '#', Block.torchRedstoneActive, 'X', Item.redstone, 'I', Block.stone });
+ this.addRecipe(new ItemStack(Item.comparator, 1), new Object[] { " # ", "#X#", "III", '#',
+ Block.torchRedstoneActive, 'X', Item.netherQuartz, 'I', Block.stone });
+ this.addRecipe(new ItemStack(Item.pocketSundial, 1),
+ new Object[] { " # ", "#X#", " # ", '#', Item.ingotGold, 'X', Item.redstone });
+ this.addRecipe(new ItemStack(Item.compass, 1),
+ new Object[] { " # ", "#X#", " # ", '#', Item.ingotIron, 'X', Item.redstone });
+ this.addRecipe(new ItemStack(Item.emptyMap, 1),
+ new Object[] { "###", "#X#", "###", '#', Item.paper, 'X', Item.compass });
+ this.addRecipe(new ItemStack(Block.stoneButton, 1), new Object[] { "#", '#', Block.stone });
+ this.addRecipe(new ItemStack(Block.woodenButton, 1), new Object[] { "#", '#', Block.planks });
+ this.addRecipe(new ItemStack(Block.pressurePlateStone, 1), new Object[] { "##", '#', Block.stone });
+ this.addRecipe(new ItemStack(Block.pressurePlatePlanks, 1), new Object[] { "##", '#', Block.planks });
+ this.addRecipe(new ItemStack(Block.pressurePlateIron, 1), new Object[] { "##", '#', Item.ingotIron });
+ this.addRecipe(new ItemStack(Block.pressurePlateGold, 1), new Object[] { "##", '#', Item.ingotGold });
+ this.addRecipe(new ItemStack(Block.dispenser, 1),
+ new Object[] { "###", "#X#", "#R#", '#', Block.cobblestone, 'X', Item.bow, 'R', Item.redstone });
+ this.addRecipe(new ItemStack(Block.dropper, 1),
+ new Object[] { "###", "# #", "#R#", '#', Block.cobblestone, 'R', Item.redstone });
+ this.addRecipe(new ItemStack(Block.pistonBase, 1), new Object[] { "TTT", "#X#", "#R#", '#', Block.cobblestone,
+ 'X', Item.ingotIron, 'R', Item.redstone, 'T', Block.planks });
+ this.addRecipe(new ItemStack(Block.pistonStickyBase, 1),
+ new Object[] { "S", "P", 'S', Item.slimeBall, 'P', Block.pistonBase });
+ this.addRecipe(new ItemStack(Item.bed, 1), new Object[] { "###", "XXX", '#', Block.cloth, 'X', Block.planks });
+ this.addRecipe(new ItemStack(Block.enchantmentTable, 1),
+ new Object[] { " B ", "D#D", "###", '#', Block.obsidian, 'B', Item.book, 'D', Item.diamond });
+ this.addRecipe(new ItemStack(Block.anvil, 1),
+ new Object[] { "III", " i ", "iii", 'I', Block.blockIron, 'i', Item.ingotIron });
+ this.addShapelessRecipe(new ItemStack(Item.eyeOfEnder, 1), new Object[] { Item.enderPearl, Item.blazePowder });
+ this.addShapelessRecipe(new ItemStack(Item.fireballCharge, 3),
+ new Object[] { Item.gunpowder, Item.blazePowder, Item.coal });
+ this.addShapelessRecipe(new ItemStack(Item.fireballCharge, 3),
+ new Object[] { Item.gunpowder, Item.blazePowder, new ItemStack(Item.coal, 1, 1) });
+ this.addRecipe(new ItemStack(Block.daylightSensor), new Object[] { "GGG", "QQQ", "WWW", 'G', Block.glass, 'Q',
+ Item.netherQuartz, 'W', Block.woodSingleSlab });
+ this.addRecipe(new ItemStack(Block.hopperBlock),
+ new Object[] { "I I", "ICI", " I ", 'I', Item.ingotIron, 'C', Block.chest });
+ Collections.sort(this.recipes, new RecipeSorter(this));
+ System.out.println(this.recipes.size() + " recipes");
+ }
+
+ ShapedRecipes addRecipe(ItemStack par1ItemStack, Object... par2ArrayOfObj) {
+ String var3 = "";
+ int var4 = 0;
+ int var5 = 0;
+ int var6 = 0;
+
+ if (par2ArrayOfObj[var4] instanceof String[]) {
+ String[] var7 = (String[]) ((String[]) par2ArrayOfObj[var4++]);
+
+ for (int var8 = 0; var8 < var7.length; ++var8) {
+ String var9 = var7[var8];
+ ++var6;
+ var5 = var9.length();
+ var3 = var3 + var9;
+ }
+ } else {
+ while (par2ArrayOfObj[var4] instanceof String) {
+ String var11 = (String) par2ArrayOfObj[var4++];
+ ++var6;
+ var5 = var11.length();
+ var3 = var3 + var11;
+ }
+ }
+
+ HashMap var12;
+
+ for (var12 = new HashMap(); var4 < par2ArrayOfObj.length; var4 += 2) {
+ Character var13 = (Character) par2ArrayOfObj[var4];
+ ItemStack var15 = null;
+
+ if (par2ArrayOfObj[var4 + 1] instanceof Item) {
+ var15 = new ItemStack((Item) par2ArrayOfObj[var4 + 1]);
+ } else if (par2ArrayOfObj[var4 + 1] instanceof Block) {
+ var15 = new ItemStack((Block) par2ArrayOfObj[var4 + 1], 1, 32767);
+ } else if (par2ArrayOfObj[var4 + 1] instanceof ItemStack) {
+ var15 = (ItemStack) par2ArrayOfObj[var4 + 1];
+ }
+
+ var12.put(var13, var15);
+ }
+
+ ItemStack[] var14 = new ItemStack[var5 * var6];
+
+ for (int var16 = 0; var16 < var5 * var6; ++var16) {
+ char var10 = var3.charAt(var16);
+
+ if (var12.containsKey(Character.valueOf(var10))) {
+ var14[var16] = ((ItemStack) var12.get(Character.valueOf(var10))).copy();
+ } else {
+ var14[var16] = null;
+ }
+ }
+
+ ShapedRecipes var17 = new ShapedRecipes(var5, var6, var14, par1ItemStack);
+ this.recipes.add(var17);
+ return var17;
+ }
+
+ void addShapelessRecipe(ItemStack par1ItemStack, Object... par2ArrayOfObj) {
+ ArrayList var3 = new ArrayList();
+ Object[] var4 = par2ArrayOfObj;
+ int var5 = par2ArrayOfObj.length;
+
+ for (int var6 = 0; var6 < var5; ++var6) {
+ Object var7 = var4[var6];
+
+ if (var7 instanceof ItemStack) {
+ var3.add(((ItemStack) var7).copy());
+ } else if (var7 instanceof Item) {
+ var3.add(new ItemStack((Item) var7));
+ } else {
+ if (!(var7 instanceof Block)) {
+ throw new RuntimeException("Invalid shapeless recipy!");
+ }
+
+ var3.add(new ItemStack((Block) var7));
+ }
+ }
+
+ this.recipes.add(new ShapelessRecipes(par1ItemStack, var3));
+ }
+
+ public ItemStack findMatchingRecipe(InventoryCrafting par1InventoryCrafting, World par2World) {
+ int var3 = 0;
+ ItemStack var4 = null;
+ ItemStack var5 = null;
+ int var6;
+
+ for (var6 = 0; var6 < par1InventoryCrafting.getSizeInventory(); ++var6) {
+ ItemStack var7 = par1InventoryCrafting.getStackInSlot(var6);
+
+ if (var7 != null) {
+ if (var3 == 0) {
+ var4 = var7;
+ }
+
+ if (var3 == 1) {
+ var5 = var7;
+ }
+
+ ++var3;
+ }
+ }
+
+ if (var3 == 2 && var4.itemID == var5.itemID && var4.stackSize == 1 && var5.stackSize == 1
+ && Item.itemsList[var4.itemID].isDamageable()) {
+ Item var11 = Item.itemsList[var4.itemID];
+ int var13 = var11.getMaxDamage() - var4.getItemDamageForDisplay();
+ int var8 = var11.getMaxDamage() - var5.getItemDamageForDisplay();
+ int var9 = var13 + var8 + var11.getMaxDamage() * 5 / 100;
+ int var10 = var11.getMaxDamage() - var9;
+
+ if (var10 < 0) {
+ var10 = 0;
+ }
+
+ return new ItemStack(var4.itemID, 1, var10);
+ } else {
+ for (var6 = 0; var6 < this.recipes.size(); ++var6) {
+ IRecipe var12 = (IRecipe) this.recipes.get(var6);
+
+ if (var12.matches(par1InventoryCrafting, par2World)) {
+ return var12.getCraftingResult(par1InventoryCrafting);
+ }
+ }
+
+ return null;
+ }
+ }
+
+ /**
+ * returns the List<> of all recipes
+ */
+ public List getRecipeList() {
+ return this.recipes;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/CreativeTabBlock.java b/sp-server/src/main/java/net/minecraft/src/CreativeTabBlock.java
new file mode 100644
index 0000000..5051561
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/CreativeTabBlock.java
@@ -0,0 +1,7 @@
+package net.minecraft.src;
+
+final class CreativeTabBlock extends CreativeTabs {
+ CreativeTabBlock(int par1, String par2Str) {
+ super(par1, par2Str);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/CreativeTabBrewing.java b/sp-server/src/main/java/net/minecraft/src/CreativeTabBrewing.java
new file mode 100644
index 0000000..7ca7105
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/CreativeTabBrewing.java
@@ -0,0 +1,7 @@
+package net.minecraft.src;
+
+final class CreativeTabBrewing extends CreativeTabs {
+ CreativeTabBrewing(int par1, String par2Str) {
+ super(par1, par2Str);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/CreativeTabCombat.java b/sp-server/src/main/java/net/minecraft/src/CreativeTabCombat.java
new file mode 100644
index 0000000..e4a9fb8
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/CreativeTabCombat.java
@@ -0,0 +1,7 @@
+package net.minecraft.src;
+
+final class CreativeTabCombat extends CreativeTabs {
+ CreativeTabCombat(int par1, String par2Str) {
+ super(par1, par2Str);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/CreativeTabDeco.java b/sp-server/src/main/java/net/minecraft/src/CreativeTabDeco.java
new file mode 100644
index 0000000..2ccb8de
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/CreativeTabDeco.java
@@ -0,0 +1,7 @@
+package net.minecraft.src;
+
+final class CreativeTabDeco extends CreativeTabs {
+ CreativeTabDeco(int par1, String par2Str) {
+ super(par1, par2Str);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/CreativeTabFood.java b/sp-server/src/main/java/net/minecraft/src/CreativeTabFood.java
new file mode 100644
index 0000000..50cd34a
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/CreativeTabFood.java
@@ -0,0 +1,7 @@
+package net.minecraft.src;
+
+final class CreativeTabFood extends CreativeTabs {
+ CreativeTabFood(int par1, String par2Str) {
+ super(par1, par2Str);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/CreativeTabInventory.java b/sp-server/src/main/java/net/minecraft/src/CreativeTabInventory.java
new file mode 100644
index 0000000..51cadaf
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/CreativeTabInventory.java
@@ -0,0 +1,7 @@
+package net.minecraft.src;
+
+final class CreativeTabInventory extends CreativeTabs {
+ CreativeTabInventory(int par1, String par2Str) {
+ super(par1, par2Str);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/CreativeTabMaterial.java b/sp-server/src/main/java/net/minecraft/src/CreativeTabMaterial.java
new file mode 100644
index 0000000..c672aba
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/CreativeTabMaterial.java
@@ -0,0 +1,7 @@
+package net.minecraft.src;
+
+final class CreativeTabMaterial extends CreativeTabs {
+ CreativeTabMaterial(int par1, String par2Str) {
+ super(par1, par2Str);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/CreativeTabMisc.java b/sp-server/src/main/java/net/minecraft/src/CreativeTabMisc.java
new file mode 100644
index 0000000..acaf7ad
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/CreativeTabMisc.java
@@ -0,0 +1,7 @@
+package net.minecraft.src;
+
+final class CreativeTabMisc extends CreativeTabs {
+ CreativeTabMisc(int par1, String par2Str) {
+ super(par1, par2Str);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/CreativeTabRedstone.java b/sp-server/src/main/java/net/minecraft/src/CreativeTabRedstone.java
new file mode 100644
index 0000000..41cb38c
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/CreativeTabRedstone.java
@@ -0,0 +1,7 @@
+package net.minecraft.src;
+
+final class CreativeTabRedstone extends CreativeTabs {
+ CreativeTabRedstone(int par1, String par2Str) {
+ super(par1, par2Str);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/CreativeTabSearch.java b/sp-server/src/main/java/net/minecraft/src/CreativeTabSearch.java
new file mode 100644
index 0000000..163b86d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/CreativeTabSearch.java
@@ -0,0 +1,7 @@
+package net.minecraft.src;
+
+final class CreativeTabSearch extends CreativeTabs {
+ CreativeTabSearch(int par1, String par2Str) {
+ super(par1, par2Str);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/CreativeTabTools.java b/sp-server/src/main/java/net/minecraft/src/CreativeTabTools.java
new file mode 100644
index 0000000..3724b08
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/CreativeTabTools.java
@@ -0,0 +1,7 @@
+package net.minecraft.src;
+
+final class CreativeTabTools extends CreativeTabs {
+ CreativeTabTools(int par1, String par2Str) {
+ super(par1, par2Str);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/CreativeTabTransport.java b/sp-server/src/main/java/net/minecraft/src/CreativeTabTransport.java
new file mode 100644
index 0000000..0c12643
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/CreativeTabTransport.java
@@ -0,0 +1,7 @@
+package net.minecraft.src;
+
+final class CreativeTabTransport extends CreativeTabs {
+ CreativeTabTransport(int par1, String par2Str) {
+ super(par1, par2Str);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/CreativeTabs.java b/sp-server/src/main/java/net/minecraft/src/CreativeTabs.java
new file mode 100644
index 0000000..a75ab56
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/CreativeTabs.java
@@ -0,0 +1,49 @@
+package net.minecraft.src;
+
+public class CreativeTabs {
+ public static final CreativeTabs[] creativeTabArray = new CreativeTabs[12];
+ public static final CreativeTabs tabBlock = new CreativeTabBlock(0, "buildingBlocks");
+ public static final CreativeTabs tabDecorations = new CreativeTabDeco(1, "decorations");
+ public static final CreativeTabs tabRedstone = new CreativeTabRedstone(2, "redstone");
+ public static final CreativeTabs tabTransport = new CreativeTabTransport(3, "transportation");
+ public static final CreativeTabs tabMisc = new CreativeTabMisc(4, "misc");
+ public static final CreativeTabs tabAllSearch = (new CreativeTabSearch(5, "search"))
+ .setBackgroundImageName("search.png");
+ public static final CreativeTabs tabFood = new CreativeTabFood(6, "food");
+ public static final CreativeTabs tabTools = new CreativeTabTools(7, "tools");
+ public static final CreativeTabs tabCombat = new CreativeTabCombat(8, "combat");
+ public static final CreativeTabs tabBrewing = new CreativeTabBrewing(9, "brewing");
+ public static final CreativeTabs tabMaterials = new CreativeTabMaterial(10, "materials");
+ public static final CreativeTabs tabInventory = (new CreativeTabInventory(11, "inventory"))
+ .setBackgroundImageName("survival_inv.png").setNoScrollbar().setNoTitle();
+ private final int tabIndex;
+ private final String tabLabel;
+
+ /** Texture to use. */
+ private String theTexture = "list_items.png";
+ private boolean hasScrollbar = true;
+
+ /** Whether to draw the title in the foreground of the creative GUI */
+ private boolean drawTitle = true;
+
+ public CreativeTabs(int par1, String par2Str) {
+ this.tabIndex = par1;
+ this.tabLabel = par2Str;
+ creativeTabArray[par1] = this;
+ }
+
+ public CreativeTabs setBackgroundImageName(String par1Str) {
+ this.theTexture = par1Str;
+ return this;
+ }
+
+ public CreativeTabs setNoTitle() {
+ this.drawTitle = false;
+ return this;
+ }
+
+ public CreativeTabs setNoScrollbar() {
+ this.hasScrollbar = false;
+ return this;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/DamageSource.java b/sp-server/src/main/java/net/minecraft/src/DamageSource.java
new file mode 100644
index 0000000..4b93429
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/DamageSource.java
@@ -0,0 +1,223 @@
+package net.minecraft.src;
+
+public class DamageSource {
+ public static DamageSource inFire = (new DamageSource("inFire")).setFireDamage();
+ public static DamageSource onFire = (new DamageSource("onFire")).setDamageBypassesArmor().setFireDamage();
+ public static DamageSource lava = (new DamageSource("lava")).setFireDamage();
+ public static DamageSource inWall = (new DamageSource("inWall")).setDamageBypassesArmor();
+ public static DamageSource drown = (new DamageSource("drown")).setDamageBypassesArmor();
+ public static DamageSource starve = (new DamageSource("starve")).setDamageBypassesArmor();
+ public static DamageSource cactus = new DamageSource("cactus");
+ public static DamageSource fall = (new DamageSource("fall")).setDamageBypassesArmor();
+ public static DamageSource outOfWorld = (new DamageSource("outOfWorld")).setDamageBypassesArmor()
+ .setDamageAllowedInCreativeMode();
+ public static DamageSource generic = (new DamageSource("generic")).setDamageBypassesArmor();
+ public static DamageSource magic = (new DamageSource("magic")).setDamageBypassesArmor().setMagicDamage();
+ public static DamageSource wither = (new DamageSource("wither")).setDamageBypassesArmor();
+ public static DamageSource anvil = new DamageSource("anvil");
+ public static DamageSource fallingBlock = new DamageSource("fallingBlock");
+
+ /** This kind of damage can be blocked or not. */
+ private boolean isUnblockable = false;
+ private boolean isDamageAllowedInCreativeMode = false;
+ private float hungerDamage = 0.3F;
+
+ /** This kind of damage is based on fire or not. */
+ private boolean fireDamage;
+
+ /** This kind of damage is based on a projectile or not. */
+ private boolean projectile;
+
+ /**
+ * Whether this damage source will have its damage amount scaled based on the
+ * current difficulty.
+ */
+ private boolean difficultyScaled;
+
+ /** Whether the damage is magic based. */
+ private boolean magicDamage = false;
+ private boolean explosion = false;
+ public String damageType;
+
+ public static DamageSource causeMobDamage(EntityLiving par0EntityLiving) {
+ return new EntityDamageSource("mob", par0EntityLiving);
+ }
+
+ /**
+ * returns an EntityDamageSource of type player
+ */
+ public static DamageSource causePlayerDamage(EntityPlayer par0EntityPlayer) {
+ return new EntityDamageSource("player", par0EntityPlayer);
+ }
+
+ /**
+ * returns EntityDamageSourceIndirect of an arrow
+ */
+ public static DamageSource causeArrowDamage(EntityArrow par0EntityArrow, Entity par1Entity) {
+ return (new EntityDamageSourceIndirect("arrow", par0EntityArrow, par1Entity)).setProjectile();
+ }
+
+ /**
+ * returns EntityDamageSourceIndirect of a fireball
+ */
+ public static DamageSource causeFireballDamage(EntityFireball par0EntityFireball, Entity par1Entity) {
+ return par1Entity == null
+ ? (new EntityDamageSourceIndirect("onFire", par0EntityFireball, par0EntityFireball)).setFireDamage()
+ .setProjectile()
+ : (new EntityDamageSourceIndirect("fireball", par0EntityFireball, par1Entity)).setFireDamage()
+ .setProjectile();
+ }
+
+ public static DamageSource causeThrownDamage(Entity par0Entity, Entity par1Entity) {
+ return (new EntityDamageSourceIndirect("thrown", par0Entity, par1Entity)).setProjectile();
+ }
+
+ public static DamageSource causeIndirectMagicDamage(Entity par0Entity, Entity par1Entity) {
+ return (new EntityDamageSourceIndirect("indirectMagic", par0Entity, par1Entity)).setDamageBypassesArmor()
+ .setMagicDamage();
+ }
+
+ /**
+ * Returns the EntityDamageSource of the Thorns enchantment
+ */
+ public static DamageSource causeThornsDamage(Entity par0Entity) {
+ return (new EntityDamageSource("thorns", par0Entity)).setMagicDamage();
+ }
+
+ public static DamageSource setExplosionSource(Explosion par0Explosion) {
+ return par0Explosion != null && par0Explosion.func_94613_c() != null
+ ? (new EntityDamageSource("explosion.player", par0Explosion.func_94613_c())).setDifficultyScaled()
+ .setExplosion()
+ : (new DamageSource("explosion")).setDifficultyScaled().setExplosion();
+ }
+
+ /**
+ * Returns true if the damage is projectile based.
+ */
+ public boolean isProjectile() {
+ return this.projectile;
+ }
+
+ /**
+ * Define the damage type as projectile based.
+ */
+ public DamageSource setProjectile() {
+ this.projectile = true;
+ return this;
+ }
+
+ public boolean isExplosion() {
+ return this.explosion;
+ }
+
+ public DamageSource setExplosion() {
+ this.explosion = true;
+ return this;
+ }
+
+ public boolean isUnblockable() {
+ return this.isUnblockable;
+ }
+
+ /**
+ * How much satiate(food) is consumed by this DamageSource
+ */
+ public float getHungerDamage() {
+ return this.hungerDamage;
+ }
+
+ public boolean canHarmInCreative() {
+ return this.isDamageAllowedInCreativeMode;
+ }
+
+ protected DamageSource(String par1Str) {
+ this.damageType = par1Str;
+ }
+
+ public Entity getSourceOfDamage() {
+ return this.getEntity();
+ }
+
+ public Entity getEntity() {
+ return null;
+ }
+
+ protected DamageSource setDamageBypassesArmor() {
+ this.isUnblockable = true;
+ this.hungerDamage = 0.0F;
+ return this;
+ }
+
+ protected DamageSource setDamageAllowedInCreativeMode() {
+ this.isDamageAllowedInCreativeMode = true;
+ return this;
+ }
+
+ /**
+ * Define the damage type as fire based.
+ */
+ protected DamageSource setFireDamage() {
+ this.fireDamage = true;
+ return this;
+ }
+
+ /**
+ * Returns the message to be displayed on player death.
+ */
+ public String getDeathMessage(EntityLiving par1EntityLiving) {
+ EntityLiving var2 = par1EntityLiving.func_94060_bK();
+ String var3 = "death.attack." + this.damageType;
+ String var4 = var3 + ".player";
+ return var2 != null && StatCollector.func_94522_b(var4)
+ ? StatCollector.translateToLocalFormatted(var4,
+ new Object[] { par1EntityLiving.getTranslatedEntityName(), var2.getTranslatedEntityName() })
+ : StatCollector.translateToLocalFormatted(var3,
+ new Object[] { par1EntityLiving.getTranslatedEntityName() });
+ }
+
+ /**
+ * Returns true if the damage is fire based.
+ */
+ public boolean isFireDamage() {
+ return this.fireDamage;
+ }
+
+ /**
+ * Return the name of damage type.
+ */
+ public String getDamageType() {
+ return this.damageType;
+ }
+
+ /**
+ * Set whether this damage source will have its damage amount scaled based on
+ * the current difficulty.
+ */
+ public DamageSource setDifficultyScaled() {
+ this.difficultyScaled = true;
+ return this;
+ }
+
+ /**
+ * Return whether this damage source will have its damage amount scaled based on
+ * the current difficulty.
+ */
+ public boolean isDifficultyScaled() {
+ return this.difficultyScaled;
+ }
+
+ /**
+ * Returns true if the damage is magic based.
+ */
+ public boolean isMagicDamage() {
+ return this.magicDamage;
+ }
+
+ /**
+ * Define the damage type as magic based.
+ */
+ public DamageSource setMagicDamage() {
+ this.magicDamage = true;
+ return this;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/DataWatcher.java b/sp-server/src/main/java/net/minecraft/src/DataWatcher.java
new file mode 100644
index 0000000..ed82d00
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/DataWatcher.java
@@ -0,0 +1,285 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+public class DataWatcher {
+ /** When isBlank is true the DataWatcher is not watching any objects */
+ private boolean isBlank = true;
+ private static final HashMap dataTypes = new HashMap();
+ private final Map watchedObjects = new HashMap();
+
+ /** true if one or more object was changed */
+ private boolean objectChanged;
+
+ /**
+ * adds a new object to dataWatcher to watch, to update an already existing
+ * object see updateObject. Arguments: data Value Id, Object to add
+ */
+ public void addObject(int par1, Object par2Obj) {
+ Integer var3 = (Integer) dataTypes.get(par2Obj.getClass());
+
+ if (var3 == null) {
+ throw new IllegalArgumentException("Unknown data type: " + par2Obj.getClass());
+ } else if (par1 > 31) {
+ throw new IllegalArgumentException("Data value id is too big with " + par1 + "! (Max is " + 31 + ")");
+ } else if (this.watchedObjects.containsKey(Integer.valueOf(par1))) {
+ throw new IllegalArgumentException("Duplicate id value for " + par1 + "!");
+ } else {
+ WatchableObject var4 = new WatchableObject(var3.intValue(), par1, par2Obj);
+ this.watchedObjects.put(Integer.valueOf(par1), var4);
+ this.isBlank = false;
+ }
+ }
+
+ /**
+ * Add a new object for the DataWatcher to watch, using the specified data type.
+ */
+ public void addObjectByDataType(int par1, int par2) {
+ WatchableObject var3 = new WatchableObject(par2, par1, (Object) null);
+ this.watchedObjects.put(Integer.valueOf(par1), var3);
+ this.isBlank = false;
+ }
+
+ /**
+ * gets the bytevalue of a watchable object
+ */
+ public byte getWatchableObjectByte(int par1) {
+ return ((Byte) this.getWatchedObject(par1).getObject()).byteValue();
+ }
+
+ public short getWatchableObjectShort(int par1) {
+ return ((Short) this.getWatchedObject(par1).getObject()).shortValue();
+ }
+
+ /**
+ * gets a watchable object and returns it as a Integer
+ */
+ public int getWatchableObjectInt(int par1) {
+ return ((Integer) this.getWatchedObject(par1).getObject()).intValue();
+ }
+
+ /**
+ * gets a watchable object and returns it as a String
+ */
+ public String getWatchableObjectString(int par1) {
+ return (String) this.getWatchedObject(par1).getObject();
+ }
+
+ /**
+ * Get a watchable object as an ItemStack.
+ */
+ public ItemStack getWatchableObjectItemStack(int par1) {
+ return (ItemStack) this.getWatchedObject(par1).getObject();
+ }
+
+ /**
+ * is threadsafe, unless it throws an exception, then
+ */
+ private WatchableObject getWatchedObject(int par1) {
+ WatchableObject var2 = (WatchableObject) this.watchedObjects.get(Integer.valueOf(par1));
+ return var2;
+ }
+
+ /**
+ * updates an already existing object
+ */
+ public void updateObject(int par1, Object par2Obj) {
+ WatchableObject var3 = this.getWatchedObject(par1);
+
+ if (!par2Obj.equals(var3.getObject())) {
+ var3.setObject(par2Obj);
+ var3.setWatched(true);
+ this.objectChanged = true;
+ }
+ }
+
+ public void setObjectWatched(int par1) {
+ WatchableObject.setWatchableObjectWatched(this.getWatchedObject(par1), true);
+ this.objectChanged = true;
+ }
+
+ /**
+ * true if one or more object was changed
+ */
+ public boolean hasObjectChanged() {
+ return this.objectChanged;
+ }
+
+ /**
+ * writes every object in passed list to dataoutputstream, terminated by 0x7F
+ */
+ public static void writeObjectsInListToStream(List par0List, DataOutputStream par1DataOutputStream)
+ throws IOException {
+ if (par0List != null) {
+ Iterator var2 = par0List.iterator();
+
+ while (var2.hasNext()) {
+ WatchableObject var3 = (WatchableObject) var2.next();
+ writeWatchableObject(par1DataOutputStream, var3);
+ }
+ }
+
+ par1DataOutputStream.writeByte(127);
+ }
+
+ public List unwatchAndReturnAllWatched() {
+ ArrayList var1 = null;
+
+ if (this.objectChanged) {
+ Iterator var2 = this.watchedObjects.values().iterator();
+
+ while (var2.hasNext()) {
+ WatchableObject var3 = (WatchableObject) var2.next();
+
+ if (var3.isWatched()) {
+ var3.setWatched(false);
+
+ if (var1 == null) {
+ var1 = new ArrayList();
+ }
+
+ var1.add(var3);
+ }
+ }
+ }
+
+ this.objectChanged = false;
+ return var1;
+ }
+
+ public void writeWatchableObjects(DataOutputStream par1DataOutputStream) throws IOException {
+ Iterator var2 = this.watchedObjects.values().iterator();
+
+ while (var2.hasNext()) {
+ WatchableObject var3 = (WatchableObject) var2.next();
+ writeWatchableObject(par1DataOutputStream, var3);
+ }
+
+ par1DataOutputStream.writeByte(127);
+ }
+
+ public List getAllWatched() {
+ ArrayList var1 = null;
+ WatchableObject var3;
+
+ for (Iterator var2 = this.watchedObjects.values().iterator(); var2.hasNext(); var1.add(var3)) {
+ var3 = (WatchableObject) var2.next();
+
+ if (var1 == null) {
+ var1 = new ArrayList();
+ }
+ }
+
+ return var1;
+ }
+
+ private static void writeWatchableObject(DataOutputStream par0DataOutputStream, WatchableObject par1WatchableObject)
+ throws IOException {
+ int var2 = (par1WatchableObject.getObjectType() << 5 | par1WatchableObject.getDataValueId() & 31) & 255;
+ par0DataOutputStream.writeByte(var2);
+
+ switch (par1WatchableObject.getObjectType()) {
+ case 0:
+ par0DataOutputStream.writeByte(((Byte) par1WatchableObject.getObject()).byteValue());
+ break;
+
+ case 1:
+ par0DataOutputStream.writeShort(((Short) par1WatchableObject.getObject()).shortValue());
+ break;
+
+ case 2:
+ par0DataOutputStream.writeInt(((Integer) par1WatchableObject.getObject()).intValue());
+ break;
+
+ case 3:
+ par0DataOutputStream.writeFloat(((Float) par1WatchableObject.getObject()).floatValue());
+ break;
+
+ case 4:
+ Packet.writeString((String) par1WatchableObject.getObject(), par0DataOutputStream);
+ break;
+
+ case 5:
+ ItemStack var4 = (ItemStack) par1WatchableObject.getObject();
+ Packet.writeItemStack(var4, par0DataOutputStream);
+ break;
+
+ case 6:
+ ChunkCoordinates var3 = (ChunkCoordinates) par1WatchableObject.getObject();
+ par0DataOutputStream.writeInt(var3.posX);
+ par0DataOutputStream.writeInt(var3.posY);
+ par0DataOutputStream.writeInt(var3.posZ);
+ }
+ }
+
+ public static List readWatchableObjects(DataInputStream par0DataInputStream) throws IOException {
+ ArrayList var1 = null;
+
+ for (byte var2 = par0DataInputStream.readByte(); var2 != 127; var2 = par0DataInputStream.readByte()) {
+ if (var1 == null) {
+ var1 = new ArrayList();
+ }
+
+ int var3 = (var2 & 224) >> 5;
+ int var4 = var2 & 31;
+ WatchableObject var5 = null;
+
+ switch (var3) {
+ case 0:
+ var5 = new WatchableObject(var3, var4, Byte.valueOf(par0DataInputStream.readByte()));
+ break;
+
+ case 1:
+ var5 = new WatchableObject(var3, var4, Short.valueOf(par0DataInputStream.readShort()));
+ break;
+
+ case 2:
+ var5 = new WatchableObject(var3, var4, Integer.valueOf(par0DataInputStream.readInt()));
+ break;
+
+ case 3:
+ var5 = new WatchableObject(var3, var4, Float.valueOf(par0DataInputStream.readFloat()));
+ break;
+
+ case 4:
+ var5 = new WatchableObject(var3, var4, Packet.readString(par0DataInputStream, 64));
+ break;
+
+ case 5:
+ var5 = new WatchableObject(var3, var4, Packet.readItemStack(par0DataInputStream));
+ break;
+
+ case 6:
+ int var6 = par0DataInputStream.readInt();
+ int var7 = par0DataInputStream.readInt();
+ int var8 = par0DataInputStream.readInt();
+ var5 = new WatchableObject(var3, var4, new ChunkCoordinates(var6, var7, var8));
+ }
+
+ var1.add(var5);
+ }
+
+ return var1;
+ }
+
+ public boolean getIsBlank() {
+ return this.isBlank;
+ }
+
+ static {
+ dataTypes.put(Byte.class, Integer.valueOf(0));
+ dataTypes.put(Short.class, Integer.valueOf(1));
+ dataTypes.put(Integer.class, Integer.valueOf(2));
+ dataTypes.put(Float.class, Integer.valueOf(3));
+ dataTypes.put(String.class, Integer.valueOf(4));
+ dataTypes.put(ItemStack.class, Integer.valueOf(5));
+ dataTypes.put(ChunkCoordinates.class, Integer.valueOf(6));
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/DerivedWorldInfo.java b/sp-server/src/main/java/net/minecraft/src/DerivedWorldInfo.java
new file mode 100644
index 0000000..3c14f63
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/DerivedWorldInfo.java
@@ -0,0 +1,221 @@
+package net.minecraft.src;
+
+public class DerivedWorldInfo extends WorldInfo {
+ /** Instance of WorldInfo. */
+ private final WorldInfo theWorldInfo;
+
+ public DerivedWorldInfo(WorldInfo par1WorldInfo) {
+ this.theWorldInfo = par1WorldInfo;
+ }
+
+ /**
+ * Gets the NBTTagCompound for the worldInfo
+ */
+ public NBTTagCompound getNBTTagCompound() {
+ return this.theWorldInfo.getNBTTagCompound();
+ }
+
+ /**
+ * Creates a new NBTTagCompound for the world, with the given NBTTag as the
+ * "Player"
+ */
+ public NBTTagCompound cloneNBTCompound(NBTTagCompound par1NBTTagCompound) {
+ return this.theWorldInfo.cloneNBTCompound(par1NBTTagCompound);
+ }
+
+ /**
+ * Returns the seed of current world.
+ */
+ public long getSeed() {
+ return this.theWorldInfo.getSeed();
+ }
+
+ /**
+ * Returns the x spawn position
+ */
+ public int getSpawnX() {
+ return this.theWorldInfo.getSpawnX();
+ }
+
+ /**
+ * Return the Y axis spawning point of the player.
+ */
+ public int getSpawnY() {
+ return this.theWorldInfo.getSpawnY();
+ }
+
+ /**
+ * Returns the z spawn position
+ */
+ public int getSpawnZ() {
+ return this.theWorldInfo.getSpawnZ();
+ }
+
+ public long getWorldTotalTime() {
+ return this.theWorldInfo.getWorldTotalTime();
+ }
+
+ /**
+ * Get current world time
+ */
+ public long getWorldTime() {
+ return this.theWorldInfo.getWorldTime();
+ }
+
+ /**
+ * Returns the player's NBTTagCompound to be loaded
+ */
+ public NBTTagCompound getPlayerNBTTagCompound() {
+ return this.theWorldInfo.getPlayerNBTTagCompound();
+ }
+
+ public int getDimension() {
+ return this.theWorldInfo.getDimension();
+ }
+
+ /**
+ * Get current world name
+ */
+ public String getWorldName() {
+ return this.theWorldInfo.getWorldName();
+ }
+
+ /**
+ * Returns the save version of this world
+ */
+ public int getSaveVersion() {
+ return this.theWorldInfo.getSaveVersion();
+ }
+
+ /**
+ * Returns true if it is thundering, false otherwise.
+ */
+ public boolean isThundering() {
+ return this.theWorldInfo.isThundering();
+ }
+
+ /**
+ * Returns the number of ticks until next thunderbolt.
+ */
+ public int getThunderTime() {
+ return this.theWorldInfo.getThunderTime();
+ }
+
+ /**
+ * Returns true if it is raining, false otherwise.
+ */
+ public boolean isRaining() {
+ return this.theWorldInfo.isRaining();
+ }
+
+ /**
+ * Return the number of ticks until rain.
+ */
+ public int getRainTime() {
+ return this.theWorldInfo.getRainTime();
+ }
+
+ /**
+ * Gets the GameType.
+ */
+ public EnumGameType getGameType() {
+ return this.theWorldInfo.getGameType();
+ }
+
+ public void incrementTotalWorldTime(long par1) {
+ }
+
+ /**
+ * Set current world time
+ */
+ public void setWorldTime(long par1) {
+ }
+
+ /**
+ * Sets the spawn zone position. Args: x, y, z
+ */
+ public void setSpawnPosition(int par1, int par2, int par3) {
+ }
+
+ public void setWorldName(String par1Str) {
+ }
+
+ /**
+ * Sets the save version of the world
+ */
+ public void setSaveVersion(int par1) {
+ }
+
+ /**
+ * Sets whether it is thundering or not.
+ */
+ public void setThundering(boolean par1) {
+ }
+
+ /**
+ * Defines the number of ticks until next thunderbolt.
+ */
+ public void setThunderTime(int par1) {
+ }
+
+ /**
+ * Sets whether it is raining or not.
+ */
+ public void setRaining(boolean par1) {
+ }
+
+ /**
+ * Sets the number of ticks until rain.
+ */
+ public void setRainTime(int par1) {
+ }
+
+ /**
+ * Get whether the map features (e.g. strongholds) generation is enabled or
+ * disabled.
+ */
+ public boolean isMapFeaturesEnabled() {
+ return this.theWorldInfo.isMapFeaturesEnabled();
+ }
+
+ /**
+ * Returns true if hardcore mode is enabled, otherwise false
+ */
+ public boolean isHardcoreModeEnabled() {
+ return this.theWorldInfo.isHardcoreModeEnabled();
+ }
+
+ public WorldType getTerrainType() {
+ return this.theWorldInfo.getTerrainType();
+ }
+
+ public void setTerrainType(WorldType par1WorldType) {
+ }
+
+ /**
+ * Returns true if commands are allowed on this World.
+ */
+ public boolean areCommandsAllowed() {
+ return this.theWorldInfo.areCommandsAllowed();
+ }
+
+ /**
+ * Returns true if the World is initialized.
+ */
+ public boolean isInitialized() {
+ return this.theWorldInfo.isInitialized();
+ }
+
+ /**
+ * Sets the initialization status of the World.
+ */
+ public void setServerInitialized(boolean par1) {
+ }
+
+ /**
+ * Gets the GameRules class Instance.
+ */
+ public GameRules getGameRulesInstance() {
+ return this.theWorldInfo.getGameRulesInstance();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Direction.java b/sp-server/src/main/java/net/minecraft/src/Direction.java
new file mode 100644
index 0000000..3433150
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Direction.java
@@ -0,0 +1,28 @@
+package net.minecraft.src;
+
+public class Direction {
+ public static final int[] offsetX = new int[] { 0, -1, 0, 1 };
+ public static final int[] offsetZ = new int[] { 1, 0, -1, 0 };
+ public static final String[] directions = new String[] { "SOUTH", "WEST", "NORTH", "EAST" };
+
+ /** Maps a Direction value (2D) to a Facing value (3D). */
+ public static final int[] directionToFacing = new int[] { 3, 4, 2, 5 };
+
+ /** Maps a Facing value (3D) to a Direction value (2D). */
+ public static final int[] facingToDirection = new int[] { -1, -1, 2, 0, 1, 3 };
+ public static final int[] footInvisibleFaceRemap = new int[] { 2, 3, 0, 1 };
+ public static final int[] enderEyeMetaToDirection = new int[] { 1, 2, 3, 0 };
+
+ /** Maps a direction to that to the left of it. */
+ public static final int[] rotateLeft = new int[] { 3, 0, 1, 2 };
+ public static final int[][] bedDirection = new int[][] { { 1, 0, 3, 2, 5, 4 }, { 1, 0, 5, 4, 2, 3 },
+ { 1, 0, 2, 3, 4, 5 }, { 1, 0, 4, 5, 3, 2 } };
+
+ /**
+ * Returns the movement direction from a velocity vector.
+ */
+ public static int getMovementDirection(double par0, double par2) {
+ return MathHelper.abs((float) par0) > MathHelper.abs((float) par2) ? (par0 > 0.0D ? 1 : 3)
+ : (par2 > 0.0D ? 2 : 0);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorArrow.java b/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorArrow.java
new file mode 100644
index 0000000..fe8339d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorArrow.java
@@ -0,0 +1,12 @@
+package net.minecraft.src;
+
+final class DispenserBehaviorArrow extends BehaviorProjectileDispense {
+ /**
+ * Return the projectile entity spawned by this dispense behavior.
+ */
+ protected IProjectile getProjectileEntity(World par1World, IPosition par2IPosition) {
+ EntityArrow var3 = new EntityArrow(par1World, par2IPosition.getX(), par2IPosition.getY(), par2IPosition.getZ());
+ var3.canBePickedUp = 1;
+ return var3;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorBoat.java b/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorBoat.java
new file mode 100644
index 0000000..b56ec06
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorBoat.java
@@ -0,0 +1,44 @@
+package net.minecraft.src;
+
+final class DispenserBehaviorBoat extends BehaviorDefaultDispenseItem {
+ private final BehaviorDefaultDispenseItem defaultDispenserItemBehavior = 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();
+ Material var14 = var4.getBlockMaterial(var11, var12, var13);
+ double var15;
+
+ if (Material.water.equals(var14)) {
+ var15 = 1.0D;
+ } else {
+ if (!Material.air.equals(var14) || !Material.water.equals(var4.getBlockMaterial(var11, var12 - 1, var13))) {
+ return this.defaultDispenserItemBehavior.dispense(par1IBlockSource, par2ItemStack);
+ }
+
+ var15 = 0.0D;
+ }
+
+ EntityBoat var17 = new EntityBoat(var4, var5, var7 + var15, var9);
+ 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);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorDye.java b/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorDye.java
new file mode 100644
index 0000000..6588d9d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorDye.java
@@ -0,0 +1,43 @@
+package net.minecraft.src;
+
+final class DispenserBehaviorDye extends BehaviorDefaultDispenseItem {
+ private boolean field_96461_b = true;
+
+ /**
+ * Dispense the specified stack, play the dispense sound and spawn particles.
+ */
+ protected ItemStack dispenseStack(IBlockSource par1IBlockSource, ItemStack par2ItemStack) {
+ if (par2ItemStack.getItemDamage() == 15) {
+ EnumFacing var3 = BlockDispenser.getFacing(par1IBlockSource.getBlockMetadata());
+ World var4 = par1IBlockSource.getWorld();
+ int var5 = par1IBlockSource.getXInt() + var3.getFrontOffsetX();
+ int var6 = par1IBlockSource.getYInt() + var3.getFrontOffsetY();
+ int var7 = par1IBlockSource.getZInt() + var3.getFrontOffsetZ();
+
+ if (ItemDye.func_96604_a(par2ItemStack, var4, var5, var6, var7)) {
+ if (!var4.isRemote) {
+ var4.playAuxSFX(2005, var5, var6, var7, 0);
+ }
+ } else {
+ this.field_96461_b = false;
+ }
+
+ return par2ItemStack;
+ } else {
+ return super.dispenseStack(par1IBlockSource, par2ItemStack);
+ }
+ }
+
+ /**
+ * Play the dispense sound from the specified block.
+ */
+ protected void playDispenseSound(IBlockSource par1IBlockSource) {
+ if (this.field_96461_b) {
+ par1IBlockSource.getWorld().playAuxSFX(1000, par1IBlockSource.getXInt(), par1IBlockSource.getYInt(),
+ par1IBlockSource.getZInt(), 0);
+ } else {
+ par1IBlockSource.getWorld().playAuxSFX(1001, par1IBlockSource.getXInt(), par1IBlockSource.getYInt(),
+ par1IBlockSource.getZInt(), 0);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorEgg.java b/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorEgg.java
new file mode 100644
index 0000000..81bdb97
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorEgg.java
@@ -0,0 +1,10 @@
+package net.minecraft.src;
+
+final class DispenserBehaviorEgg extends BehaviorProjectileDispense {
+ /**
+ * Return the projectile entity spawned by this dispense behavior.
+ */
+ protected IProjectile getProjectileEntity(World par1World, IPosition par2IPosition) {
+ return new EntityEgg(par1World, par2IPosition.getX(), par2IPosition.getY(), par2IPosition.getZ());
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorEmptyBucket.java b/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorEmptyBucket.java
new file mode 100644
index 0000000..d71413d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorEmptyBucket.java
@@ -0,0 +1,40 @@
+package net.minecraft.src;
+
+final class DispenserBehaviorEmptyBucket extends BehaviorDefaultDispenseItem {
+ private final BehaviorDefaultDispenseItem defaultDispenserItemBehavior = 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();
+ int var5 = par1IBlockSource.getXInt() + var3.getFrontOffsetX();
+ int var6 = par1IBlockSource.getYInt() + var3.getFrontOffsetY();
+ int var7 = par1IBlockSource.getZInt() + var3.getFrontOffsetZ();
+ Material var8 = var4.getBlockMaterial(var5, var6, var7);
+ int var9 = var4.getBlockMetadata(var5, var6, var7);
+ Item var10;
+
+ if (Material.water.equals(var8) && var9 == 0) {
+ var10 = Item.bucketWater;
+ } else {
+ if (!Material.lava.equals(var8) || var9 != 0) {
+ return super.dispenseStack(par1IBlockSource, par2ItemStack);
+ }
+
+ var10 = Item.bucketLava;
+ }
+
+ var4.setBlockToAir(var5, var6, var7);
+
+ if (--par2ItemStack.stackSize == 0) {
+ par2ItemStack.itemID = var10.itemID;
+ par2ItemStack.stackSize = 1;
+ } else if (((TileEntityDispenser) par1IBlockSource.getBlockTileEntity()).addItem(new ItemStack(var10)) < 0) {
+ this.defaultDispenserItemBehavior.dispense(par1IBlockSource, new ItemStack(var10));
+ }
+
+ return par2ItemStack;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorExperience.java b/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorExperience.java
new file mode 100644
index 0000000..3852da9
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorExperience.java
@@ -0,0 +1,18 @@
+package net.minecraft.src;
+
+final class DispenserBehaviorExperience extends BehaviorProjectileDispense {
+ /**
+ * Return the projectile entity spawned by this dispense behavior.
+ */
+ protected IProjectile getProjectileEntity(World par1World, IPosition par2IPosition) {
+ return new EntityExpBottle(par1World, par2IPosition.getX(), par2IPosition.getY(), par2IPosition.getZ());
+ }
+
+ protected float func_82498_a() {
+ return super.func_82498_a() * 0.5F;
+ }
+
+ protected float func_82500_b() {
+ return super.func_82500_b() * 1.25F;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorFilledBucket.java b/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorFilledBucket.java
new file mode 100644
index 0000000..b949311
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorFilledBucket.java
@@ -0,0 +1,25 @@
+package net.minecraft.src;
+
+final class DispenserBehaviorFilledBucket extends BehaviorDefaultDispenseItem {
+ private final BehaviorDefaultDispenseItem defaultDispenserItemBehavior = new BehaviorDefaultDispenseItem();
+
+ /**
+ * Dispense the specified stack, play the dispense sound and spawn particles.
+ */
+ public ItemStack dispenseStack(IBlockSource par1IBlockSource, ItemStack par2ItemStack) {
+ ItemBucket var3 = (ItemBucket) par2ItemStack.getItem();
+ int var4 = par1IBlockSource.getXInt();
+ int var5 = par1IBlockSource.getYInt();
+ int var6 = par1IBlockSource.getZInt();
+ EnumFacing var7 = BlockDispenser.getFacing(par1IBlockSource.getBlockMetadata());
+
+ if (var3.tryPlaceContainedLiquid(par1IBlockSource.getWorld(), (double) var4, (double) var5, (double) var6,
+ var4 + var7.getFrontOffsetX(), var5 + var7.getFrontOffsetY(), var6 + var7.getFrontOffsetZ())) {
+ par2ItemStack.itemID = Item.bucketEmpty.itemID;
+ par2ItemStack.stackSize = 1;
+ return par2ItemStack;
+ } else {
+ return this.defaultDispenserItemBehavior.dispense(par1IBlockSource, par2ItemStack);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorFire.java b/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorFire.java
new file mode 100644
index 0000000..8d90d8d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorFire.java
@@ -0,0 +1,44 @@
+package net.minecraft.src;
+
+final class DispenserBehaviorFire extends BehaviorDefaultDispenseItem {
+ private boolean field_96466_b = true;
+
+ /**
+ * Dispense the specified stack, play the dispense sound and spawn particles.
+ */
+ protected ItemStack dispenseStack(IBlockSource par1IBlockSource, ItemStack par2ItemStack) {
+ EnumFacing var3 = BlockDispenser.getFacing(par1IBlockSource.getBlockMetadata());
+ World var4 = par1IBlockSource.getWorld();
+ int var5 = par1IBlockSource.getXInt() + var3.getFrontOffsetX();
+ int var6 = par1IBlockSource.getYInt() + var3.getFrontOffsetY();
+ int var7 = par1IBlockSource.getZInt() + var3.getFrontOffsetZ();
+
+ if (var4.isAirBlock(var5, var6, var7)) {
+ var4.setBlock(var5, var6, var7, Block.fire.blockID);
+
+ if (par2ItemStack.func_96631_a(1, var4.rand)) {
+ par2ItemStack.stackSize = 0;
+ }
+ } else if (var4.getBlockId(var5, var6, var7) == Block.tnt.blockID) {
+ Block.tnt.onBlockDestroyedByPlayer(var4, var5, var6, var7, 1);
+ var4.setBlockToAir(var5, var6, var7);
+ } else {
+ this.field_96466_b = false;
+ }
+
+ return par2ItemStack;
+ }
+
+ /**
+ * Play the dispense sound from the specified block.
+ */
+ protected void playDispenseSound(IBlockSource par1IBlockSource) {
+ if (this.field_96466_b) {
+ par1IBlockSource.getWorld().playAuxSFX(1000, par1IBlockSource.getXInt(), par1IBlockSource.getYInt(),
+ par1IBlockSource.getZInt(), 0);
+ } else {
+ par1IBlockSource.getWorld().playAuxSFX(1001, par1IBlockSource.getXInt(), par1IBlockSource.getYInt(),
+ par1IBlockSource.getZInt(), 0);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorFireball.java b/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorFireball.java
new file mode 100644
index 0000000..67d2296
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorFireball.java
@@ -0,0 +1,32 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+final class DispenserBehaviorFireball extends 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());
+ IPosition var4 = BlockDispenser.getIPositionFromBlockSource(par1IBlockSource);
+ double var5 = var4.getX() + (double) ((float) var3.getFrontOffsetX() * 0.3F);
+ double var7 = var4.getY() + (double) ((float) var3.getFrontOffsetX() * 0.3F);
+ double var9 = var4.getZ() + (double) ((float) var3.getFrontOffsetZ() * 0.3F);
+ World var11 = par1IBlockSource.getWorld();
+ EaglercraftRandom var12 = var11.rand;
+ double var13 = var12.nextGaussian() * 0.05D + (double) var3.getFrontOffsetX();
+ double var15 = var12.nextGaussian() * 0.05D + (double) var3.getFrontOffsetY();
+ double var17 = var12.nextGaussian() * 0.05D + (double) var3.getFrontOffsetZ();
+ var11.spawnEntityInWorld(new EntitySmallFireball(var11, var5, var7, var9, var13, var15, var17));
+ par2ItemStack.splitStack(1);
+ return par2ItemStack;
+ }
+
+ /**
+ * Play the dispense sound from the specified block.
+ */
+ protected void playDispenseSound(IBlockSource par1IBlockSource) {
+ par1IBlockSource.getWorld().playAuxSFX(1009, par1IBlockSource.getXInt(), par1IBlockSource.getYInt(),
+ par1IBlockSource.getZInt(), 0);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorFireworks.java b/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorFireworks.java
new file mode 100644
index 0000000..a056b49
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorFireworks.java
@@ -0,0 +1,26 @@
+package net.minecraft.src;
+
+final class DispenserBehaviorFireworks extends 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());
+ double var4 = par1IBlockSource.getX() + (double) var3.getFrontOffsetX();
+ double var6 = (double) ((float) par1IBlockSource.getYInt() + 0.2F);
+ double var8 = par1IBlockSource.getZ() + (double) var3.getFrontOffsetZ();
+ EntityFireworkRocket var10 = new EntityFireworkRocket(par1IBlockSource.getWorld(), var4, var6, var8,
+ par2ItemStack);
+ par1IBlockSource.getWorld().spawnEntityInWorld(var10);
+ 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);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorMobEgg.java b/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorMobEgg.java
new file mode 100644
index 0000000..26298d6
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorMobEgg.java
@@ -0,0 +1,22 @@
+package net.minecraft.src;
+
+final class DispenserBehaviorMobEgg extends 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());
+ double var4 = par1IBlockSource.getX() + (double) var3.getFrontOffsetX();
+ double var6 = (double) ((float) par1IBlockSource.getYInt() + 0.2F);
+ double var8 = par1IBlockSource.getZ() + (double) var3.getFrontOffsetZ();
+ Entity var10 = ItemMonsterPlacer.spawnCreature(par1IBlockSource.getWorld(), par2ItemStack.getItemDamage(), var4,
+ var6, var8);
+
+ if (var10 instanceof EntityLiving && par2ItemStack.hasDisplayName()) {
+ ((EntityLiving) var10).func_94058_c(par2ItemStack.getDisplayName());
+ }
+
+ par2ItemStack.splitStack(1);
+ return par2ItemStack;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorPotion.java b/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorPotion.java
new file mode 100644
index 0000000..8538963
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorPotion.java
@@ -0,0 +1,14 @@
+package net.minecraft.src;
+
+final class DispenserBehaviorPotion implements IBehaviorDispenseItem {
+ private final BehaviorDefaultDispenseItem defaultDispenserItemBehavior = new BehaviorDefaultDispenseItem();
+
+ /**
+ * Dispenses the specified ItemStack from a dispenser.
+ */
+ public ItemStack dispense(IBlockSource par1IBlockSource, ItemStack par2ItemStack) {
+ return ItemPotion.isSplash(par2ItemStack.getItemDamage())
+ ? (new DispenserBehaviorPotionProjectile(this, par2ItemStack)).dispense(par1IBlockSource, par2ItemStack)
+ : this.defaultDispenserItemBehavior.dispense(par1IBlockSource, par2ItemStack);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorPotionProjectile.java b/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorPotionProjectile.java
new file mode 100644
index 0000000..95b44ac
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorPotionProjectile.java
@@ -0,0 +1,28 @@
+package net.minecraft.src;
+
+class DispenserBehaviorPotionProjectile extends BehaviorProjectileDispense {
+ final ItemStack potionItemStack;
+
+ final DispenserBehaviorPotion dispenserPotionBehavior;
+
+ DispenserBehaviorPotionProjectile(DispenserBehaviorPotion par1DispenserBehaviorPotion, ItemStack par2ItemStack) {
+ this.dispenserPotionBehavior = par1DispenserBehaviorPotion;
+ this.potionItemStack = par2ItemStack;
+ }
+
+ /**
+ * Return the projectile entity spawned by this dispense behavior.
+ */
+ protected IProjectile getProjectileEntity(World par1World, IPosition par2IPosition) {
+ return new EntityPotion(par1World, par2IPosition.getX(), par2IPosition.getY(), par2IPosition.getZ(),
+ this.potionItemStack.copy());
+ }
+
+ protected float func_82498_a() {
+ return super.func_82498_a() * 0.5F;
+ }
+
+ protected float func_82500_b() {
+ return super.func_82500_b() * 1.25F;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorSnowball.java b/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorSnowball.java
new file mode 100644
index 0000000..f9ffb8b
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorSnowball.java
@@ -0,0 +1,10 @@
+package net.minecraft.src;
+
+final class DispenserBehaviorSnowball extends BehaviorProjectileDispense {
+ /**
+ * Return the projectile entity spawned by this dispense behavior.
+ */
+ protected IProjectile getProjectileEntity(World par1World, IPosition par2IPosition) {
+ return new EntitySnowball(par1World, par2IPosition.getX(), par2IPosition.getY(), par2IPosition.getZ());
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorTNT.java b/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorTNT.java
new file mode 100644
index 0000000..8a35241
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/DispenserBehaviorTNT.java
@@ -0,0 +1,19 @@
+package net.minecraft.src;
+
+final class DispenserBehaviorTNT 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());
+ World var4 = par1IBlockSource.getWorld();
+ int var5 = par1IBlockSource.getXInt() + var3.getFrontOffsetX();
+ int var6 = par1IBlockSource.getYInt() + var3.getFrontOffsetY();
+ int var7 = par1IBlockSource.getZInt() + var3.getFrontOffsetZ();
+ EntityTNTPrimed var8 = new EntityTNTPrimed(var4, (double) ((float) var5 + 0.5F), (double) ((float) var6 + 0.5F),
+ (double) ((float) var7 + 0.5F), (EntityLiving) null);
+ var4.spawnEntityInWorld(var8);
+ --par2ItemStack.stackSize;
+ return par2ItemStack;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/DispenserBehaviors.java b/sp-server/src/main/java/net/minecraft/src/DispenserBehaviors.java
new file mode 100644
index 0000000..f19cf3d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/DispenserBehaviors.java
@@ -0,0 +1,28 @@
+package net.minecraft.src;
+
+public class DispenserBehaviors {
+ private static boolean hasInit = false;
+ public static void func_96467_a() {
+ if(hasInit) {
+ return;
+ }
+ BlockDispenser.dispenseBehaviorRegistry.putObject(Item.arrow, new DispenserBehaviorArrow());
+ BlockDispenser.dispenseBehaviorRegistry.putObject(Item.egg, new DispenserBehaviorEgg());
+ BlockDispenser.dispenseBehaviorRegistry.putObject(Item.snowball, new DispenserBehaviorSnowball());
+ BlockDispenser.dispenseBehaviorRegistry.putObject(Item.expBottle, new DispenserBehaviorExperience());
+ BlockDispenser.dispenseBehaviorRegistry.putObject(Item.potion, new DispenserBehaviorPotion());
+ BlockDispenser.dispenseBehaviorRegistry.putObject(Item.monsterPlacer, new DispenserBehaviorMobEgg());
+ BlockDispenser.dispenseBehaviorRegistry.putObject(Item.firework, new DispenserBehaviorFireworks());
+ BlockDispenser.dispenseBehaviorRegistry.putObject(Item.fireballCharge, new DispenserBehaviorFireball());
+ BlockDispenser.dispenseBehaviorRegistry.putObject(Item.boat, new DispenserBehaviorBoat());
+ DispenserBehaviorFilledBucket var0 = new DispenserBehaviorFilledBucket();
+ BlockDispenser.dispenseBehaviorRegistry.putObject(Item.bucketLava, var0);
+ BlockDispenser.dispenseBehaviorRegistry.putObject(Item.bucketWater, var0);
+ BlockDispenser.dispenseBehaviorRegistry.putObject(Item.bucketEmpty, new DispenserBehaviorEmptyBucket());
+ BlockDispenser.dispenseBehaviorRegistry.putObject(Item.flintAndSteel, new DispenserBehaviorFire());
+ BlockDispenser.dispenseBehaviorRegistry.putObject(Item.dyePowder, new DispenserBehaviorDye());
+ BlockDispenser.dispenseBehaviorRegistry.putObject(Item.itemsList[Block.tnt.blockID],
+ new DispenserBehaviorTNT());
+ hasInit = true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Empty3.java b/sp-server/src/main/java/net/minecraft/src/Empty3.java
new file mode 100644
index 0000000..8c4433e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Empty3.java
@@ -0,0 +1,4 @@
+package net.minecraft.src;
+
+class Empty3 {
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EmptyChunk.java b/sp-server/src/main/java/net/minecraft/src/EmptyChunk.java
new file mode 100644
index 0000000..a77c228
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EmptyChunk.java
@@ -0,0 +1,196 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class EmptyChunk extends Chunk {
+ public EmptyChunk(World par1World, int par2, int par3) {
+ super(par1World, par2, par3);
+ }
+
+ /**
+ * Checks whether the chunk is at the X/Z location specified
+ */
+ public boolean isAtLocation(int par1, int par2) {
+ return par1 == this.xPosition && par2 == this.zPosition;
+ }
+
+ /**
+ * Returns the value in the height map at this x, z coordinate in the chunk
+ */
+ public int getHeightValue(int par1, int par2) {
+ return 0;
+ }
+
+ /**
+ * Generates the initial skylight map for the chunk upon generation or load.
+ */
+ public void generateSkylightMap() {
+ }
+
+ /**
+ * Return the ID of a block in the chunk.
+ */
+ public int getBlockID(int par1, int par2, int par3) {
+ return 0;
+ }
+
+ public int getBlockLightOpacity(int par1, int par2, int par3) {
+ return 255;
+ }
+
+ /**
+ * Sets a blockID of a position within a chunk with metadata. Args: x, y, z,
+ * blockID, metadata
+ */
+ public boolean setBlockIDWithMetadata(int par1, int par2, int par3, int par4, int par5) {
+ return true;
+ }
+
+ /**
+ * Return the metadata corresponding to the given coordinates inside a chunk.
+ */
+ public int getBlockMetadata(int par1, int par2, int par3) {
+ return 0;
+ }
+
+ /**
+ * Set the metadata of a block in the chunk
+ */
+ public boolean setBlockMetadata(int par1, int par2, int par3, int par4) {
+ return false;
+ }
+
+ /**
+ * Gets the amount of light saved in this block (doesn't adjust for daylight)
+ */
+ public int getSavedLightValue(EnumSkyBlock par1EnumSkyBlock, int par2, int par3, int par4) {
+ return 0;
+ }
+
+ /**
+ * Sets the light value at the coordinate. If enumskyblock is set to sky it sets
+ * it in the skylightmap and if its a block then into the blocklightmap. Args
+ * enumSkyBlock, x, y, z, lightValue
+ */
+ public void setLightValue(EnumSkyBlock par1EnumSkyBlock, int par2, int par3, int par4, int par5) {
+ }
+
+ /**
+ * Gets the amount of light on a block taking into account sunlight
+ */
+ public int getBlockLightValue(int par1, int par2, int par3, int par4) {
+ return 0;
+ }
+
+ /**
+ * Adds an entity to the chunk. Args: entity
+ */
+ public void addEntity(Entity par1Entity) {
+ }
+
+ /**
+ * removes entity using its y chunk coordinate as its index
+ */
+ public void removeEntity(Entity par1Entity) {
+ }
+
+ /**
+ * Removes entity at the specified index from the entity array.
+ */
+ public void removeEntityAtIndex(Entity par1Entity, int par2) {
+ }
+
+ /**
+ * Returns whether is not a block above this one blocking sight to the sky (done
+ * via checking against the heightmap)
+ */
+ public boolean canBlockSeeTheSky(int par1, int par2, int par3) {
+ return false;
+ }
+
+ /**
+ * Gets the TileEntity for a given block in this chunk
+ */
+ public TileEntity getChunkBlockTileEntity(int par1, int par2, int par3) {
+ return null;
+ }
+
+ /**
+ * Adds a TileEntity to a chunk
+ */
+ public void addTileEntity(TileEntity par1TileEntity) {
+ }
+
+ /**
+ * Sets the TileEntity for a given block in this chunk
+ */
+ public void setChunkBlockTileEntity(int par1, int par2, int par3, TileEntity par4TileEntity) {
+ }
+
+ /**
+ * Removes the TileEntity for a given block in this chunk
+ */
+ public void removeChunkBlockTileEntity(int par1, int par2, int par3) {
+ }
+
+ /**
+ * Called when this Chunk is loaded by the ChunkProvider
+ */
+ public void onChunkLoad() {
+ }
+
+ /**
+ * Called when this Chunk is unloaded by the ChunkProvider
+ */
+ public void onChunkUnload() {
+ }
+
+ /**
+ * Sets the isModified flag for this Chunk
+ */
+ public void setChunkModified() {
+ }
+
+ /**
+ * Fills the given list of all entities that intersect within the given bounding
+ * box that aren't the passed entity Args: entity, aabb, listToFill
+ */
+ public void getEntitiesWithinAABBForEntity(Entity par1Entity, AxisAlignedBB par2AxisAlignedBB, List par3List,
+ IEntitySelector par4IEntitySelector) {
+ }
+
+ /**
+ * Gets all entities that can be assigned to the specified class. Args:
+ * entityClass, aabb, listToFill
+ */
+ public void getEntitiesOfTypeWithinAAAB(Class par1Class, AxisAlignedBB par2AxisAlignedBB, List par3List,
+ IEntitySelector par4IEntitySelector) {
+ }
+
+ /**
+ * Returns true if this Chunk needs to be saved
+ */
+ public boolean needsSaving(boolean par1) {
+ return false;
+ }
+
+ public EaglercraftRandom getRandomWithSeed(long par1) {
+ return new EaglercraftRandom(this.worldObj.getSeed() + (long) (this.xPosition * this.xPosition * 4987142)
+ + (long) (this.xPosition * 5947611) + (long) (this.zPosition * this.zPosition) * 4392871L
+ + (long) (this.zPosition * 389711) ^ par1);
+ }
+
+ public boolean isEmpty() {
+ return true;
+ }
+
+ /**
+ * Returns whether the ExtendedBlockStorages containing levels (in blocks) from
+ * arg 1 to arg 2 are fully empty (true) or not (false).
+ */
+ public boolean getAreLevelsEmpty(int par1, int par2) {
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Enchantment.java b/sp-server/src/main/java/net/minecraft/src/Enchantment.java
new file mode 100644
index 0000000..0d042bb
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Enchantment.java
@@ -0,0 +1,211 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+
+public abstract class Enchantment {
+ public static final Enchantment[] enchantmentsList = new Enchantment[256];
+ public static final Enchantment[] field_92090_c;
+
+ /** Converts environmental damage to armour damage */
+ public static final Enchantment protection = new EnchantmentProtection(0, 10, 0);
+
+ /** Protection against fire */
+ public static final Enchantment fireProtection = new EnchantmentProtection(1, 5, 1);
+
+ /** Less fall damage */
+ public static final Enchantment featherFalling = new EnchantmentProtection(2, 5, 2);
+
+ /** Protection against explosions */
+ public static final Enchantment blastProtection = new EnchantmentProtection(3, 2, 3);
+
+ /** Protection against projectile entities (e.g. arrows) */
+ public static final Enchantment projectileProtection = new EnchantmentProtection(4, 5, 4);
+
+ /**
+ * Decreases the rate of air loss underwater; increases time between damage
+ * while suffocating
+ */
+ public static final Enchantment respiration = new EnchantmentOxygen(5, 2);
+
+ /** Increases underwater mining rate */
+ public static final Enchantment aquaAffinity = new EnchantmentWaterWorker(6, 2);
+ public static final Enchantment thorns = new EnchantmentThorns(7, 1);
+
+ /** Extra damage to mobs */
+ public static final Enchantment sharpness = new EnchantmentDamage(16, 10, 0);
+
+ /** Extra damage to zombies, zombie pigmen and skeletons */
+ public static final Enchantment smite = new EnchantmentDamage(17, 5, 1);
+
+ /** Extra damage to spiders, cave spiders and silverfish */
+ public static final Enchantment baneOfArthropods = new EnchantmentDamage(18, 5, 2);
+
+ /** Knocks mob and players backwards upon hit */
+ public static final Enchantment knockback = new EnchantmentKnockback(19, 5);
+
+ /** Lights mobs on fire */
+ public static final Enchantment fireAspect = new EnchantmentFireAspect(20, 2);
+
+ /** Mobs have a chance to drop more loot */
+ public static final Enchantment looting = new EnchantmentLootBonus(21, 2, EnumEnchantmentType.weapon);
+
+ /** Faster resource gathering while in use */
+ public static final Enchantment efficiency = new EnchantmentDigging(32, 10);
+
+ /**
+ * Blocks mined will drop themselves, even if it should drop something else
+ * (e.g. stone will drop stone, not cobblestone)
+ */
+ public static final Enchantment silkTouch = new EnchantmentUntouching(33, 1);
+
+ /**
+ * Sometimes, the tool's durability will not be spent when the tool is used
+ */
+ public static final Enchantment unbreaking = new EnchantmentDurability(34, 5);
+
+ /** Can multiply the drop rate of items from blocks */
+ public static final Enchantment fortune = new EnchantmentLootBonus(35, 2, EnumEnchantmentType.digger);
+
+ /** Power enchantment for bows, add's extra damage to arrows. */
+ public static final Enchantment power = new EnchantmentArrowDamage(48, 10);
+
+ /**
+ * Knockback enchantments for bows, the arrows will knockback the target when
+ * hit.
+ */
+ public static final Enchantment punch = new EnchantmentArrowKnockback(49, 2);
+
+ /**
+ * Flame enchantment for bows. Arrows fired by the bow will be on fire. Any
+ * target hit will also set on fire.
+ */
+ public static final Enchantment flame = new EnchantmentArrowFire(50, 2);
+
+ /**
+ * Infinity enchantment for bows. The bow will not consume arrows anymore, but
+ * will still required at least one arrow on inventory use the bow.
+ */
+ public static final Enchantment infinity = new EnchantmentArrowInfinite(51, 1);
+ public final int effectId;
+ private final int weight;
+
+ /** The EnumEnchantmentType given to this Enchantment. */
+ public EnumEnchantmentType type;
+
+ /** Used in localisation and stats. */
+ protected String name;
+
+ protected Enchantment(int par1, int par2, EnumEnchantmentType par3EnumEnchantmentType) {
+ this.effectId = par1;
+ this.weight = par2;
+ this.type = par3EnumEnchantmentType;
+
+ if (enchantmentsList[par1] != null) {
+ throw new IllegalArgumentException("Duplicate enchantment id!");
+ } else {
+ enchantmentsList[par1] = this;
+ }
+ }
+
+ public int getWeight() {
+ return this.weight;
+ }
+
+ /**
+ * Returns the minimum level that the enchantment can have.
+ */
+ public int getMinLevel() {
+ return 1;
+ }
+
+ /**
+ * Returns the maximum level that the enchantment can have.
+ */
+ public int getMaxLevel() {
+ return 1;
+ }
+
+ /**
+ * Returns the minimal value of enchantability needed on the enchantment level
+ * passed.
+ */
+ public int getMinEnchantability(int par1) {
+ return 1 + par1 * 10;
+ }
+
+ /**
+ * Returns the maximum value of enchantability nedded on the enchantment level
+ * passed.
+ */
+ public int getMaxEnchantability(int par1) {
+ return this.getMinEnchantability(par1) + 5;
+ }
+
+ /**
+ * Calculates de damage protection of the enchantment based on level and damage
+ * source passed.
+ */
+ public int calcModifierDamage(int par1, DamageSource par2DamageSource) {
+ return 0;
+ }
+
+ /**
+ * Calculates de (magic) damage done by the enchantment on a living entity based
+ * on level and entity passed.
+ */
+ public int calcModifierLiving(int par1, EntityLiving par2EntityLiving) {
+ return 0;
+ }
+
+ /**
+ * Determines if the enchantment passed can be applyied together with this
+ * enchantment.
+ */
+ public boolean canApplyTogether(Enchantment par1Enchantment) {
+ return this != par1Enchantment;
+ }
+
+ /**
+ * Sets the enchantment name
+ */
+ public Enchantment setName(String par1Str) {
+ this.name = par1Str;
+ return this;
+ }
+
+ /**
+ * Return the name of key in translation table of this enchantment.
+ */
+ public String getName() {
+ return "enchantment." + this.name;
+ }
+
+ /**
+ * Returns the correct traslated name of the enchantment and the level in roman
+ * numbers.
+ */
+ public String getTranslatedName(int par1) {
+ String var2 = StatCollector.translateToLocal(this.getName());
+ return var2 + " " + StatCollector.translateToLocal("enchantment.level." + par1);
+ }
+
+ public boolean func_92089_a(ItemStack par1ItemStack) {
+ return this.type.canEnchantItem(par1ItemStack.getItem());
+ }
+
+ static {
+ ArrayList var0 = new ArrayList();
+ Enchantment[] var1 = enchantmentsList;
+ int var2 = var1.length;
+
+ for (int var3 = 0; var3 < var2; ++var3) {
+ Enchantment var4 = var1[var3];
+
+ if (var4 != null) {
+ var0.add(var4);
+ }
+ }
+
+ field_92090_c = (Enchantment[]) var0.toArray(new Enchantment[0]);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EnchantmentArrowDamage.java b/sp-server/src/main/java/net/minecraft/src/EnchantmentArrowDamage.java
new file mode 100644
index 0000000..7d1b531
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EnchantmentArrowDamage.java
@@ -0,0 +1,31 @@
+package net.minecraft.src;
+
+public class EnchantmentArrowDamage extends Enchantment {
+ public EnchantmentArrowDamage(int par1, int par2) {
+ super(par1, par2, EnumEnchantmentType.bow);
+ this.setName("arrowDamage");
+ }
+
+ /**
+ * Returns the minimal value of enchantability needed on the enchantment level
+ * passed.
+ */
+ public int getMinEnchantability(int par1) {
+ return 1 + (par1 - 1) * 10;
+ }
+
+ /**
+ * Returns the maximum value of enchantability nedded on the enchantment level
+ * passed.
+ */
+ public int getMaxEnchantability(int par1) {
+ return this.getMinEnchantability(par1) + 15;
+ }
+
+ /**
+ * Returns the maximum level that the enchantment can have.
+ */
+ public int getMaxLevel() {
+ return 5;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EnchantmentArrowFire.java b/sp-server/src/main/java/net/minecraft/src/EnchantmentArrowFire.java
new file mode 100644
index 0000000..71c42be
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EnchantmentArrowFire.java
@@ -0,0 +1,31 @@
+package net.minecraft.src;
+
+public class EnchantmentArrowFire extends Enchantment {
+ public EnchantmentArrowFire(int par1, int par2) {
+ super(par1, par2, EnumEnchantmentType.bow);
+ this.setName("arrowFire");
+ }
+
+ /**
+ * Returns the minimal value of enchantability needed on the enchantment level
+ * passed.
+ */
+ public int getMinEnchantability(int par1) {
+ return 20;
+ }
+
+ /**
+ * Returns the maximum value of enchantability nedded on the enchantment level
+ * passed.
+ */
+ public int getMaxEnchantability(int par1) {
+ return 50;
+ }
+
+ /**
+ * Returns the maximum level that the enchantment can have.
+ */
+ public int getMaxLevel() {
+ return 1;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EnchantmentArrowInfinite.java b/sp-server/src/main/java/net/minecraft/src/EnchantmentArrowInfinite.java
new file mode 100644
index 0000000..fe94cde
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EnchantmentArrowInfinite.java
@@ -0,0 +1,31 @@
+package net.minecraft.src;
+
+public class EnchantmentArrowInfinite extends Enchantment {
+ public EnchantmentArrowInfinite(int par1, int par2) {
+ super(par1, par2, EnumEnchantmentType.bow);
+ this.setName("arrowInfinite");
+ }
+
+ /**
+ * Returns the minimal value of enchantability needed on the enchantment level
+ * passed.
+ */
+ public int getMinEnchantability(int par1) {
+ return 20;
+ }
+
+ /**
+ * Returns the maximum value of enchantability nedded on the enchantment level
+ * passed.
+ */
+ public int getMaxEnchantability(int par1) {
+ return 50;
+ }
+
+ /**
+ * Returns the maximum level that the enchantment can have.
+ */
+ public int getMaxLevel() {
+ return 1;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EnchantmentArrowKnockback.java b/sp-server/src/main/java/net/minecraft/src/EnchantmentArrowKnockback.java
new file mode 100644
index 0000000..bf8d973
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EnchantmentArrowKnockback.java
@@ -0,0 +1,31 @@
+package net.minecraft.src;
+
+public class EnchantmentArrowKnockback extends Enchantment {
+ public EnchantmentArrowKnockback(int par1, int par2) {
+ super(par1, par2, EnumEnchantmentType.bow);
+ this.setName("arrowKnockback");
+ }
+
+ /**
+ * Returns the minimal value of enchantability needed on the enchantment level
+ * passed.
+ */
+ public int getMinEnchantability(int par1) {
+ return 12 + (par1 - 1) * 20;
+ }
+
+ /**
+ * Returns the maximum value of enchantability nedded on the enchantment level
+ * passed.
+ */
+ public int getMaxEnchantability(int par1) {
+ return this.getMinEnchantability(par1) + 25;
+ }
+
+ /**
+ * Returns the maximum level that the enchantment can have.
+ */
+ public int getMaxLevel() {
+ return 2;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EnchantmentDamage.java b/sp-server/src/main/java/net/minecraft/src/EnchantmentDamage.java
new file mode 100644
index 0000000..4b83f6b
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EnchantmentDamage.java
@@ -0,0 +1,90 @@
+package net.minecraft.src;
+
+public class EnchantmentDamage extends Enchantment {
+ /** Holds the name to be translated of each protection type. */
+ private static final String[] protectionName = new String[] { "all", "undead", "arthropods" };
+
+ /**
+ * Holds the base factor of enchantability needed to be able to use the enchant.
+ */
+ private static final int[] baseEnchantability = new int[] { 1, 5, 5 };
+
+ /**
+ * Holds how much each level increased the enchantability factor to be able to
+ * use this enchant.
+ */
+ private static final int[] levelEnchantability = new int[] { 11, 8, 8 };
+
+ /**
+ * Used on the formula of base enchantability, this is the 'window' factor of
+ * values to be able to use thing enchant.
+ */
+ private static final int[] thresholdEnchantability = new int[] { 20, 20, 20 };
+
+ /**
+ * Defines the type of damage of the enchantment, 0 = all, 1 = undead, 3 =
+ * arthropods
+ */
+ public final int damageType;
+
+ public EnchantmentDamage(int par1, int par2, int par3) {
+ super(par1, par2, EnumEnchantmentType.weapon);
+ this.damageType = par3;
+ }
+
+ /**
+ * Returns the minimal value of enchantability needed on the enchantment level
+ * passed.
+ */
+ public int getMinEnchantability(int par1) {
+ return baseEnchantability[this.damageType] + (par1 - 1) * levelEnchantability[this.damageType];
+ }
+
+ /**
+ * Returns the maximum value of enchantability nedded on the enchantment level
+ * passed.
+ */
+ public int getMaxEnchantability(int par1) {
+ return this.getMinEnchantability(par1) + thresholdEnchantability[this.damageType];
+ }
+
+ /**
+ * Returns the maximum level that the enchantment can have.
+ */
+ public int getMaxLevel() {
+ return 5;
+ }
+
+ /**
+ * Calculates de (magic) damage done by the enchantment on a living entity based
+ * on level and entity passed.
+ */
+ public int calcModifierLiving(int par1, EntityLiving par2EntityLiving) {
+ return this.damageType == 0 ? MathHelper.floor_float((float) par1 * 2.75F)
+ : (this.damageType == 1 && par2EntityLiving.getCreatureAttribute() == EnumCreatureAttribute.UNDEAD
+ ? MathHelper.floor_float((float) par1 * 4.5F)
+ : (this.damageType == 2
+ && par2EntityLiving.getCreatureAttribute() == EnumCreatureAttribute.ARTHROPOD
+ ? MathHelper.floor_float((float) par1 * 4.5F)
+ : 0));
+ }
+
+ /**
+ * Return the name of key in translation table of this enchantment.
+ */
+ public String getName() {
+ return "enchantment.damage." + protectionName[this.damageType];
+ }
+
+ /**
+ * Determines if the enchantment passed can be applyied together with this
+ * enchantment.
+ */
+ public boolean canApplyTogether(Enchantment par1Enchantment) {
+ return !(par1Enchantment instanceof EnchantmentDamage);
+ }
+
+ public boolean func_92089_a(ItemStack par1ItemStack) {
+ return par1ItemStack.getItem() instanceof ItemAxe ? true : super.func_92089_a(par1ItemStack);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EnchantmentData.java b/sp-server/src/main/java/net/minecraft/src/EnchantmentData.java
new file mode 100644
index 0000000..04b96cd
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EnchantmentData.java
@@ -0,0 +1,19 @@
+package net.minecraft.src;
+
+public class EnchantmentData extends WeightedRandomItem {
+ /** Enchantment object associated with this EnchantmentData */
+ public final Enchantment enchantmentobj;
+
+ /** Enchantment level associated with this EnchantmentData */
+ public final int enchantmentLevel;
+
+ public EnchantmentData(Enchantment par1Enchantment, int par2) {
+ super(par1Enchantment.getWeight());
+ this.enchantmentobj = par1Enchantment;
+ this.enchantmentLevel = par2;
+ }
+
+ public EnchantmentData(int par1, int par2) {
+ this(Enchantment.enchantmentsList[par1], par2);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EnchantmentDigging.java b/sp-server/src/main/java/net/minecraft/src/EnchantmentDigging.java
new file mode 100644
index 0000000..307987b
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EnchantmentDigging.java
@@ -0,0 +1,35 @@
+package net.minecraft.src;
+
+public class EnchantmentDigging extends Enchantment {
+ protected EnchantmentDigging(int par1, int par2) {
+ super(par1, par2, EnumEnchantmentType.digger);
+ this.setName("digging");
+ }
+
+ /**
+ * Returns the minimal value of enchantability needed on the enchantment level
+ * passed.
+ */
+ public int getMinEnchantability(int par1) {
+ return 1 + 10 * (par1 - 1);
+ }
+
+ /**
+ * Returns the maximum value of enchantability nedded on the enchantment level
+ * passed.
+ */
+ public int getMaxEnchantability(int par1) {
+ return super.getMinEnchantability(par1) + 50;
+ }
+
+ /**
+ * Returns the maximum level that the enchantment can have.
+ */
+ public int getMaxLevel() {
+ return 5;
+ }
+
+ public boolean func_92089_a(ItemStack par1ItemStack) {
+ return par1ItemStack.getItem().itemID == Item.shears.itemID ? true : super.func_92089_a(par1ItemStack);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EnchantmentDurability.java b/sp-server/src/main/java/net/minecraft/src/EnchantmentDurability.java
new file mode 100644
index 0000000..15b1120
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EnchantmentDurability.java
@@ -0,0 +1,42 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class EnchantmentDurability extends Enchantment {
+ protected EnchantmentDurability(int par1, int par2) {
+ super(par1, par2, EnumEnchantmentType.digger);
+ this.setName("durability");
+ }
+
+ /**
+ * Returns the minimal value of enchantability needed on the enchantment level
+ * passed.
+ */
+ public int getMinEnchantability(int par1) {
+ return 5 + (par1 - 1) * 8;
+ }
+
+ /**
+ * Returns the maximum value of enchantability nedded on the enchantment level
+ * passed.
+ */
+ public int getMaxEnchantability(int par1) {
+ return super.getMinEnchantability(par1) + 50;
+ }
+
+ /**
+ * Returns the maximum level that the enchantment can have.
+ */
+ public int getMaxLevel() {
+ return 3;
+ }
+
+ public boolean func_92089_a(ItemStack par1ItemStack) {
+ return par1ItemStack.isItemStackDamageable() ? true : super.func_92089_a(par1ItemStack);
+ }
+
+ public static boolean func_92097_a(ItemStack par0ItemStack, int par1, EaglercraftRandom par2Random) {
+ return par0ItemStack.getItem() instanceof ItemArmor && par2Random.nextFloat() < 0.6F ? false
+ : par2Random.nextInt(par1 + 1) > 0;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EnchantmentFireAspect.java b/sp-server/src/main/java/net/minecraft/src/EnchantmentFireAspect.java
new file mode 100644
index 0000000..51e4809
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EnchantmentFireAspect.java
@@ -0,0 +1,31 @@
+package net.minecraft.src;
+
+public class EnchantmentFireAspect extends Enchantment {
+ protected EnchantmentFireAspect(int par1, int par2) {
+ super(par1, par2, EnumEnchantmentType.weapon);
+ this.setName("fire");
+ }
+
+ /**
+ * Returns the minimal value of enchantability needed on the enchantment level
+ * passed.
+ */
+ public int getMinEnchantability(int par1) {
+ return 10 + 20 * (par1 - 1);
+ }
+
+ /**
+ * Returns the maximum value of enchantability nedded on the enchantment level
+ * passed.
+ */
+ public int getMaxEnchantability(int par1) {
+ return super.getMinEnchantability(par1) + 50;
+ }
+
+ /**
+ * Returns the maximum level that the enchantment can have.
+ */
+ public int getMaxLevel() {
+ return 2;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EnchantmentHelper.java b/sp-server/src/main/java/net/minecraft/src/EnchantmentHelper.java
new file mode 100644
index 0000000..987fe5d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EnchantmentHelper.java
@@ -0,0 +1,423 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class EnchantmentHelper {
+ /** Is the random seed of enchantment effects. */
+ private static final EaglercraftRandom enchantmentRand = new EaglercraftRandom();
+
+ /**
+ * Used to calculate the extra armor of enchantments on armors equipped on
+ * player.
+ */
+ private static final EnchantmentModifierDamage enchantmentModifierDamage = new EnchantmentModifierDamage(
+ (Empty3) null);
+
+ /**
+ * Used to calculate the (magic) extra damage done by enchantments on current
+ * equipped item of player.
+ */
+ private static final EnchantmentModifierLiving enchantmentModifierLiving = new EnchantmentModifierLiving(
+ (Empty3) null);
+
+ /**
+ * Returns the level of enchantment on the ItemStack passed.
+ */
+ public static int getEnchantmentLevel(int par0, ItemStack par1ItemStack) {
+ if (par1ItemStack == null) {
+ return 0;
+ } else {
+ NBTTagList var2 = par1ItemStack.getEnchantmentTagList();
+
+ if (var2 == null) {
+ return 0;
+ } else {
+ for (int var3 = 0; var3 < var2.tagCount(); ++var3) {
+ short var4 = ((NBTTagCompound) var2.tagAt(var3)).getShort("id");
+ short var5 = ((NBTTagCompound) var2.tagAt(var3)).getShort("lvl");
+
+ if (var4 == par0) {
+ return var5;
+ }
+ }
+
+ return 0;
+ }
+ }
+ }
+
+ /**
+ * Return the enchantments for the specified stack.
+ */
+ public static Map getEnchantments(ItemStack par0ItemStack) {
+ LinkedHashMap var1 = new LinkedHashMap();
+ NBTTagList var2 = par0ItemStack.itemID == Item.enchantedBook.itemID
+ ? Item.enchantedBook.func_92110_g(par0ItemStack)
+ : par0ItemStack.getEnchantmentTagList();
+
+ if (var2 != null) {
+ for (int var3 = 0; var3 < var2.tagCount(); ++var3) {
+ short var4 = ((NBTTagCompound) var2.tagAt(var3)).getShort("id");
+ short var5 = ((NBTTagCompound) var2.tagAt(var3)).getShort("lvl");
+ var1.put(Integer.valueOf(var4), Integer.valueOf(var5));
+ }
+ }
+
+ return var1;
+ }
+
+ /**
+ * Set the enchantments for the specified stack.
+ */
+ public static void setEnchantments(Map par0Map, ItemStack par1ItemStack) {
+ NBTTagList var2 = new NBTTagList();
+ Iterator var3 = par0Map.keySet().iterator();
+
+ while (var3.hasNext()) {
+ int var4 = ((Integer) var3.next()).intValue();
+ NBTTagCompound var5 = new NBTTagCompound();
+ var5.setShort("id", (short) var4);
+ var5.setShort("lvl", (short) ((Integer) par0Map.get(Integer.valueOf(var4))).intValue());
+ var2.appendTag(var5);
+
+ if (par1ItemStack.itemID == Item.enchantedBook.itemID) {
+ Item.enchantedBook.func_92115_a(par1ItemStack,
+ new EnchantmentData(var4, ((Integer) par0Map.get(Integer.valueOf(var4))).intValue()));
+ }
+ }
+
+ if (var2.tagCount() > 0) {
+ if (par1ItemStack.itemID != Item.enchantedBook.itemID) {
+ par1ItemStack.setTagInfo("ench", var2);
+ }
+ } else if (par1ItemStack.hasTagCompound()) {
+ par1ItemStack.getTagCompound().removeTag("ench");
+ }
+ }
+
+ /**
+ * Returns the biggest level of the enchantment on the array of ItemStack
+ * passed.
+ */
+ public static int getMaxEnchantmentLevel(int par0, ItemStack[] par1ArrayOfItemStack) {
+ if (par1ArrayOfItemStack == null) {
+ return 0;
+ } else {
+ int var2 = 0;
+ ItemStack[] var3 = par1ArrayOfItemStack;
+ int var4 = par1ArrayOfItemStack.length;
+
+ for (int var5 = 0; var5 < var4; ++var5) {
+ ItemStack var6 = var3[var5];
+ int var7 = getEnchantmentLevel(par0, var6);
+
+ if (var7 > var2) {
+ var2 = var7;
+ }
+ }
+
+ return var2;
+ }
+ }
+
+ /**
+ * Executes the enchantment modifier on the ItemStack passed.
+ */
+ private static void applyEnchantmentModifier(IEnchantmentModifier par0IEnchantmentModifier,
+ ItemStack par1ItemStack) {
+ if (par1ItemStack != null) {
+ NBTTagList var2 = par1ItemStack.getEnchantmentTagList();
+
+ if (var2 != null) {
+ for (int var3 = 0; var3 < var2.tagCount(); ++var3) {
+ short var4 = ((NBTTagCompound) var2.tagAt(var3)).getShort("id");
+ short var5 = ((NBTTagCompound) var2.tagAt(var3)).getShort("lvl");
+
+ if (Enchantment.enchantmentsList[var4] != null) {
+ par0IEnchantmentModifier.calculateModifier(Enchantment.enchantmentsList[var4], var5);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Executes the enchantment modifier on the array of ItemStack passed.
+ */
+ private static void applyEnchantmentModifierArray(IEnchantmentModifier par0IEnchantmentModifier,
+ ItemStack[] par1ArrayOfItemStack) {
+ ItemStack[] var2 = par1ArrayOfItemStack;
+ int var3 = par1ArrayOfItemStack.length;
+
+ for (int var4 = 0; var4 < var3; ++var4) {
+ ItemStack var5 = var2[var4];
+ applyEnchantmentModifier(par0IEnchantmentModifier, var5);
+ }
+ }
+
+ /**
+ * Returns the modifier of protection enchantments on armors equipped on player.
+ */
+ public static int getEnchantmentModifierDamage(ItemStack[] par0ArrayOfItemStack, DamageSource par1DamageSource) {
+ enchantmentModifierDamage.damageModifier = 0;
+ enchantmentModifierDamage.source = par1DamageSource;
+ applyEnchantmentModifierArray(enchantmentModifierDamage, par0ArrayOfItemStack);
+
+ if (enchantmentModifierDamage.damageModifier > 25) {
+ enchantmentModifierDamage.damageModifier = 25;
+ }
+
+ return (enchantmentModifierDamage.damageModifier + 1 >> 1)
+ + enchantmentRand.nextInt((enchantmentModifierDamage.damageModifier >> 1) + 1);
+ }
+
+ /**
+ * Return the (magic) extra damage of the enchantments on player equipped item.
+ */
+ public static int getEnchantmentModifierLiving(EntityLiving par0EntityLiving, EntityLiving par1EntityLiving) {
+ enchantmentModifierLiving.livingModifier = 0;
+ enchantmentModifierLiving.entityLiving = par1EntityLiving;
+ applyEnchantmentModifier(enchantmentModifierLiving, par0EntityLiving.getHeldItem());
+ return enchantmentModifierLiving.livingModifier > 0
+ ? 1 + enchantmentRand.nextInt(enchantmentModifierLiving.livingModifier)
+ : 0;
+ }
+
+ /**
+ * Returns the knockback value of enchantments on equipped player item.
+ */
+ public static int getKnockbackModifier(EntityLiving par0EntityLiving, EntityLiving par1EntityLiving) {
+ return getEnchantmentLevel(Enchantment.knockback.effectId, par0EntityLiving.getHeldItem());
+ }
+
+ public static int getFireAspectModifier(EntityLiving par0EntityLiving) {
+ return getEnchantmentLevel(Enchantment.fireAspect.effectId, par0EntityLiving.getHeldItem());
+ }
+
+ /**
+ * Returns the 'Water Breathing' modifier of enchantments on player equipped
+ * armors.
+ */
+ public static int getRespiration(EntityLiving par0EntityLiving) {
+ return getMaxEnchantmentLevel(Enchantment.respiration.effectId, par0EntityLiving.getInventory());
+ }
+
+ /**
+ * Return the extra efficiency of tools based on enchantments on equipped player
+ * item.
+ */
+ public static int getEfficiencyModifier(EntityLiving par0EntityLiving) {
+ return getEnchantmentLevel(Enchantment.efficiency.effectId, par0EntityLiving.getHeldItem());
+ }
+
+ /**
+ * Returns the silk touch status of enchantments on current equipped item of
+ * player.
+ */
+ public static boolean getSilkTouchModifier(EntityLiving par0EntityLiving) {
+ return getEnchantmentLevel(Enchantment.silkTouch.effectId, par0EntityLiving.getHeldItem()) > 0;
+ }
+
+ /**
+ * Returns the fortune enchantment modifier of the current equipped item of
+ * player.
+ */
+ public static int getFortuneModifier(EntityLiving par0EntityLiving) {
+ return getEnchantmentLevel(Enchantment.fortune.effectId, par0EntityLiving.getHeldItem());
+ }
+
+ /**
+ * Returns the looting enchantment modifier of the current equipped item of
+ * player.
+ */
+ public static int getLootingModifier(EntityLiving par0EntityLiving) {
+ return getEnchantmentLevel(Enchantment.looting.effectId, par0EntityLiving.getHeldItem());
+ }
+
+ /**
+ * Returns the aqua affinity status of enchantments on current equipped item of
+ * player.
+ */
+ public static boolean getAquaAffinityModifier(EntityLiving par0EntityLiving) {
+ return getMaxEnchantmentLevel(Enchantment.aquaAffinity.effectId, par0EntityLiving.getInventory()) > 0;
+ }
+
+ public static int func_92098_i(EntityLiving par0EntityLiving) {
+ return getMaxEnchantmentLevel(Enchantment.thorns.effectId, par0EntityLiving.getInventory());
+ }
+
+ public static ItemStack func_92099_a(Enchantment par0Enchantment, EntityLiving par1EntityLiving) {
+ ItemStack[] var2 = par1EntityLiving.getInventory();
+ int var3 = var2.length;
+
+ for (int var4 = 0; var4 < var3; ++var4) {
+ ItemStack var5 = var2[var4];
+
+ if (var5 != null && getEnchantmentLevel(par0Enchantment.effectId, var5) > 0) {
+ return var5;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the enchantability of itemstack, it's uses a singular formula for
+ * each index (2nd parameter: 0, 1 and 2), cutting to the max enchantability
+ * power of the table (3rd parameter)
+ */
+ public static int calcItemStackEnchantability(EaglercraftRandom par0Random, int par1, int par2, ItemStack par3ItemStack) {
+ Item var4 = par3ItemStack.getItem();
+ int var5 = var4.getItemEnchantability();
+
+ if (var5 <= 0) {
+ return 0;
+ } else {
+ if (par2 > 15) {
+ par2 = 15;
+ }
+
+ int var6 = par0Random.nextInt(8) + 1 + (par2 >> 1) + par0Random.nextInt(par2 + 1);
+ return par1 == 0 ? Math.max(var6 / 3, 1) : (par1 == 1 ? var6 * 2 / 3 + 1 : Math.max(var6, par2 * 2));
+ }
+ }
+
+ /**
+ * Adds a random enchantment to the specified item. Args: random, itemStack,
+ * enchantabilityLevel
+ */
+ public static ItemStack addRandomEnchantment(EaglercraftRandom par0Random, ItemStack par1ItemStack, int par2) {
+ List var3 = buildEnchantmentList(par0Random, par1ItemStack, par2);
+ boolean var4 = par1ItemStack.itemID == Item.book.itemID;
+
+ if (var4) {
+ par1ItemStack.itemID = Item.enchantedBook.itemID;
+ }
+
+ if (var3 != null) {
+ Iterator var5 = var3.iterator();
+
+ while (var5.hasNext()) {
+ EnchantmentData var6 = (EnchantmentData) var5.next();
+
+ if (var4) {
+ Item.enchantedBook.func_92115_a(par1ItemStack, var6);
+ } else {
+ par1ItemStack.addEnchantment(var6.enchantmentobj, var6.enchantmentLevel);
+ }
+ }
+ }
+
+ return par1ItemStack;
+ }
+
+ /**
+ * Create a list of random EnchantmentData (enchantments) that can be added
+ * together to the ItemStack, the 3rd parameter is the total enchantability
+ * level.
+ */
+ public static List buildEnchantmentList(EaglercraftRandom par0Random, ItemStack par1ItemStack, int par2) {
+ Item var3 = par1ItemStack.getItem();
+ int var4 = var3.getItemEnchantability();
+
+ if (var4 <= 0) {
+ return null;
+ } else {
+ var4 /= 2;
+ var4 = 1 + par0Random.nextInt((var4 >> 1) + 1) + par0Random.nextInt((var4 >> 1) + 1);
+ int var5 = var4 + par2;
+ float var6 = (par0Random.nextFloat() + par0Random.nextFloat() - 1.0F) * 0.15F;
+ int var7 = (int) ((float) var5 * (1.0F + var6) + 0.5F);
+
+ if (var7 < 1) {
+ var7 = 1;
+ }
+
+ ArrayList var8 = null;
+ Map var9 = mapEnchantmentData(var7, par1ItemStack);
+
+ if (var9 != null && !var9.isEmpty()) {
+ EnchantmentData var10 = (EnchantmentData) WeightedRandom.getRandomItem(par0Random, var9.values());
+
+ if (var10 != null) {
+ var8 = new ArrayList();
+ var8.add(var10);
+
+ for (int var11 = var7; par0Random.nextInt(50) <= var11; var11 >>= 1) {
+ Iterator var12 = var9.keySet().iterator();
+
+ while (var12.hasNext()) {
+ Integer var13 = (Integer) var12.next();
+ boolean var14 = true;
+ Iterator var15 = var8.iterator();
+
+ while (true) {
+ if (var15.hasNext()) {
+ EnchantmentData var16 = (EnchantmentData) var15.next();
+
+ if (var16.enchantmentobj
+ .canApplyTogether(Enchantment.enchantmentsList[var13.intValue()])) {
+ continue;
+ }
+
+ var14 = false;
+ }
+
+ if (!var14) {
+ var12.remove();
+ }
+
+ break;
+ }
+ }
+
+ if (!var9.isEmpty()) {
+ EnchantmentData var17 = (EnchantmentData) WeightedRandom.getRandomItem(par0Random,
+ var9.values());
+ var8.add(var17);
+ }
+ }
+ }
+ }
+
+ return var8;
+ }
+ }
+
+ /**
+ * Creates a 'Map' of EnchantmentData (enchantments) possible to add on the
+ * ItemStack and the enchantability level passed.
+ */
+ public static Map mapEnchantmentData(int par0, ItemStack par1ItemStack) {
+ Item var2 = par1ItemStack.getItem();
+ HashMap var3 = null;
+ boolean var4 = par1ItemStack.itemID == Item.book.itemID;
+ Enchantment[] var5 = Enchantment.enchantmentsList;
+ int var6 = var5.length;
+
+ for (int var7 = 0; var7 < var6; ++var7) {
+ Enchantment var8 = var5[var7];
+
+ if (var8 != null && (var8.type.canEnchantItem(var2) || var4)) {
+ for (int var9 = var8.getMinLevel(); var9 <= var8.getMaxLevel(); ++var9) {
+ if (par0 >= var8.getMinEnchantability(var9) && par0 <= var8.getMaxEnchantability(var9)) {
+ if (var3 == null) {
+ var3 = new HashMap();
+ }
+
+ var3.put(Integer.valueOf(var8.effectId), new EnchantmentData(var8, var9));
+ }
+ }
+ }
+ }
+
+ return var3;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EnchantmentKnockback.java b/sp-server/src/main/java/net/minecraft/src/EnchantmentKnockback.java
new file mode 100644
index 0000000..2e3bfb2
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EnchantmentKnockback.java
@@ -0,0 +1,31 @@
+package net.minecraft.src;
+
+public class EnchantmentKnockback extends Enchantment {
+ protected EnchantmentKnockback(int par1, int par2) {
+ super(par1, par2, EnumEnchantmentType.weapon);
+ this.setName("knockback");
+ }
+
+ /**
+ * Returns the minimal value of enchantability needed on the enchantment level
+ * passed.
+ */
+ public int getMinEnchantability(int par1) {
+ return 5 + 20 * (par1 - 1);
+ }
+
+ /**
+ * Returns the maximum value of enchantability nedded on the enchantment level
+ * passed.
+ */
+ public int getMaxEnchantability(int par1) {
+ return super.getMinEnchantability(par1) + 50;
+ }
+
+ /**
+ * Returns the maximum level that the enchantment can have.
+ */
+ public int getMaxLevel() {
+ return 2;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EnchantmentLootBonus.java b/sp-server/src/main/java/net/minecraft/src/EnchantmentLootBonus.java
new file mode 100644
index 0000000..f91e1da
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EnchantmentLootBonus.java
@@ -0,0 +1,43 @@
+package net.minecraft.src;
+
+public class EnchantmentLootBonus extends Enchantment {
+ protected EnchantmentLootBonus(int par1, int par2, EnumEnchantmentType par3EnumEnchantmentType) {
+ super(par1, par2, par3EnumEnchantmentType);
+ this.setName("lootBonus");
+
+ if (par3EnumEnchantmentType == EnumEnchantmentType.digger) {
+ this.setName("lootBonusDigger");
+ }
+ }
+
+ /**
+ * Returns the minimal value of enchantability needed on the enchantment level
+ * passed.
+ */
+ public int getMinEnchantability(int par1) {
+ return 15 + (par1 - 1) * 9;
+ }
+
+ /**
+ * Returns the maximum value of enchantability nedded on the enchantment level
+ * passed.
+ */
+ public int getMaxEnchantability(int par1) {
+ return super.getMinEnchantability(par1) + 50;
+ }
+
+ /**
+ * Returns the maximum level that the enchantment can have.
+ */
+ public int getMaxLevel() {
+ return 3;
+ }
+
+ /**
+ * Determines if the enchantment passed can be applyied together with this
+ * enchantment.
+ */
+ public boolean canApplyTogether(Enchantment par1Enchantment) {
+ return super.canApplyTogether(par1Enchantment) && par1Enchantment.effectId != silkTouch.effectId;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EnchantmentModifierDamage.java b/sp-server/src/main/java/net/minecraft/src/EnchantmentModifierDamage.java
new file mode 100644
index 0000000..7be4638
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EnchantmentModifierDamage.java
@@ -0,0 +1,30 @@
+package net.minecraft.src;
+
+final class EnchantmentModifierDamage implements IEnchantmentModifier {
+ /**
+ * Used to calculate the damage modifier (extra armor) on enchantments that the
+ * player have on equipped armors.
+ */
+ public int damageModifier;
+
+ /**
+ * Used as parameter to calculate the damage modifier (extra armor) on
+ * enchantments that the player have on equipped armors.
+ */
+ public DamageSource source;
+
+ private EnchantmentModifierDamage() {
+ }
+
+ /**
+ * Generic method use to calculate modifiers of offensive or defensive
+ * enchantment values.
+ */
+ public void calculateModifier(Enchantment par1Enchantment, int par2) {
+ this.damageModifier += par1Enchantment.calcModifierDamage(par2, this.source);
+ }
+
+ EnchantmentModifierDamage(Empty3 par1Empty3) {
+ this();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EnchantmentModifierLiving.java b/sp-server/src/main/java/net/minecraft/src/EnchantmentModifierLiving.java
new file mode 100644
index 0000000..883a005
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EnchantmentModifierLiving.java
@@ -0,0 +1,25 @@
+package net.minecraft.src;
+
+final class EnchantmentModifierLiving implements IEnchantmentModifier {
+ /**
+ * Used to calculate the (magic) extra damage based on enchantments of current
+ * equipped player item.
+ */
+ public int livingModifier;
+ public EntityLiving entityLiving;
+
+ private EnchantmentModifierLiving() {
+ }
+
+ /**
+ * Generic method use to calculate modifiers of offensive or defensive
+ * enchantment values.
+ */
+ public void calculateModifier(Enchantment par1Enchantment, int par2) {
+ this.livingModifier += par1Enchantment.calcModifierLiving(par2, this.entityLiving);
+ }
+
+ EnchantmentModifierLiving(Empty3 par1Empty3) {
+ this();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EnchantmentOxygen.java b/sp-server/src/main/java/net/minecraft/src/EnchantmentOxygen.java
new file mode 100644
index 0000000..4c0f1bb
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EnchantmentOxygen.java
@@ -0,0 +1,31 @@
+package net.minecraft.src;
+
+public class EnchantmentOxygen extends Enchantment {
+ public EnchantmentOxygen(int par1, int par2) {
+ super(par1, par2, EnumEnchantmentType.armor_head);
+ this.setName("oxygen");
+ }
+
+ /**
+ * Returns the minimal value of enchantability needed on the enchantment level
+ * passed.
+ */
+ public int getMinEnchantability(int par1) {
+ return 10 * par1;
+ }
+
+ /**
+ * Returns the maximum value of enchantability nedded on the enchantment level
+ * passed.
+ */
+ public int getMaxEnchantability(int par1) {
+ return this.getMinEnchantability(par1) + 30;
+ }
+
+ /**
+ * Returns the maximum level that the enchantment can have.
+ */
+ public int getMaxLevel() {
+ return 3;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EnchantmentProtection.java b/sp-server/src/main/java/net/minecraft/src/EnchantmentProtection.java
new file mode 100644
index 0000000..99ceb5e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EnchantmentProtection.java
@@ -0,0 +1,126 @@
+package net.minecraft.src;
+
+public class EnchantmentProtection extends Enchantment {
+ /** Holds the name to be translated of each protection type. */
+ private static final String[] protectionName = new String[] { "all", "fire", "fall", "explosion", "projectile" };
+
+ /**
+ * Holds the base factor of enchantability needed to be able to use the enchant.
+ */
+ private static final int[] baseEnchantability = new int[] { 1, 10, 5, 5, 3 };
+
+ /**
+ * Holds how much each level increased the enchantability factor to be able to
+ * use this enchant.
+ */
+ private static final int[] levelEnchantability = new int[] { 11, 8, 6, 8, 6 };
+
+ /**
+ * Used on the formula of base enchantability, this is the 'window' factor of
+ * values to be able to use thing enchant.
+ */
+ private static final int[] thresholdEnchantability = new int[] { 20, 12, 10, 12, 15 };
+
+ /**
+ * Defines the type of protection of the enchantment, 0 = all, 1 = fire, 2 =
+ * fall (feather fall), 3 = explosion and 4 = projectile.
+ */
+ public final int protectionType;
+
+ public EnchantmentProtection(int par1, int par2, int par3) {
+ super(par1, par2, EnumEnchantmentType.armor);
+ this.protectionType = par3;
+
+ if (par3 == 2) {
+ this.type = EnumEnchantmentType.armor_feet;
+ }
+ }
+
+ /**
+ * Returns the minimal value of enchantability needed on the enchantment level
+ * passed.
+ */
+ public int getMinEnchantability(int par1) {
+ return baseEnchantability[this.protectionType] + (par1 - 1) * levelEnchantability[this.protectionType];
+ }
+
+ /**
+ * Returns the maximum value of enchantability nedded on the enchantment level
+ * passed.
+ */
+ public int getMaxEnchantability(int par1) {
+ return this.getMinEnchantability(par1) + thresholdEnchantability[this.protectionType];
+ }
+
+ /**
+ * Returns the maximum level that the enchantment can have.
+ */
+ public int getMaxLevel() {
+ return 4;
+ }
+
+ /**
+ * Calculates de damage protection of the enchantment based on level and damage
+ * source passed.
+ */
+ public int calcModifierDamage(int par1, DamageSource par2DamageSource) {
+ if (par2DamageSource.canHarmInCreative()) {
+ return 0;
+ } else {
+ float var3 = (float) (6 + par1 * par1) / 3.0F;
+ return this.protectionType == 0 ? MathHelper.floor_float(var3 * 0.75F)
+ : (this.protectionType == 1 && par2DamageSource.isFireDamage()
+ ? MathHelper.floor_float(var3 * 1.25F)
+ : (this.protectionType == 2 && par2DamageSource == DamageSource.fall
+ ? MathHelper.floor_float(var3 * 2.5F)
+ : (this.protectionType == 3 && par2DamageSource.isExplosion()
+ ? MathHelper.floor_float(var3 * 1.5F)
+ : (this.protectionType == 4 && par2DamageSource.isProjectile()
+ ? MathHelper.floor_float(var3 * 1.5F)
+ : 0))));
+ }
+ }
+
+ /**
+ * Return the name of key in translation table of this enchantment.
+ */
+ public String getName() {
+ return "enchantment.protect." + protectionName[this.protectionType];
+ }
+
+ /**
+ * Determines if the enchantment passed can be applyied together with this
+ * enchantment.
+ */
+ public boolean canApplyTogether(Enchantment par1Enchantment) {
+ if (par1Enchantment instanceof EnchantmentProtection) {
+ EnchantmentProtection var2 = (EnchantmentProtection) par1Enchantment;
+ return var2.protectionType == this.protectionType ? false
+ : this.protectionType == 2 || var2.protectionType == 2;
+ } else {
+ return super.canApplyTogether(par1Enchantment);
+ }
+ }
+
+ public static int func_92093_a(Entity par0Entity, int par1) {
+ int var2 = EnchantmentHelper.getMaxEnchantmentLevel(Enchantment.fireProtection.effectId,
+ par0Entity.getInventory());
+
+ if (var2 > 0) {
+ par1 -= MathHelper.floor_float((float) par1 * (float) var2 * 0.15F);
+ }
+
+ return par1;
+ }
+
+ public static double func_92092_a(Entity par0Entity, double par1) {
+ int var3 = EnchantmentHelper.getMaxEnchantmentLevel(Enchantment.blastProtection.effectId,
+ par0Entity.getInventory());
+
+ if (var3 > 0) {
+ par1 -= (double) MathHelper.floor_double(par1 * (double) ((float) var3 * 0.15F));
+ }
+
+ return par1;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EnchantmentThorns.java b/sp-server/src/main/java/net/minecraft/src/EnchantmentThorns.java
new file mode 100644
index 0000000..b30f4a4
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EnchantmentThorns.java
@@ -0,0 +1,62 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class EnchantmentThorns extends Enchantment {
+ public EnchantmentThorns(int par1, int par2) {
+ super(par1, par2, EnumEnchantmentType.armor_torso);
+ this.setName("thorns");
+ }
+
+ /**
+ * Returns the minimal value of enchantability needed on the enchantment level
+ * passed.
+ */
+ public int getMinEnchantability(int par1) {
+ return 10 + 20 * (par1 - 1);
+ }
+
+ /**
+ * Returns the maximum value of enchantability nedded on the enchantment level
+ * passed.
+ */
+ public int getMaxEnchantability(int par1) {
+ return super.getMinEnchantability(par1) + 50;
+ }
+
+ /**
+ * Returns the maximum level that the enchantment can have.
+ */
+ public int getMaxLevel() {
+ return 3;
+ }
+
+ public boolean func_92089_a(ItemStack par1ItemStack) {
+ return par1ItemStack.getItem() instanceof ItemArmor ? true : super.func_92089_a(par1ItemStack);
+ }
+
+ public static boolean func_92094_a(int par0, EaglercraftRandom par1Random) {
+ return par0 <= 0 ? false : par1Random.nextFloat() < 0.15F * (float) par0;
+ }
+
+ public static int func_92095_b(int par0, EaglercraftRandom par1Random) {
+ return par0 > 10 ? par0 - 10 : 1 + par1Random.nextInt(4);
+ }
+
+ public static void func_92096_a(Entity par0Entity, EntityLiving par1EntityLiving, EaglercraftRandom par2Random) {
+ int var3 = EnchantmentHelper.func_92098_i(par1EntityLiving);
+ ItemStack var4 = EnchantmentHelper.func_92099_a(Enchantment.thorns, par1EntityLiving);
+
+ if (func_92094_a(var3, par2Random)) {
+ par0Entity.attackEntityFrom(DamageSource.causeThornsDamage(par1EntityLiving),
+ func_92095_b(var3, par2Random));
+ par0Entity.playSound("damage.thorns", 0.5F, 1.0F);
+
+ if (var4 != null) {
+ var4.damageItem(3, par1EntityLiving);
+ }
+ } else if (var4 != null) {
+ var4.damageItem(1, par1EntityLiving);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EnchantmentUntouching.java b/sp-server/src/main/java/net/minecraft/src/EnchantmentUntouching.java
new file mode 100644
index 0000000..bd53660
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EnchantmentUntouching.java
@@ -0,0 +1,43 @@
+package net.minecraft.src;
+
+public class EnchantmentUntouching extends Enchantment {
+ protected EnchantmentUntouching(int par1, int par2) {
+ super(par1, par2, EnumEnchantmentType.digger);
+ this.setName("untouching");
+ }
+
+ /**
+ * Returns the minimal value of enchantability needed on the enchantment level
+ * passed.
+ */
+ public int getMinEnchantability(int par1) {
+ return 15;
+ }
+
+ /**
+ * Returns the maximum value of enchantability nedded on the enchantment level
+ * passed.
+ */
+ public int getMaxEnchantability(int par1) {
+ return super.getMinEnchantability(par1) + 50;
+ }
+
+ /**
+ * Returns the maximum level that the enchantment can have.
+ */
+ public int getMaxLevel() {
+ return 1;
+ }
+
+ /**
+ * Determines if the enchantment passed can be applyied together with this
+ * enchantment.
+ */
+ public boolean canApplyTogether(Enchantment par1Enchantment) {
+ return super.canApplyTogether(par1Enchantment) && par1Enchantment.effectId != fortune.effectId;
+ }
+
+ public boolean func_92089_a(ItemStack par1ItemStack) {
+ return par1ItemStack.getItem().itemID == Item.shears.itemID ? true : super.func_92089_a(par1ItemStack);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EnchantmentWaterWorker.java b/sp-server/src/main/java/net/minecraft/src/EnchantmentWaterWorker.java
new file mode 100644
index 0000000..2b03536
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EnchantmentWaterWorker.java
@@ -0,0 +1,31 @@
+package net.minecraft.src;
+
+public class EnchantmentWaterWorker extends Enchantment {
+ public EnchantmentWaterWorker(int par1, int par2) {
+ super(par1, par2, EnumEnchantmentType.armor_head);
+ this.setName("waterWorker");
+ }
+
+ /**
+ * Returns the minimal value of enchantability needed on the enchantment level
+ * passed.
+ */
+ public int getMinEnchantability(int par1) {
+ return 1;
+ }
+
+ /**
+ * Returns the maximum value of enchantability nedded on the enchantment level
+ * passed.
+ */
+ public int getMaxEnchantability(int par1) {
+ return this.getMinEnchantability(par1) + 40;
+ }
+
+ /**
+ * Returns the maximum level that the enchantment can have.
+ */
+ public int getMaxLevel() {
+ return 1;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Entity.java b/sp-server/src/main/java/net/minecraft/src/Entity.java
new file mode 100644
index 0000000..4371d90
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Entity.java
@@ -0,0 +1,1946 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglerUUID;
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+import net.minecraft.server.MinecraftServer;
+
+public abstract class Entity {
+ private static int nextEntityID = 0;
+ public int entityId;
+ public double renderDistanceWeight;
+
+ /**
+ * Blocks entities from spawning when they do their AABB check to make sure the
+ * spot is clear of entities that can prevent spawning.
+ */
+ public boolean preventEntitySpawning;
+
+ /** The entity that is riding this entity */
+ public Entity riddenByEntity;
+
+ /** The entity we are currently riding */
+ public Entity ridingEntity;
+ public boolean field_98038_p;
+
+ /** Reference to the World object. */
+ public World worldObj;
+ public double prevPosX;
+ public double prevPosY;
+ public double prevPosZ;
+
+ /** Entity position X */
+ public double posX;
+
+ /** Entity position Y */
+ public double posY;
+
+ /** Entity position Z */
+ public double posZ;
+
+ /** Entity motion X */
+ public double motionX;
+
+ /** Entity motion Y */
+ public double motionY;
+
+ /** Entity motion Z */
+ public double motionZ;
+
+ /** Entity rotation Yaw */
+ public float rotationYaw;
+
+ /** Entity rotation Pitch */
+ public float rotationPitch;
+ public float prevRotationYaw;
+ public float prevRotationPitch;
+
+ /** Axis aligned bounding box. */
+ public final AxisAlignedBB boundingBox;
+ public boolean onGround;
+
+ /**
+ * True if after a move this entity has collided with something on X- or Z-axis
+ */
+ public boolean isCollidedHorizontally;
+
+ /**
+ * True if after a move this entity has collided with something on Y-axis
+ */
+ public boolean isCollidedVertically;
+
+ /**
+ * True if after a move this entity has collided with something either
+ * vertically or horizontally
+ */
+ public boolean isCollided;
+ public boolean velocityChanged;
+ protected boolean isInWeb;
+ public boolean field_70135_K;
+
+ /**
+ * gets set by setEntityDead, so this must be the flag whether an Entity is dead
+ * (inactive may be better term)
+ */
+ public boolean isDead;
+ public float yOffset;
+
+ /** How wide this entity is considered to be */
+ public float width;
+
+ /** How high this entity is considered to be */
+ public float height;
+
+ /** The previous ticks distance walked multiplied by 0.6 */
+ public float prevDistanceWalkedModified;
+
+ /** The distance walked multiplied by 0.6 */
+ public float distanceWalkedModified;
+ public float distanceWalkedOnStepModified;
+ public float fallDistance;
+
+ /**
+ * The distance that has to be exceeded in order to triger a new step sound and
+ * an onEntityWalking event on a block
+ */
+ private int nextStepDistance;
+
+ /**
+ * The entity's X coordinate at the previous tick, used to calculate position
+ * during rendering routines
+ */
+ public double lastTickPosX;
+
+ /**
+ * The entity's Y coordinate at the previous tick, used to calculate position
+ * during rendering routines
+ */
+ public double lastTickPosY;
+
+ /**
+ * The entity's Z coordinate at the previous tick, used to calculate position
+ * during rendering routines
+ */
+ public double lastTickPosZ;
+ public float ySize;
+
+ /**
+ * How high this entity can step up when running into a block to try to get over
+ * it (currently make note the entity will always step up this amount and not
+ * just the amount needed)
+ */
+ public float stepHeight;
+
+ /**
+ * Whether this entity won't clip with collision or not (make note it won't
+ * disable gravity)
+ */
+ public boolean noClip;
+
+ /**
+ * Reduces the velocity applied by entity collisions by the specified percent.
+ */
+ public float entityCollisionReduction;
+ protected EaglercraftRandom rand;
+
+ /** How many ticks has this entity had ran since being alive */
+ public int ticksExisted;
+
+ /**
+ * The amount of ticks you have to stand inside of fire before be set on fire
+ */
+ public int fireResistance;
+ private int fire;
+
+ /**
+ * Whether this entity is currently inside of water (if it handles water
+ * movement that is)
+ */
+ protected boolean inWater;
+
+ /**
+ * Remaining time an entity will be "immune" to further damage after being hurt.
+ */
+ public int hurtResistantTime;
+ private boolean firstUpdate;
+ protected boolean isImmuneToFire;
+ protected DataWatcher dataWatcher;
+ private double entityRiderPitchDelta;
+ private double entityRiderYawDelta;
+
+ /** Has this entity been added to the chunk its within */
+ public boolean addedToChunk;
+ public int chunkCoordX;
+ public int chunkCoordY;
+ public int chunkCoordZ;
+
+ /**
+ * Render entity even if it is outside the camera frustum. Only true in
+ * EntityFish for now. Used in RenderGlobal: render if ignoreFrustumCheck or in
+ * frustum.
+ */
+ public boolean ignoreFrustumCheck;
+ public boolean isAirBorne;
+ public int timeUntilPortal;
+
+ /** Whether the entity is inside a Portal */
+ protected boolean inPortal;
+ protected int timeInPortal;
+
+ /** Which dimension the player is in (-1 = the Nether, 0 = normal world) */
+ public int dimension;
+ protected int teleportDirection;
+ private boolean invulnerable;
+ protected EaglerUUID entityUniqueID;
+ public EnumEntitySize myEntitySize;
+
+ public Entity(World par1World) {
+ this.entityId = nextEntityID++;
+ this.renderDistanceWeight = 1.0D;
+ this.preventEntitySpawning = false;
+ this.boundingBox = AxisAlignedBB.getBoundingBox(0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D);
+ this.onGround = false;
+ this.isCollided = false;
+ this.velocityChanged = false;
+ this.field_70135_K = true;
+ this.isDead = false;
+ this.yOffset = 0.0F;
+ this.width = 0.6F;
+ this.height = 1.8F;
+ this.prevDistanceWalkedModified = 0.0F;
+ this.distanceWalkedModified = 0.0F;
+ this.distanceWalkedOnStepModified = 0.0F;
+ this.fallDistance = 0.0F;
+ this.nextStepDistance = 1;
+ this.ySize = 0.0F;
+ this.stepHeight = 0.0F;
+ this.noClip = false;
+ this.entityCollisionReduction = 0.0F;
+ this.rand = new EaglercraftRandom();
+ this.ticksExisted = 0;
+ this.fireResistance = 1;
+ this.fire = 0;
+ this.inWater = false;
+ this.hurtResistantTime = 0;
+ this.firstUpdate = true;
+ this.isImmuneToFire = false;
+ this.dataWatcher = new DataWatcher();
+ this.addedToChunk = false;
+ this.teleportDirection = 0;
+ this.invulnerable = false;
+ this.entityUniqueID = EaglerUUID.randomUUID();
+ this.myEntitySize = EnumEntitySize.SIZE_2;
+ this.worldObj = par1World;
+ this.setPosition(0.0D, 0.0D, 0.0D);
+
+ if (par1World != null) {
+ this.dimension = par1World.provider.dimensionId;
+ }
+
+ this.dataWatcher.addObject(0, Byte.valueOf((byte) 0));
+ this.dataWatcher.addObject(1, Short.valueOf((short) 300));
+ this.entityInit();
+ }
+
+ protected abstract void entityInit();
+
+ public DataWatcher getDataWatcher() {
+ return this.dataWatcher;
+ }
+
+ public boolean equals(Object par1Obj) {
+ return par1Obj instanceof Entity ? ((Entity) par1Obj).entityId == this.entityId : false;
+ }
+
+ public int hashCode() {
+ return this.entityId;
+ }
+
+ /**
+ * Will get destroyed next tick.
+ */
+ public void setDead() {
+ this.isDead = true;
+ }
+
+ /**
+ * Sets the width and height of the entity. Args: width, height
+ */
+ protected void setSize(float par1, float par2) {
+ if (par1 != this.width || par2 != this.height) {
+ this.width = par1;
+ this.height = par2;
+ this.boundingBox.maxX = this.boundingBox.minX + (double) this.width;
+ this.boundingBox.maxZ = this.boundingBox.minZ + (double) this.width;
+ this.boundingBox.maxY = this.boundingBox.minY + (double) this.height;
+ }
+
+ float var3 = par1 % 2.0F;
+
+ if ((double) var3 < 0.375D) {
+ this.myEntitySize = EnumEntitySize.SIZE_1;
+ } else if ((double) var3 < 0.75D) {
+ this.myEntitySize = EnumEntitySize.SIZE_2;
+ } else if ((double) var3 < 1.0D) {
+ this.myEntitySize = EnumEntitySize.SIZE_3;
+ } else if ((double) var3 < 1.375D) {
+ this.myEntitySize = EnumEntitySize.SIZE_4;
+ } else if ((double) var3 < 1.75D) {
+ this.myEntitySize = EnumEntitySize.SIZE_5;
+ } else {
+ this.myEntitySize = EnumEntitySize.SIZE_6;
+ }
+ }
+
+ /**
+ * Sets the rotation of the entity. Args: yaw, pitch (both in degrees)
+ */
+ protected void setRotation(float par1, float par2) {
+ this.rotationYaw = par1 % 360.0F;
+ this.rotationPitch = par2 % 360.0F;
+ }
+
+ /**
+ * Sets the x,y,z of the entity from the given parameters. Also seems to set up
+ * a bounding box.
+ */
+ public void setPosition(double par1, double par3, double par5) {
+ this.posX = par1;
+ this.posY = par3;
+ this.posZ = par5;
+ float var7 = this.width / 2.0F;
+ float var8 = this.height;
+ this.boundingBox.setBounds(par1 - (double) var7, par3 - (double) this.yOffset + (double) this.ySize,
+ par5 - (double) var7, par1 + (double) var7,
+ par3 - (double) this.yOffset + (double) this.ySize + (double) var8, par5 + (double) var7);
+ }
+
+ /**
+ * Called to update the entity's position/logic.
+ */
+ public void onUpdate() {
+ this.onEntityUpdate();
+ }
+
+ /**
+ * Gets called every tick from main Entity class
+ */
+ public void onEntityUpdate() {
+ if (this.ridingEntity != null && this.ridingEntity.isDead) {
+ this.ridingEntity = null;
+ }
+
+ this.prevDistanceWalkedModified = this.distanceWalkedModified;
+ this.prevPosX = this.posX;
+ this.prevPosY = this.posY;
+ this.prevPosZ = this.posZ;
+ this.prevRotationPitch = this.rotationPitch;
+ this.prevRotationYaw = this.rotationYaw;
+ int var2;
+
+ if (!this.worldObj.isRemote && this.worldObj instanceof WorldServer) {
+ MinecraftServer var1 = ((WorldServer) this.worldObj).getMinecraftServer();
+ var2 = this.getMaxInPortalTime();
+
+ if (this.inPortal) {
+ if (var1.getAllowNether()) {
+ if (this.ridingEntity == null && this.timeInPortal++ >= var2) {
+ this.timeInPortal = var2;
+ this.timeUntilPortal = this.getPortalCooldown();
+ byte var3;
+
+ if (this.worldObj.provider.dimensionId == -1) {
+ var3 = 0;
+ } else {
+ var3 = -1;
+ }
+
+ this.travelToTheEnd(var3);
+ }
+
+ this.inPortal = false;
+ }
+ } else {
+ if (this.timeInPortal > 0) {
+ this.timeInPortal -= 4;
+ }
+
+ if (this.timeInPortal < 0) {
+ this.timeInPortal = 0;
+ }
+ }
+
+ if (this.timeUntilPortal > 0) {
+ --this.timeUntilPortal;
+ }
+ }
+
+ if (this.isSprinting() && !this.isInWater()) {
+ int var5 = MathHelper.floor_double(this.posX);
+ var2 = MathHelper.floor_double(this.posY - 0.20000000298023224D - (double) this.yOffset);
+ int var6 = MathHelper.floor_double(this.posZ);
+ int var4 = this.worldObj.getBlockId(var5, var2, var6);
+
+ if (var4 > 0) {
+ this.worldObj.spawnParticle(
+ "tilecrack_" + var4 + "_" + this.worldObj.getBlockMetadata(var5, var2, var6),
+ this.posX + ((double) this.rand.nextFloat() - 0.5D) * (double) this.width,
+ this.boundingBox.minY + 0.1D,
+ this.posZ + ((double) this.rand.nextFloat() - 0.5D) * (double) this.width, -this.motionX * 4.0D,
+ 1.5D, -this.motionZ * 4.0D);
+ }
+ }
+
+ this.handleWaterMovement();
+
+ if (this.worldObj.isRemote) {
+ this.fire = 0;
+ } else if (this.fire > 0) {
+ if (this.isImmuneToFire) {
+ this.fire -= 4;
+
+ if (this.fire < 0) {
+ this.fire = 0;
+ }
+ } else {
+ if (this.fire % 20 == 0) {
+ this.attackEntityFrom(DamageSource.onFire, 1);
+ }
+
+ --this.fire;
+ }
+ }
+
+ if (this.handleLavaMovement()) {
+ this.setOnFireFromLava();
+ this.fallDistance *= 0.5F;
+ }
+
+ if (this.posY < -64.0D) {
+ this.kill();
+ }
+
+ if (!this.worldObj.isRemote) {
+ this.setFlag(0, this.fire > 0);
+ this.setFlag(2, this.ridingEntity != null);
+ }
+
+ this.firstUpdate = false;
+ }
+
+ /**
+ * Return the amount of time this entity should stay in a portal before being
+ * transported.
+ */
+ public int getMaxInPortalTime() {
+ return 0;
+ }
+
+ /**
+ * Called whenever the entity is walking inside of lava.
+ */
+ protected void setOnFireFromLava() {
+ if (!this.isImmuneToFire) {
+ this.attackEntityFrom(DamageSource.lava, 4);
+ this.setFire(15);
+ }
+ }
+
+ /**
+ * Sets entity to burn for x amount of seconds, cannot lower amount of existing
+ * fire.
+ */
+ public void setFire(int par1) {
+ int var2 = par1 * 20;
+ var2 = EnchantmentProtection.func_92093_a(this, var2);
+
+ if (this.fire < var2) {
+ this.fire = var2;
+ }
+ }
+
+ /**
+ * Removes fire from entity.
+ */
+ public void extinguish() {
+ this.fire = 0;
+ }
+
+ /**
+ * sets the dead flag. Used when you fall off the bottom of the world.
+ */
+ protected void kill() {
+ this.setDead();
+ }
+
+ /**
+ * Checks if the offset position from the entity's current position is inside of
+ * liquid. Args: x, y, z
+ */
+ public boolean isOffsetPositionInLiquid(double par1, double par3, double par5) {
+ AxisAlignedBB var7 = this.boundingBox.getOffsetBoundingBox(par1, par3, par5);
+ List var8 = this.worldObj.getCollidingBoundingBoxes(this, var7);
+ return !var8.isEmpty() ? false : !this.worldObj.isAnyLiquid(var7);
+ }
+
+ /**
+ * Tries to moves the entity by the passed in displacement. Args: x, y, z
+ */
+ public void moveEntity(double par1, double par3, double par5) {
+ if (this.noClip) {
+ this.boundingBox.offset(par1, par3, par5);
+ this.posX = (this.boundingBox.minX + this.boundingBox.maxX) / 2.0D;
+ this.posY = this.boundingBox.minY + (double) this.yOffset - (double) this.ySize;
+ this.posZ = (this.boundingBox.minZ + this.boundingBox.maxZ) / 2.0D;
+ } else {
+ this.ySize *= 0.4F;
+ double var7 = this.posX;
+ double var9 = this.posY;
+ double var11 = this.posZ;
+
+ if (this.isInWeb) {
+ this.isInWeb = false;
+ par1 *= 0.25D;
+ par3 *= 0.05000000074505806D;
+ par5 *= 0.25D;
+ this.motionX = 0.0D;
+ this.motionY = 0.0D;
+ this.motionZ = 0.0D;
+ }
+
+ double var13 = par1;
+ double var15 = par3;
+ double var17 = par5;
+ AxisAlignedBB var19 = this.boundingBox.copy();
+ boolean var20 = this.onGround && this.isSneaking() && this instanceof EntityPlayer;
+
+ if (var20) {
+ double var21;
+
+ for (var21 = 0.05D; par1 != 0.0D && this.worldObj
+ .getCollidingBoundingBoxes(this, this.boundingBox.getOffsetBoundingBox(par1, -1.0D, 0.0D))
+ .isEmpty(); var13 = par1) {
+ if (par1 < var21 && par1 >= -var21) {
+ par1 = 0.0D;
+ } else if (par1 > 0.0D) {
+ par1 -= var21;
+ } else {
+ par1 += var21;
+ }
+ }
+
+ for (; par5 != 0.0D && this.worldObj
+ .getCollidingBoundingBoxes(this, this.boundingBox.getOffsetBoundingBox(0.0D, -1.0D, par5))
+ .isEmpty(); var17 = par5) {
+ if (par5 < var21 && par5 >= -var21) {
+ par5 = 0.0D;
+ } else if (par5 > 0.0D) {
+ par5 -= var21;
+ } else {
+ par5 += var21;
+ }
+ }
+
+ while (par1 != 0.0D && par5 != 0.0D && this.worldObj
+ .getCollidingBoundingBoxes(this, this.boundingBox.getOffsetBoundingBox(par1, -1.0D, par5))
+ .isEmpty()) {
+ if (par1 < var21 && par1 >= -var21) {
+ par1 = 0.0D;
+ } else if (par1 > 0.0D) {
+ par1 -= var21;
+ } else {
+ par1 += var21;
+ }
+
+ if (par5 < var21 && par5 >= -var21) {
+ par5 = 0.0D;
+ } else if (par5 > 0.0D) {
+ par5 -= var21;
+ } else {
+ par5 += var21;
+ }
+
+ var13 = par1;
+ var17 = par5;
+ }
+ }
+
+ List var34 = this.worldObj.getCollidingBoundingBoxes(this, this.boundingBox.addCoord(par1, par3, par5));
+
+ for (int var22 = 0; var22 < var34.size(); ++var22) {
+ par3 = ((AxisAlignedBB) var34.get(var22)).calculateYOffset(this.boundingBox, par3);
+ }
+
+ this.boundingBox.offset(0.0D, par3, 0.0D);
+
+ if (!this.field_70135_K && var15 != par3) {
+ par5 = 0.0D;
+ par3 = 0.0D;
+ par1 = 0.0D;
+ }
+
+ boolean var35 = this.onGround || var15 != par3 && var15 < 0.0D;
+ int var23;
+
+ for (var23 = 0; var23 < var34.size(); ++var23) {
+ par1 = ((AxisAlignedBB) var34.get(var23)).calculateXOffset(this.boundingBox, par1);
+ }
+
+ this.boundingBox.offset(par1, 0.0D, 0.0D);
+
+ if (!this.field_70135_K && var13 != par1) {
+ par5 = 0.0D;
+ par3 = 0.0D;
+ par1 = 0.0D;
+ }
+
+ for (var23 = 0; var23 < var34.size(); ++var23) {
+ par5 = ((AxisAlignedBB) var34.get(var23)).calculateZOffset(this.boundingBox, par5);
+ }
+
+ this.boundingBox.offset(0.0D, 0.0D, par5);
+
+ if (!this.field_70135_K && var17 != par5) {
+ par5 = 0.0D;
+ par3 = 0.0D;
+ par1 = 0.0D;
+ }
+
+ double var25;
+ double var27;
+ int var30;
+ double var36;
+
+ if (this.stepHeight > 0.0F && var35 && (var20 || this.ySize < 0.05F) && (var13 != par1 || var17 != par5)) {
+ var36 = par1;
+ var25 = par3;
+ var27 = par5;
+ par1 = var13;
+ par3 = (double) this.stepHeight;
+ par5 = var17;
+ AxisAlignedBB var29 = this.boundingBox.copy();
+ this.boundingBox.setBB(var19);
+ var34 = this.worldObj.getCollidingBoundingBoxes(this, this.boundingBox.addCoord(var13, par3, var17));
+
+ for (var30 = 0; var30 < var34.size(); ++var30) {
+ par3 = ((AxisAlignedBB) var34.get(var30)).calculateYOffset(this.boundingBox, par3);
+ }
+
+ this.boundingBox.offset(0.0D, par3, 0.0D);
+
+ if (!this.field_70135_K && var15 != par3) {
+ par5 = 0.0D;
+ par3 = 0.0D;
+ par1 = 0.0D;
+ }
+
+ for (var30 = 0; var30 < var34.size(); ++var30) {
+ par1 = ((AxisAlignedBB) var34.get(var30)).calculateXOffset(this.boundingBox, par1);
+ }
+
+ this.boundingBox.offset(par1, 0.0D, 0.0D);
+
+ if (!this.field_70135_K && var13 != par1) {
+ par5 = 0.0D;
+ par3 = 0.0D;
+ par1 = 0.0D;
+ }
+
+ for (var30 = 0; var30 < var34.size(); ++var30) {
+ par5 = ((AxisAlignedBB) var34.get(var30)).calculateZOffset(this.boundingBox, par5);
+ }
+
+ this.boundingBox.offset(0.0D, 0.0D, par5);
+
+ if (!this.field_70135_K && var17 != par5) {
+ par5 = 0.0D;
+ par3 = 0.0D;
+ par1 = 0.0D;
+ }
+
+ if (!this.field_70135_K && var15 != par3) {
+ par5 = 0.0D;
+ par3 = 0.0D;
+ par1 = 0.0D;
+ } else {
+ par3 = (double) (-this.stepHeight);
+
+ for (var30 = 0; var30 < var34.size(); ++var30) {
+ par3 = ((AxisAlignedBB) var34.get(var30)).calculateYOffset(this.boundingBox, par3);
+ }
+
+ this.boundingBox.offset(0.0D, par3, 0.0D);
+ }
+
+ if (var36 * var36 + var27 * var27 >= par1 * par1 + par5 * par5) {
+ par1 = var36;
+ par3 = var25;
+ par5 = var27;
+ this.boundingBox.setBB(var29);
+ }
+ }
+
+ this.posX = (this.boundingBox.minX + this.boundingBox.maxX) / 2.0D;
+ this.posY = this.boundingBox.minY + (double) this.yOffset - (double) this.ySize;
+ this.posZ = (this.boundingBox.minZ + this.boundingBox.maxZ) / 2.0D;
+ this.isCollidedHorizontally = var13 != par1 || var17 != par5;
+ this.isCollidedVertically = var15 != par3;
+ this.onGround = var15 != par3 && var15 < 0.0D;
+ this.isCollided = this.isCollidedHorizontally || this.isCollidedVertically;
+ this.updateFallState(par3, this.onGround);
+
+ if (var13 != par1) {
+ this.motionX = 0.0D;
+ }
+
+ if (var15 != par3) {
+ this.motionY = 0.0D;
+ }
+
+ if (var17 != par5) {
+ this.motionZ = 0.0D;
+ }
+
+ var36 = this.posX - var7;
+ var25 = this.posY - var9;
+ var27 = this.posZ - var11;
+
+ if (this.canTriggerWalking() && !var20 && this.ridingEntity == null) {
+ int var37 = MathHelper.floor_double(this.posX);
+ var30 = MathHelper.floor_double(this.posY - 0.20000000298023224D - (double) this.yOffset);
+ int var31 = MathHelper.floor_double(this.posZ);
+ int var32 = this.worldObj.getBlockId(var37, var30, var31);
+
+ if (var32 == 0) {
+ int var33 = this.worldObj.blockGetRenderType(var37, var30 - 1, var31);
+
+ if (var33 == 11 || var33 == 32 || var33 == 21) {
+ var32 = this.worldObj.getBlockId(var37, var30 - 1, var31);
+ }
+ }
+
+ if (var32 != Block.ladder.blockID) {
+ var25 = 0.0D;
+ }
+
+ this.distanceWalkedModified = (float) ((double) this.distanceWalkedModified
+ + (double) MathHelper.sqrt_double(var36 * var36 + var27 * var27) * 0.6D);
+ this.distanceWalkedOnStepModified = (float) ((double) this.distanceWalkedOnStepModified
+ + (double) MathHelper.sqrt_double(var36 * var36 + var25 * var25 + var27 * var27) * 0.6D);
+
+ if (this.distanceWalkedOnStepModified > (float) this.nextStepDistance && var32 > 0) {
+ this.nextStepDistance = (int) this.distanceWalkedOnStepModified + 1;
+
+ if (this.isInWater()) {
+ float var39 = MathHelper.sqrt_double(this.motionX * this.motionX * 0.20000000298023224D
+ + this.motionY * this.motionY + this.motionZ * this.motionZ * 0.20000000298023224D)
+ * 0.35F;
+
+ if (var39 > 1.0F) {
+ var39 = 1.0F;
+ }
+
+ this.playSound("liquid.swim", var39,
+ 1.0F + (this.rand.nextFloat() - this.rand.nextFloat()) * 0.4F);
+ }
+
+ this.playStepSound(var37, var30, var31, var32);
+ Block.blocksList[var32].onEntityWalking(this.worldObj, var37, var30, var31, this);
+ }
+ }
+
+ this.doBlockCollisions();
+ boolean var38 = this.isWet();
+
+ if (this.worldObj.isBoundingBoxBurning(this.boundingBox.contract(0.001D, 0.001D, 0.001D))) {
+ this.dealFireDamage(1);
+
+ if (!var38) {
+ ++this.fire;
+
+ if (this.fire == 0) {
+ this.setFire(8);
+ }
+ }
+ } else if (this.fire <= 0) {
+ this.fire = -this.fireResistance;
+ }
+
+ if (var38 && this.fire > 0) {
+ this.playSound("random.fizz", 0.7F, 1.6F + (this.rand.nextFloat() - this.rand.nextFloat()) * 0.4F);
+ this.fire = -this.fireResistance;
+ }
+ }
+ }
+
+ /**
+ * Checks for block collisions, and calls the associated onBlockCollided method
+ * for the collided block.
+ */
+ protected void doBlockCollisions() {
+ int var1 = MathHelper.floor_double(this.boundingBox.minX + 0.001D);
+ int var2 = MathHelper.floor_double(this.boundingBox.minY + 0.001D);
+ int var3 = MathHelper.floor_double(this.boundingBox.minZ + 0.001D);
+ int var4 = MathHelper.floor_double(this.boundingBox.maxX - 0.001D);
+ int var5 = MathHelper.floor_double(this.boundingBox.maxY - 0.001D);
+ int var6 = MathHelper.floor_double(this.boundingBox.maxZ - 0.001D);
+
+ if (this.worldObj.checkChunksExist(var1, var2, var3, var4, var5, var6)) {
+ for (int var7 = var1; var7 <= var4; ++var7) {
+ for (int var8 = var2; var8 <= var5; ++var8) {
+ for (int var9 = var3; var9 <= var6; ++var9) {
+ int var10 = this.worldObj.getBlockId(var7, var8, var9);
+
+ if (var10 > 0) {
+ Block.blocksList[var10].onEntityCollidedWithBlock(this.worldObj, var7, var8, var9, this);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Plays step sound at given x, y, z for the entity
+ */
+ protected void playStepSound(int par1, int par2, int par3, int par4) {
+ StepSound var5 = Block.blocksList[par4].stepSound;
+
+ if (this.worldObj.getBlockId(par1, par2 + 1, par3) == Block.snow.blockID) {
+ var5 = Block.snow.stepSound;
+ this.playSound(var5.getStepSound(), var5.getVolume() * 0.15F, var5.getPitch());
+ } else if (!Block.blocksList[par4].blockMaterial.isLiquid()) {
+ this.playSound(var5.getStepSound(), var5.getVolume() * 0.15F, var5.getPitch());
+ }
+ }
+
+ public void playSound(String par1Str, float par2, float par3) {
+ this.worldObj.playSoundAtEntity(this, par1Str, par2, par3);
+ }
+
+ /**
+ * returns if this entity triggers Block.onEntityWalking on the blocks they walk
+ * on. used for spiders and wolves to prevent them from trampling crops
+ */
+ protected boolean canTriggerWalking() {
+ return true;
+ }
+
+ /**
+ * Takes in the distance the entity has fallen this tick and whether its on the
+ * ground to update the fall distance and deal fall damage if landing on the
+ * ground. Args: distanceFallenThisTick, onGround
+ */
+ protected void updateFallState(double par1, boolean par3) {
+ if (par3) {
+ if (this.fallDistance > 0.0F) {
+ this.fall(this.fallDistance);
+ this.fallDistance = 0.0F;
+ }
+ } else if (par1 < 0.0D) {
+ this.fallDistance = (float) ((double) this.fallDistance - par1);
+ }
+ }
+
+ /**
+ * returns the bounding box for this entity
+ */
+ public AxisAlignedBB getBoundingBox() {
+ return null;
+ }
+
+ /**
+ * Will deal the specified amount of damage to the entity if the entity isn't
+ * immune to fire damage. Args: amountDamage
+ */
+ protected void dealFireDamage(int par1) {
+ if (!this.isImmuneToFire) {
+ this.attackEntityFrom(DamageSource.inFire, par1);
+ }
+ }
+
+ public final boolean isImmuneToFire() {
+ return this.isImmuneToFire;
+ }
+
+ /**
+ * Called when the mob is falling. Calculates and applies fall damage.
+ */
+ protected void fall(float par1) {
+ if (this.riddenByEntity != null) {
+ this.riddenByEntity.fall(par1);
+ }
+ }
+
+ /**
+ * Checks if this entity is either in water or on an open air block in rain
+ * (used in wolves).
+ */
+ public boolean isWet() {
+ return this.inWater
+ || this.worldObj.canLightningStrikeAt(MathHelper.floor_double(this.posX),
+ MathHelper.floor_double(this.posY), MathHelper.floor_double(this.posZ))
+ || this.worldObj.canLightningStrikeAt(MathHelper.floor_double(this.posX),
+ MathHelper.floor_double(this.posY + (double) this.height), MathHelper.floor_double(this.posZ));
+ }
+
+ /**
+ * Checks if this entity is inside water (if inWater field is true as a result
+ * of handleWaterMovement() returning true)
+ */
+ public boolean isInWater() {
+ return this.inWater;
+ }
+
+ /**
+ * Returns if this entity is in water and will end up adding the waters velocity
+ * to the entity
+ */
+ public boolean handleWaterMovement() {
+ if (this.worldObj.handleMaterialAcceleration(
+ this.boundingBox.expand(0.0D, -0.4000000059604645D, 0.0D).contract(0.001D, 0.001D, 0.001D),
+ Material.water, this)) {
+ if (!this.inWater && !this.firstUpdate) {
+ float var1 = MathHelper.sqrt_double(this.motionX * this.motionX * 0.20000000298023224D
+ + this.motionY * this.motionY + this.motionZ * this.motionZ * 0.20000000298023224D) * 0.2F;
+
+ if (var1 > 1.0F) {
+ var1 = 1.0F;
+ }
+
+ this.playSound("liquid.splash", var1, 1.0F + (this.rand.nextFloat() - this.rand.nextFloat()) * 0.4F);
+ float var2 = (float) MathHelper.floor_double(this.boundingBox.minY);
+ int var3;
+ float var4;
+ float var5;
+
+ for (var3 = 0; (float) var3 < 1.0F + this.width * 20.0F; ++var3) {
+ var4 = (this.rand.nextFloat() * 2.0F - 1.0F) * this.width;
+ var5 = (this.rand.nextFloat() * 2.0F - 1.0F) * this.width;
+ this.worldObj.spawnParticle("bubble", this.posX + (double) var4, (double) (var2 + 1.0F),
+ this.posZ + (double) var5, this.motionX,
+ this.motionY - (double) (this.rand.nextFloat() * 0.2F), this.motionZ);
+ }
+
+ for (var3 = 0; (float) var3 < 1.0F + this.width * 20.0F; ++var3) {
+ var4 = (this.rand.nextFloat() * 2.0F - 1.0F) * this.width;
+ var5 = (this.rand.nextFloat() * 2.0F - 1.0F) * this.width;
+ this.worldObj.spawnParticle("splash", this.posX + (double) var4, (double) (var2 + 1.0F),
+ this.posZ + (double) var5, this.motionX, this.motionY, this.motionZ);
+ }
+ }
+
+ this.fallDistance = 0.0F;
+ this.inWater = true;
+ this.fire = 0;
+ } else {
+ this.inWater = false;
+ }
+
+ return this.inWater;
+ }
+
+ /**
+ * Checks if the current block the entity is within of the specified material
+ * type
+ */
+ public boolean isInsideOfMaterial(Material par1Material) {
+ double var2 = this.posY + (double) this.getEyeHeight();
+ int var4 = MathHelper.floor_double(this.posX);
+ int var5 = MathHelper.floor_float((float) MathHelper.floor_double(var2));
+ int var6 = MathHelper.floor_double(this.posZ);
+ int var7 = this.worldObj.getBlockId(var4, var5, var6);
+
+ if (var7 != 0 && Block.blocksList[var7].blockMaterial == par1Material) {
+ float var8 = BlockFluid.getFluidHeightPercent(this.worldObj.getBlockMetadata(var4, var5, var6))
+ - 0.11111111F;
+ float var9 = (float) (var5 + 1) - var8;
+ return var2 < (double) var9;
+ } else {
+ return false;
+ }
+ }
+
+ public float getEyeHeight() {
+ return 0.0F;
+ }
+
+ /**
+ * Whether or not the current entity is in lava
+ */
+ public boolean handleLavaMovement() {
+ return this.worldObj.isMaterialInBB(
+ this.boundingBox.expand(-0.10000000149011612D, -0.4000000059604645D, -0.10000000149011612D),
+ Material.lava);
+ }
+
+ /**
+ * Used in both water and by flying objects
+ */
+ public void moveFlying(float par1, float par2, float par3) {
+ float var4 = par1 * par1 + par2 * par2;
+
+ if (var4 >= 1.0E-4F) {
+ var4 = MathHelper.sqrt_float(var4);
+
+ if (var4 < 1.0F) {
+ var4 = 1.0F;
+ }
+
+ var4 = par3 / var4;
+ par1 *= var4;
+ par2 *= var4;
+ float var5 = MathHelper.sin(this.rotationYaw * (float) Math.PI / 180.0F);
+ float var6 = MathHelper.cos(this.rotationYaw * (float) Math.PI / 180.0F);
+ this.motionX += (double) (par1 * var6 - par2 * var5);
+ this.motionZ += (double) (par2 * var6 + par1 * var5);
+ }
+ }
+
+ /**
+ * Gets how bright this entity is.
+ */
+ public float getBrightness(float par1) {
+ int var2 = MathHelper.floor_double(this.posX);
+ int var3 = MathHelper.floor_double(this.posZ);
+
+ if (this.worldObj.blockExists(var2, 0, var3)) {
+ double var4 = (this.boundingBox.maxY - this.boundingBox.minY) * 0.66D;
+ int var6 = MathHelper.floor_double(this.posY - (double) this.yOffset + var4);
+ return this.worldObj.getLightBrightness(var2, var6, var3);
+ } else {
+ return 0.0F;
+ }
+ }
+
+ /**
+ * Sets the reference to the World object.
+ */
+ public void setWorld(World par1World) {
+ this.worldObj = par1World;
+ }
+
+ /**
+ * Sets the entity's position and rotation. Args: posX, posY, posZ, yaw, pitch
+ */
+ public void setPositionAndRotation(double par1, double par3, double par5, float par7, float par8) {
+ this.prevPosX = this.posX = par1;
+ this.prevPosY = this.posY = par3;
+ this.prevPosZ = this.posZ = par5;
+ this.prevRotationYaw = this.rotationYaw = par7;
+ this.prevRotationPitch = this.rotationPitch = par8;
+ this.ySize = 0.0F;
+ double var9 = (double) (this.prevRotationYaw - par7);
+
+ if (var9 < -180.0D) {
+ this.prevRotationYaw += 360.0F;
+ }
+
+ if (var9 >= 180.0D) {
+ this.prevRotationYaw -= 360.0F;
+ }
+
+ this.setPosition(this.posX, this.posY, this.posZ);
+ this.setRotation(par7, par8);
+ }
+
+ /**
+ * Sets the location and Yaw/Pitch of an entity in the world
+ */
+ public void setLocationAndAngles(double par1, double par3, double par5, float par7, float par8) {
+ this.lastTickPosX = this.prevPosX = this.posX = par1;
+ this.lastTickPosY = this.prevPosY = this.posY = par3 + (double) this.yOffset;
+ this.lastTickPosZ = this.prevPosZ = this.posZ = par5;
+ this.rotationYaw = par7;
+ this.rotationPitch = par8;
+ this.setPosition(this.posX, this.posY, this.posZ);
+ }
+
+ /**
+ * Returns the distance to the entity. Args: entity
+ */
+ public float getDistanceToEntity(Entity par1Entity) {
+ float var2 = (float) (this.posX - par1Entity.posX);
+ float var3 = (float) (this.posY - par1Entity.posY);
+ float var4 = (float) (this.posZ - par1Entity.posZ);
+ return MathHelper.sqrt_float(var2 * var2 + var3 * var3 + var4 * var4);
+ }
+
+ /**
+ * Gets the squared distance to the position. Args: x, y, z
+ */
+ public double getDistanceSq(double par1, double par3, double par5) {
+ double var7 = this.posX - par1;
+ double var9 = this.posY - par3;
+ double var11 = this.posZ - par5;
+ return var7 * var7 + var9 * var9 + var11 * var11;
+ }
+
+ /**
+ * Gets the distance to the position. Args: x, y, z
+ */
+ public double getDistance(double par1, double par3, double par5) {
+ double var7 = this.posX - par1;
+ double var9 = this.posY - par3;
+ double var11 = this.posZ - par5;
+ return (double) MathHelper.sqrt_double(var7 * var7 + var9 * var9 + var11 * var11);
+ }
+
+ /**
+ * Returns the squared distance to the entity. Args: entity
+ */
+ public double getDistanceSqToEntity(Entity par1Entity) {
+ double var2 = this.posX - par1Entity.posX;
+ double var4 = this.posY - par1Entity.posY;
+ double var6 = this.posZ - par1Entity.posZ;
+ return var2 * var2 + var4 * var4 + var6 * var6;
+ }
+
+ /**
+ * Called by a player entity when they collide with an entity
+ */
+ public void onCollideWithPlayer(EntityPlayer par1EntityPlayer) {
+ }
+
+ /**
+ * Applies a velocity to each of the entities pushing them away from each other.
+ * Args: entity
+ */
+ public void applyEntityCollision(Entity par1Entity) {
+ if (par1Entity.riddenByEntity != this && par1Entity.ridingEntity != this) {
+ double var2 = par1Entity.posX - this.posX;
+ double var4 = par1Entity.posZ - this.posZ;
+ double var6 = MathHelper.abs_max(var2, var4);
+
+ if (var6 >= 0.009999999776482582D) {
+ var6 = (double) MathHelper.sqrt_double(var6);
+ var2 /= var6;
+ var4 /= var6;
+ double var8 = 1.0D / var6;
+
+ if (var8 > 1.0D) {
+ var8 = 1.0D;
+ }
+
+ var2 *= var8;
+ var4 *= var8;
+ var2 *= 0.05000000074505806D;
+ var4 *= 0.05000000074505806D;
+ var2 *= (double) (1.0F - this.entityCollisionReduction);
+ var4 *= (double) (1.0F - this.entityCollisionReduction);
+ this.addVelocity(-var2, 0.0D, -var4);
+ par1Entity.addVelocity(var2, 0.0D, var4);
+ }
+ }
+ }
+
+ /**
+ * Adds to the current velocity of the entity. Args: x, y, z
+ */
+ public void addVelocity(double par1, double par3, double par5) {
+ this.motionX += par1;
+ this.motionY += par3;
+ this.motionZ += par5;
+ this.isAirBorne = true;
+ }
+
+ /**
+ * Sets that this entity has been attacked.
+ */
+ protected void setBeenAttacked() {
+ this.velocityChanged = true;
+ }
+
+ /**
+ * Called when the entity is attacked.
+ */
+ public boolean attackEntityFrom(DamageSource par1DamageSource, int par2) {
+ if (this.isEntityInvulnerable()) {
+ return false;
+ } else {
+ this.setBeenAttacked();
+ return false;
+ }
+ }
+
+ /**
+ * Returns true if other Entities should be prevented from moving through this
+ * Entity.
+ */
+ public boolean canBeCollidedWith() {
+ return false;
+ }
+
+ /**
+ * Returns true if this entity should push and be pushed by other entities when
+ * colliding.
+ */
+ public boolean canBePushed() {
+ return false;
+ }
+
+ /**
+ * Adds a value to the player score. Currently not actually used and the entity
+ * passed in does nothing. Args: entity, scoreToAdd
+ */
+ public void addToPlayerScore(Entity par1Entity, int par2) {
+ }
+
+ public boolean addNotRiddenEntityID(NBTTagCompound par1NBTTagCompound) {
+ String var2 = this.getEntityString();
+
+ if (!this.isDead && var2 != null) {
+ par1NBTTagCompound.setString("id", var2);
+ this.writeToNBT(par1NBTTagCompound);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * adds the ID of this entity to the NBT given
+ */
+ public boolean addEntityID(NBTTagCompound par1NBTTagCompound) {
+ String var2 = this.getEntityString();
+
+ if (!this.isDead && var2 != null && this.riddenByEntity == null) {
+ par1NBTTagCompound.setString("id", var2);
+ this.writeToNBT(par1NBTTagCompound);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Save the entity to NBT (calls an abstract helper method to write extra data)
+ */
+ public void writeToNBT(NBTTagCompound par1NBTTagCompound) {
+ par1NBTTagCompound.setTag("Pos",
+ this.newDoubleNBTList(new double[] { this.posX, this.posY + (double) this.ySize, this.posZ }));
+ par1NBTTagCompound.setTag("Motion",
+ this.newDoubleNBTList(new double[] { this.motionX, this.motionY, this.motionZ }));
+ par1NBTTagCompound.setTag("Rotation",
+ this.newFloatNBTList(new float[] { this.rotationYaw, this.rotationPitch }));
+ par1NBTTagCompound.setFloat("FallDistance", this.fallDistance);
+ par1NBTTagCompound.setShort("Fire", (short) this.fire);
+ par1NBTTagCompound.setShort("Air", (short) this.getAir());
+ par1NBTTagCompound.setBoolean("OnGround", this.onGround);
+ par1NBTTagCompound.setInteger("Dimension", this.dimension);
+ par1NBTTagCompound.setBoolean("Invulnerable", this.invulnerable);
+ par1NBTTagCompound.setInteger("PortalCooldown", this.timeUntilPortal);
+ par1NBTTagCompound.setLong("UUIDMost", this.entityUniqueID.getMostSignificantBits());
+ par1NBTTagCompound.setLong("UUIDLeast", this.entityUniqueID.getLeastSignificantBits());
+ this.writeEntityToNBT(par1NBTTagCompound);
+
+ if (this.ridingEntity != null) {
+ NBTTagCompound var2 = new NBTTagCompound("Riding");
+
+ if (this.ridingEntity.addNotRiddenEntityID(var2)) {
+ par1NBTTagCompound.setTag("Riding", var2);
+ }
+ }
+ }
+
+ /**
+ * Reads the entity from NBT (calls an abstract helper method to read
+ * specialized data)
+ */
+ public void readFromNBT(NBTTagCompound par1NBTTagCompound) {
+ NBTTagList var2 = par1NBTTagCompound.getTagList("Pos");
+ NBTTagList var6 = par1NBTTagCompound.getTagList("Motion");
+ NBTTagList var7 = par1NBTTagCompound.getTagList("Rotation");
+ this.motionX = ((NBTTagDouble) var6.tagAt(0)).data;
+ this.motionY = ((NBTTagDouble) var6.tagAt(1)).data;
+ this.motionZ = ((NBTTagDouble) var6.tagAt(2)).data;
+
+ if (Math.abs(this.motionX) > 10.0D) {
+ this.motionX = 0.0D;
+ }
+
+ if (Math.abs(this.motionY) > 10.0D) {
+ this.motionY = 0.0D;
+ }
+
+ if (Math.abs(this.motionZ) > 10.0D) {
+ this.motionZ = 0.0D;
+ }
+
+ this.prevPosX = this.lastTickPosX = this.posX = ((NBTTagDouble) var2.tagAt(0)).data;
+ this.prevPosY = this.lastTickPosY = this.posY = ((NBTTagDouble) var2.tagAt(1)).data;
+ this.prevPosZ = this.lastTickPosZ = this.posZ = ((NBTTagDouble) var2.tagAt(2)).data;
+ this.prevRotationYaw = this.rotationYaw = ((NBTTagFloat) var7.tagAt(0)).data;
+ this.prevRotationPitch = this.rotationPitch = ((NBTTagFloat) var7.tagAt(1)).data;
+ this.fallDistance = par1NBTTagCompound.getFloat("FallDistance");
+ this.fire = par1NBTTagCompound.getShort("Fire");
+ this.setAir(par1NBTTagCompound.getShort("Air"));
+ this.onGround = par1NBTTagCompound.getBoolean("OnGround");
+ this.dimension = par1NBTTagCompound.getInteger("Dimension");
+ this.invulnerable = par1NBTTagCompound.getBoolean("Invulnerable");
+ this.timeUntilPortal = par1NBTTagCompound.getInteger("PortalCooldown");
+
+ if (par1NBTTagCompound.hasKey("UUIDMost") && par1NBTTagCompound.hasKey("UUIDLeast")) {
+ this.entityUniqueID = new EaglerUUID(par1NBTTagCompound.getLong("UUIDMost"),
+ par1NBTTagCompound.getLong("UUIDLeast"));
+ }
+
+ this.setPosition(this.posX, this.posY, this.posZ);
+ this.setRotation(this.rotationYaw, this.rotationPitch);
+ this.readEntityFromNBT(par1NBTTagCompound);
+ }
+
+ /**
+ * Returns the string that identifies this Entity's class
+ */
+ protected final String getEntityString() {
+ return EntityList.getEntityString(this);
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ protected abstract void readEntityFromNBT(NBTTagCompound var1);
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ protected abstract void writeEntityToNBT(NBTTagCompound var1);
+
+ /**
+ * creates a NBT list from the array of doubles passed to this function
+ */
+ protected NBTTagList newDoubleNBTList(double... par1ArrayOfDouble) {
+ NBTTagList var2 = new NBTTagList();
+ double[] var3 = par1ArrayOfDouble;
+ int var4 = par1ArrayOfDouble.length;
+
+ for (int var5 = 0; var5 < var4; ++var5) {
+ double var6 = var3[var5];
+ var2.appendTag(new NBTTagDouble((String) null, var6));
+ }
+
+ return var2;
+ }
+
+ /**
+ * Returns a new NBTTagList filled with the specified floats
+ */
+ protected NBTTagList newFloatNBTList(float... par1ArrayOfFloat) {
+ NBTTagList var2 = new NBTTagList();
+ float[] var3 = par1ArrayOfFloat;
+ int var4 = par1ArrayOfFloat.length;
+
+ for (int var5 = 0; var5 < var4; ++var5) {
+ float var6 = var3[var5];
+ var2.appendTag(new NBTTagFloat((String) null, var6));
+ }
+
+ return var2;
+ }
+
+ /**
+ * Drops an item stack at the entity's position. Args: itemID, count
+ */
+ public EntityItem dropItem(int par1, int par2) {
+ return this.dropItemWithOffset(par1, par2, 0.0F);
+ }
+
+ /**
+ * Drops an item stack with a specified y offset. Args: itemID, count, yOffset
+ */
+ public EntityItem dropItemWithOffset(int par1, int par2, float par3) {
+ return this.entityDropItem(new ItemStack(par1, par2, 0), par3);
+ }
+
+ /**
+ * Drops an item at the position of the entity.
+ */
+ public EntityItem entityDropItem(ItemStack par1ItemStack, float par2) {
+ EntityItem var3 = new EntityItem(this.worldObj, this.posX, this.posY + (double) par2, this.posZ, par1ItemStack);
+ var3.delayBeforeCanPickup = 10;
+ this.worldObj.spawnEntityInWorld(var3);
+ return var3;
+ }
+
+ /**
+ * Checks whether target entity is alive.
+ */
+ public boolean isEntityAlive() {
+ return !this.isDead;
+ }
+
+ /**
+ * Checks if this entity is inside of an opaque block
+ */
+ public boolean isEntityInsideOpaqueBlock() {
+ for (int var1 = 0; var1 < 8; ++var1) {
+ float var2 = ((float) ((var1 >> 0) % 2) - 0.5F) * this.width * 0.8F;
+ float var3 = ((float) ((var1 >> 1) % 2) - 0.5F) * 0.1F;
+ float var4 = ((float) ((var1 >> 2) % 2) - 0.5F) * this.width * 0.8F;
+ int var5 = MathHelper.floor_double(this.posX + (double) var2);
+ int var6 = MathHelper.floor_double(this.posY + (double) this.getEyeHeight() + (double) var3);
+ int var7 = MathHelper.floor_double(this.posZ + (double) var4);
+
+ if (this.worldObj.isBlockNormalCube(var5, var6, var7)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Called when a player interacts with a mob. e.g. gets milk from a cow, gets
+ * into the saddle on a pig.
+ */
+ public boolean interact(EntityPlayer par1EntityPlayer) {
+ return false;
+ }
+
+ /**
+ * Returns a boundingBox used to collide the entity with other entities and
+ * blocks. This enables the entity to be pushable on contact, like boats or
+ * minecarts.
+ */
+ public AxisAlignedBB getCollisionBox(Entity par1Entity) {
+ return null;
+ }
+
+ /**
+ * Handles updating while being ridden by an entity
+ */
+ public void updateRidden() {
+ if (this.ridingEntity.isDead) {
+ this.ridingEntity = null;
+ } else {
+ this.motionX = 0.0D;
+ this.motionY = 0.0D;
+ this.motionZ = 0.0D;
+ this.onUpdate();
+
+ if (this.ridingEntity != null) {
+ this.ridingEntity.updateRiderPosition();
+ this.entityRiderYawDelta += (double) (this.ridingEntity.rotationYaw
+ - this.ridingEntity.prevRotationYaw);
+
+ for (this.entityRiderPitchDelta += (double) (this.ridingEntity.rotationPitch
+ - this.ridingEntity.prevRotationPitch); this.entityRiderYawDelta >= 180.0D; this.entityRiderYawDelta -= 360.0D) {
+ ;
+ }
+
+ while (this.entityRiderYawDelta < -180.0D) {
+ this.entityRiderYawDelta += 360.0D;
+ }
+
+ while (this.entityRiderPitchDelta >= 180.0D) {
+ this.entityRiderPitchDelta -= 360.0D;
+ }
+
+ while (this.entityRiderPitchDelta < -180.0D) {
+ this.entityRiderPitchDelta += 360.0D;
+ }
+
+ double var1 = this.entityRiderYawDelta * 0.5D;
+ double var3 = this.entityRiderPitchDelta * 0.5D;
+ float var5 = 10.0F;
+
+ if (var1 > (double) var5) {
+ var1 = (double) var5;
+ }
+
+ if (var1 < (double) (-var5)) {
+ var1 = (double) (-var5);
+ }
+
+ if (var3 > (double) var5) {
+ var3 = (double) var5;
+ }
+
+ if (var3 < (double) (-var5)) {
+ var3 = (double) (-var5);
+ }
+
+ this.entityRiderYawDelta -= var1;
+ this.entityRiderPitchDelta -= var3;
+ this.rotationYaw = (float) ((double) this.rotationYaw + var1);
+ this.rotationPitch = (float) ((double) this.rotationPitch + var3);
+ }
+ }
+ }
+
+ public void updateRiderPosition() {
+ if (this.riddenByEntity != null) {
+ if (!(this.riddenByEntity instanceof EntityPlayer)
+ || !((EntityPlayer) this.riddenByEntity).func_71066_bF()) {
+ this.riddenByEntity.lastTickPosX = this.lastTickPosX;
+ this.riddenByEntity.lastTickPosY = this.lastTickPosY + this.getMountedYOffset()
+ + this.riddenByEntity.getYOffset();
+ this.riddenByEntity.lastTickPosZ = this.lastTickPosZ;
+ }
+
+ this.riddenByEntity.setPosition(this.posX,
+ this.posY + this.getMountedYOffset() + this.riddenByEntity.getYOffset(), this.posZ);
+ }
+ }
+
+ /**
+ * Returns the Y Offset of this entity.
+ */
+ public double getYOffset() {
+ return (double) this.yOffset;
+ }
+
+ /**
+ * Returns the Y offset from the entity's position for any entity riding this
+ * one.
+ */
+ public double getMountedYOffset() {
+ return (double) this.height * 0.75D;
+ }
+
+ /**
+ * Called when a player mounts an entity. e.g. mounts a pig, mounts a boat.
+ */
+ public void mountEntity(Entity par1Entity) {
+ this.entityRiderPitchDelta = 0.0D;
+ this.entityRiderYawDelta = 0.0D;
+
+ if (par1Entity == null) {
+ if (this.ridingEntity != null) {
+ this.setLocationAndAngles(this.ridingEntity.posX,
+ this.ridingEntity.boundingBox.minY + (double) this.ridingEntity.height, this.ridingEntity.posZ,
+ this.rotationYaw, this.rotationPitch);
+ this.ridingEntity.riddenByEntity = null;
+ }
+
+ this.ridingEntity = null;
+ } else {
+ if (this.ridingEntity != null) {
+ this.ridingEntity.riddenByEntity = null;
+ }
+
+ this.ridingEntity = par1Entity;
+ par1Entity.riddenByEntity = this;
+ }
+ }
+
+ /**
+ * Called when a player unounts an entity.
+ */
+ public void unmountEntity(Entity par1Entity) {
+ double var3 = this.posX;
+ double var5 = this.posY;
+ double var7 = this.posZ;
+
+ if (par1Entity != null) {
+ var3 = par1Entity.posX;
+ var5 = par1Entity.boundingBox.minY + (double) par1Entity.height;
+ var7 = par1Entity.posZ;
+ }
+
+ for (double var9 = -1.5D; var9 < 2.0D; ++var9) {
+ for (double var11 = -1.5D; var11 < 2.0D; ++var11) {
+ if (var9 != 0.0D || var11 != 0.0D) {
+ int var13 = (int) (this.posX + var9);
+ int var14 = (int) (this.posZ + var11);
+ AxisAlignedBB var2 = this.boundingBox.getOffsetBoundingBox(var9, 1.0D, var11);
+
+ if (this.worldObj.getCollidingBlockBounds(var2).isEmpty()) {
+ if (this.worldObj.doesBlockHaveSolidTopSurface(var13, (int) this.posY, var14)) {
+ this.setLocationAndAngles(this.posX + var9, this.posY + 1.0D, this.posZ + var11,
+ this.rotationYaw, this.rotationPitch);
+ return;
+ }
+
+ if (this.worldObj.doesBlockHaveSolidTopSurface(var13, (int) this.posY - 1, var14)
+ || this.worldObj.getBlockMaterial(var13, (int) this.posY - 1,
+ var14) == Material.water) {
+ var3 = this.posX + var9;
+ var5 = this.posY + 1.0D;
+ var7 = this.posZ + var11;
+ }
+ }
+ }
+ }
+ }
+
+ this.setLocationAndAngles(var3, var5, var7, this.rotationYaw, this.rotationPitch);
+ }
+
+ public float getCollisionBorderSize() {
+ return 0.1F;
+ }
+
+ /**
+ * returns a (normalized) vector of where this entity is looking
+ */
+ public Vec3 getLookVec() {
+ return null;
+ }
+
+ /**
+ * Called by portal blocks when an entity is within it.
+ */
+ public void setInPortal() {
+ if (this.timeUntilPortal > 0) {
+ this.timeUntilPortal = this.getPortalCooldown();
+ } else {
+ double var1 = this.prevPosX - this.posX;
+ double var3 = this.prevPosZ - this.posZ;
+
+ if (!this.worldObj.isRemote && !this.inPortal) {
+ this.teleportDirection = Direction.getMovementDirection(var1, var3);
+ }
+
+ this.inPortal = true;
+ }
+ }
+
+ /**
+ * Return the amount of cooldown before this entity can use a portal again.
+ */
+ public int getPortalCooldown() {
+ return 900;
+ }
+
+ /**
+ * returns the inventory of this entity (only used in EntityPlayerMP it seems)
+ */
+ public ItemStack[] getInventory() {
+ return null;
+ }
+
+ /**
+ * Sets the held item, or an armor slot. Slot 0 is held item. Slot 1-4 is armor.
+ * Params: Item, slot
+ */
+ public void setCurrentItemOrArmor(int par1, ItemStack par2ItemStack) {
+ }
+
+ /**
+ * Returns true if the entity is on fire. Used by render to add the fire effect
+ * on rendering.
+ */
+ public boolean isBurning() {
+ return this.fire > 0 || this.getFlag(0);
+ }
+
+ /**
+ * Returns true if the entity is riding another entity, used by render to rotate
+ * the legs to be in 'sit' position for players.
+ */
+ public boolean isRiding() {
+ return this.ridingEntity != null || this.getFlag(2);
+ }
+
+ /**
+ * Returns if this entity is sneaking.
+ */
+ public boolean isSneaking() {
+ return this.getFlag(1);
+ }
+
+ /**
+ * Sets the sneaking flag.
+ */
+ public void setSneaking(boolean par1) {
+ this.setFlag(1, par1);
+ }
+
+ /**
+ * Get if the Entity is sprinting.
+ */
+ public boolean isSprinting() {
+ return this.getFlag(3);
+ }
+
+ /**
+ * Set sprinting switch for Entity.
+ */
+ public void setSprinting(boolean par1) {
+ this.setFlag(3, par1);
+ }
+
+ public boolean isInvisible() {
+ return this.getFlag(5);
+ }
+
+ public void setInvisible(boolean par1) {
+ this.setFlag(5, par1);
+ }
+
+ public void setEating(boolean par1) {
+ this.setFlag(4, par1);
+ }
+
+ /**
+ * Returns true if the flag is active for the entity. Known flags: 0) is
+ * burning; 1) is sneaking; 2) is riding something; 3) is sprinting; 4) is
+ * eating
+ */
+ protected boolean getFlag(int par1) {
+ return (this.dataWatcher.getWatchableObjectByte(0) & 1 << par1) != 0;
+ }
+
+ /**
+ * Enable or disable a entity flag, see getEntityFlag to read the know flags.
+ */
+ protected void setFlag(int par1, boolean par2) {
+ byte var3 = this.dataWatcher.getWatchableObjectByte(0);
+
+ if (par2) {
+ this.dataWatcher.updateObject(0, Byte.valueOf((byte) (var3 | 1 << par1)));
+ } else {
+ this.dataWatcher.updateObject(0, Byte.valueOf((byte) (var3 & ~(1 << par1))));
+ }
+ }
+
+ public int getAir() {
+ return this.dataWatcher.getWatchableObjectShort(1);
+ }
+
+ public void setAir(int par1) {
+ this.dataWatcher.updateObject(1, Short.valueOf((short) par1));
+ }
+
+ /**
+ * Called when a lightning bolt hits the entity.
+ */
+ public void onStruckByLightning(EntityLightningBolt par1EntityLightningBolt) {
+ this.dealFireDamage(5);
+ ++this.fire;
+
+ if (this.fire == 0) {
+ this.setFire(8);
+ }
+ }
+
+ /**
+ * This method gets called when the entity kills another one.
+ */
+ public void onKillEntity(EntityLiving par1EntityLiving) {
+ }
+
+ /**
+ * Adds velocity to push the entity out of blocks at the specified x, y, z
+ * position Args: x, y, z
+ */
+ protected boolean pushOutOfBlocks(double par1, double par3, double par5) {
+ int var7 = MathHelper.floor_double(par1);
+ int var8 = MathHelper.floor_double(par3);
+ int var9 = MathHelper.floor_double(par5);
+ double var10 = par1 - (double) var7;
+ double var12 = par3 - (double) var8;
+ double var14 = par5 - (double) var9;
+ List var16 = this.worldObj.getCollidingBlockBounds(this.boundingBox);
+
+ if (var16.isEmpty() && !this.worldObj.func_85174_u(var7, var8, var9)) {
+ return false;
+ } else {
+ boolean var17 = !this.worldObj.func_85174_u(var7 - 1, var8, var9);
+ boolean var18 = !this.worldObj.func_85174_u(var7 + 1, var8, var9);
+ boolean var19 = !this.worldObj.func_85174_u(var7, var8 - 1, var9);
+ boolean var20 = !this.worldObj.func_85174_u(var7, var8 + 1, var9);
+ boolean var21 = !this.worldObj.func_85174_u(var7, var8, var9 - 1);
+ boolean var22 = !this.worldObj.func_85174_u(var7, var8, var9 + 1);
+ byte var23 = 3;
+ double var24 = 9999.0D;
+
+ if (var17 && var10 < var24) {
+ var24 = var10;
+ var23 = 0;
+ }
+
+ if (var18 && 1.0D - var10 < var24) {
+ var24 = 1.0D - var10;
+ var23 = 1;
+ }
+
+ if (var20 && 1.0D - var12 < var24) {
+ var24 = 1.0D - var12;
+ var23 = 3;
+ }
+
+ if (var21 && var14 < var24) {
+ var24 = var14;
+ var23 = 4;
+ }
+
+ if (var22 && 1.0D - var14 < var24) {
+ var24 = 1.0D - var14;
+ var23 = 5;
+ }
+
+ float var26 = this.rand.nextFloat() * 0.2F + 0.1F;
+
+ if (var23 == 0) {
+ this.motionX = (double) (-var26);
+ }
+
+ if (var23 == 1) {
+ this.motionX = (double) var26;
+ }
+
+ if (var23 == 2) {
+ this.motionY = (double) (-var26);
+ }
+
+ if (var23 == 3) {
+ this.motionY = (double) var26;
+ }
+
+ if (var23 == 4) {
+ this.motionZ = (double) (-var26);
+ }
+
+ if (var23 == 5) {
+ this.motionZ = (double) var26;
+ }
+
+ return true;
+ }
+ }
+
+ /**
+ * Sets the Entity inside a web block.
+ */
+ public void setInWeb() {
+ this.isInWeb = true;
+ this.fallDistance = 0.0F;
+ }
+
+ /**
+ * Gets the username of the entity.
+ */
+ public String getEntityName() {
+ String var1 = EntityList.getEntityString(this);
+
+ if (var1 == null) {
+ var1 = "generic";
+ }
+
+ return StatCollector.translateToLocal("entity." + var1 + ".name");
+ }
+
+ /**
+ * Return the Entity parts making up this Entity (currently only for dragons)
+ */
+ public Entity[] getParts() {
+ return null;
+ }
+
+ /**
+ * Returns true if Entity argument is equal to this Entity
+ */
+ public boolean isEntityEqual(Entity par1Entity) {
+ return this == par1Entity;
+ }
+
+ public float getRotationYawHead() {
+ return 0.0F;
+ }
+
+ /**
+ * If returns false, the item will not inflict any damage against entities.
+ */
+ public boolean canAttackWithItem() {
+ return true;
+ }
+
+ public boolean func_85031_j(Entity par1Entity) {
+ return false;
+ }
+
+ public String toString() {
+ return String.format("%s[\'%s\'/%d, l=\'%s\', x=%s, y=%s, z=%s]",
+ new Object[] { this.getClass().getSimpleName(), this.getEntityName(), Integer.valueOf(this.entityId),
+ this.worldObj == null ? "~NULL~" : this.worldObj.getWorldInfo().getWorldName(),
+ Double.valueOf(this.posX), Double.valueOf(this.posY), Double.valueOf(this.posZ) });
+ }
+
+ /**
+ * Return whether this entity is invulnerable to damage.
+ */
+ public boolean isEntityInvulnerable() {
+ return this.invulnerable;
+ }
+
+ public void func_82149_j(Entity par1Entity) {
+ this.setLocationAndAngles(par1Entity.posX, par1Entity.posY, par1Entity.posZ, par1Entity.rotationYaw,
+ par1Entity.rotationPitch);
+ }
+
+ /**
+ * Copies important data from another entity to this entity. Used when
+ * teleporting entities between worlds, as this actually deletes the teleporting
+ * entity and re-creates it on the other side. Params: Entity to copy from,
+ * unused (always true)
+ */
+ public void copyDataFrom(Entity par1Entity, boolean par2) {
+ NBTTagCompound var3 = new NBTTagCompound();
+ par1Entity.writeToNBT(var3);
+ this.readFromNBT(var3);
+ this.timeUntilPortal = par1Entity.timeUntilPortal;
+ this.teleportDirection = par1Entity.teleportDirection;
+ }
+
+ public void travelToTheEnd(int par1) {
+ if (!this.worldObj.isRemote && !this.isDead) {
+ MinecraftServer var2 = MinecraftServer.getServer();
+ int var3 = this.dimension;
+ WorldServer var4 = var2.worldServerForDimension(var3);
+ WorldServer var5 = var2.worldServerForDimension(par1);
+ this.dimension = par1;
+ this.worldObj.removeEntity(this);
+ this.isDead = false;
+ var2.getConfigurationManager().transferEntityToWorld(this, var3, var4, var5);
+ Entity var6 = EntityList.createEntityByName(EntityList.getEntityString(this), var5);
+
+ if (var6 != null) {
+ var6.copyDataFrom(this, true);
+ var5.spawnEntityInWorld(var6);
+ }
+
+ this.isDead = true;
+ var4.resetUpdateEntityTick();
+ var5.resetUpdateEntityTick();
+ }
+ }
+
+ public float func_82146_a(Explosion par1Explosion, World par2World, int par3, int par4, int par5, Block par6Block) {
+ return par6Block.getExplosionResistance(this);
+ }
+
+ public boolean func_96091_a(Explosion par1Explosion, World par2World, int par3, int par4, int par5, int par6,
+ float par7) {
+ return true;
+ }
+
+ public int func_82143_as() {
+ return 3;
+ }
+
+ public int getTeleportDirection() {
+ return this.teleportDirection;
+ }
+
+ /**
+ * Return whether this entity should NOT trigger a pressure plate or a tripwire.
+ */
+ public boolean doesEntityNotTriggerPressurePlate() {
+ return false;
+ }
+
+ public boolean func_96092_aw() {
+ return true;
+ }
+
+ /**
+ * Returns the translated name of the entity.
+ */
+ public String getTranslatedEntityName() {
+ return this.getEntityName();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAIArrowAttack.java b/sp-server/src/main/java/net/minecraft/src/EntityAIArrowAttack.java
new file mode 100644
index 0000000..39cbf28
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAIArrowAttack.java
@@ -0,0 +1,129 @@
+package net.minecraft.src;
+
+public class EntityAIArrowAttack extends EntityAIBase {
+ /** The entity the AI instance has been applied to */
+ private final EntityLiving entityHost;
+
+ /**
+ * The entity (as a RangedAttackMob) the AI instance has been applied to.
+ */
+ private final IRangedAttackMob rangedAttackEntityHost;
+ private EntityLiving attackTarget;
+
+ /**
+ * A decrementing tick that spawns a ranged attack once this value reaches 0. It
+ * is then set back to the maxRangedAttackTime.
+ */
+ private int rangedAttackTime;
+ private float entityMoveSpeed;
+ private int field_75318_f;
+ private int field_96561_g;
+
+ /**
+ * The maximum time the AI has to wait before peforming another ranged attack.
+ */
+ private int maxRangedAttackTime;
+ private float field_96562_i;
+ private float field_82642_h;
+
+ public EntityAIArrowAttack(IRangedAttackMob par1IRangedAttackMob, float par2, int par3, float par4) {
+ this(par1IRangedAttackMob, par2, par3, par3, par4);
+ }
+
+ public EntityAIArrowAttack(IRangedAttackMob par1IRangedAttackMob, float par2, int par3, int par4, float par5) {
+ this.rangedAttackTime = -1;
+ this.field_75318_f = 0;
+
+ if (!(par1IRangedAttackMob instanceof EntityLiving)) {
+ throw new IllegalArgumentException("ArrowAttackGoal requires Mob implements RangedAttackMob");
+ } else {
+ this.rangedAttackEntityHost = par1IRangedAttackMob;
+ this.entityHost = (EntityLiving) par1IRangedAttackMob;
+ this.entityMoveSpeed = par2;
+ this.field_96561_g = par3;
+ this.maxRangedAttackTime = par4;
+ this.field_96562_i = par5;
+ this.field_82642_h = par5 * par5;
+ this.setMutexBits(3);
+ }
+ }
+
+ /**
+ * Returns whether the EntityAIBase should begin execution.
+ */
+ public boolean shouldExecute() {
+ EntityLiving var1 = this.entityHost.getAttackTarget();
+
+ if (var1 == null) {
+ return false;
+ } else {
+ this.attackTarget = var1;
+ return true;
+ }
+ }
+
+ /**
+ * Returns whether an in-progress EntityAIBase should continue executing
+ */
+ public boolean continueExecuting() {
+ return this.shouldExecute() || !this.entityHost.getNavigator().noPath();
+ }
+
+ /**
+ * Resets the task
+ */
+ public void resetTask() {
+ this.attackTarget = null;
+ this.field_75318_f = 0;
+ this.rangedAttackTime = -1;
+ }
+
+ /**
+ * Updates the task
+ */
+ public void updateTask() {
+ double var1 = this.entityHost.getDistanceSq(this.attackTarget.posX, this.attackTarget.boundingBox.minY,
+ this.attackTarget.posZ);
+ boolean var3 = this.entityHost.getEntitySenses().canSee(this.attackTarget);
+
+ if (var3) {
+ ++this.field_75318_f;
+ } else {
+ this.field_75318_f = 0;
+ }
+
+ if (var1 <= (double) this.field_82642_h && this.field_75318_f >= 20) {
+ this.entityHost.getNavigator().clearPathEntity();
+ } else {
+ this.entityHost.getNavigator().tryMoveToEntityLiving(this.attackTarget, this.entityMoveSpeed);
+ }
+
+ this.entityHost.getLookHelper().setLookPositionWithEntity(this.attackTarget, 30.0F, 30.0F);
+ float var4;
+
+ if (--this.rangedAttackTime == 0) {
+ if (var1 > (double) this.field_82642_h || !var3) {
+ return;
+ }
+
+ var4 = MathHelper.sqrt_double(var1) / this.field_96562_i;
+ float var5 = var4;
+
+ if (var4 < 0.1F) {
+ var5 = 0.1F;
+ }
+
+ if (var5 > 1.0F) {
+ var5 = 1.0F;
+ }
+
+ this.rangedAttackEntityHost.attackEntityWithRangedAttack(this.attackTarget, var5);
+ this.rangedAttackTime = MathHelper.floor_float(
+ var4 * (float) (this.maxRangedAttackTime - this.field_96561_g) + (float) this.field_96561_g);
+ } else if (this.rangedAttackTime < 0) {
+ var4 = MathHelper.sqrt_double(var1) / this.field_96562_i;
+ this.rangedAttackTime = MathHelper.floor_float(
+ var4 * (float) (this.maxRangedAttackTime - this.field_96561_g) + (float) this.field_96561_g);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAIAttackOnCollide.java b/sp-server/src/main/java/net/minecraft/src/EntityAIAttackOnCollide.java
new file mode 100644
index 0000000..28a0b61
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAIAttackOnCollide.java
@@ -0,0 +1,109 @@
+package net.minecraft.src;
+
+public class EntityAIAttackOnCollide extends EntityAIBase {
+ World worldObj;
+ EntityLiving attacker;
+ EntityLiving entityTarget;
+
+ /**
+ * An amount of decrementing ticks that allows the entity to attack once the
+ * tick reaches 0.
+ */
+ int attackTick;
+ float field_75440_e;
+ boolean field_75437_f;
+
+ /** The PathEntity of our entity. */
+ PathEntity entityPathEntity;
+ Class classTarget;
+ private int field_75445_i;
+
+ public EntityAIAttackOnCollide(EntityLiving par1EntityLiving, Class par2Class, float par3, boolean par4) {
+ this(par1EntityLiving, par3, par4);
+ this.classTarget = par2Class;
+ }
+
+ public EntityAIAttackOnCollide(EntityLiving par1EntityLiving, float par2, boolean par3) {
+ this.attackTick = 0;
+ this.attacker = par1EntityLiving;
+ this.worldObj = par1EntityLiving.worldObj;
+ this.field_75440_e = par2;
+ this.field_75437_f = par3;
+ this.setMutexBits(3);
+ }
+
+ /**
+ * Returns whether the EntityAIBase should begin execution.
+ */
+ public boolean shouldExecute() {
+ EntityLiving var1 = this.attacker.getAttackTarget();
+
+ if (var1 == null) {
+ return false;
+ } else if (this.classTarget != null && !this.classTarget.isAssignableFrom(var1.getClass())) {
+ return false;
+ } else {
+ this.entityTarget = var1;
+ this.entityPathEntity = this.attacker.getNavigator().getPathToEntityLiving(this.entityTarget);
+ return this.entityPathEntity != null;
+ }
+ }
+
+ /**
+ * Returns whether an in-progress EntityAIBase should continue executing
+ */
+ public boolean continueExecuting() {
+ EntityLiving var1 = this.attacker.getAttackTarget();
+ return var1 == null ? false
+ : (!this.entityTarget.isEntityAlive() ? false
+ : (!this.field_75437_f ? !this.attacker.getNavigator().noPath()
+ : this.attacker.isWithinHomeDistance(MathHelper.floor_double(this.entityTarget.posX),
+ MathHelper.floor_double(this.entityTarget.posY),
+ MathHelper.floor_double(this.entityTarget.posZ))));
+ }
+
+ /**
+ * Execute a one shot task or start executing a continuous task
+ */
+ public void startExecuting() {
+ this.attacker.getNavigator().setPath(this.entityPathEntity, this.field_75440_e);
+ this.field_75445_i = 0;
+ }
+
+ /**
+ * Resets the task
+ */
+ public void resetTask() {
+ this.entityTarget = null;
+ this.attacker.getNavigator().clearPathEntity();
+ }
+
+ /**
+ * Updates the task
+ */
+ public void updateTask() {
+ this.attacker.getLookHelper().setLookPositionWithEntity(this.entityTarget, 30.0F, 30.0F);
+
+ if ((this.field_75437_f || this.attacker.getEntitySenses().canSee(this.entityTarget))
+ && --this.field_75445_i <= 0) {
+ this.field_75445_i = 4 + this.attacker.getRNG().nextInt(7);
+ this.attacker.getNavigator().tryMoveToEntityLiving(this.entityTarget, this.field_75440_e);
+ }
+
+ this.attackTick = Math.max(this.attackTick - 1, 0);
+ double var1 = (double) (this.attacker.width * 2.0F * this.attacker.width * 2.0F);
+
+ if (this.attacker.getDistanceSq(this.entityTarget.posX, this.entityTarget.boundingBox.minY,
+ this.entityTarget.posZ) <= var1) {
+ if (this.attackTick <= 0) {
+ this.attackTick = 20;
+
+ if (this.attacker.getHeldItem() != null) {
+ this.attacker.swingItem();
+ }
+
+ this.attacker.attackEntityAsMob(this.entityTarget);
+ }
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAIAvoidEntity.java b/sp-server/src/main/java/net/minecraft/src/EntityAIAvoidEntity.java
new file mode 100644
index 0000000..8373979
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAIAvoidEntity.java
@@ -0,0 +1,112 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+public class EntityAIAvoidEntity extends EntityAIBase {
+ public final IEntitySelector field_98218_a = new EntityAIAvoidEntitySelector(this);
+
+ /** The entity we are attached to */
+ private EntityCreature theEntity;
+ private float farSpeed;
+ private float nearSpeed;
+ private Entity closestLivingEntity;
+ private float distanceFromEntity;
+
+ /** The PathEntity of our entity */
+ private PathEntity entityPathEntity;
+
+ /** The PathNavigate of our entity */
+ private PathNavigate entityPathNavigate;
+
+ /** The class of the entity we should avoid */
+ private Class targetEntityClass;
+
+ public EntityAIAvoidEntity(EntityCreature par1EntityCreature, Class par2Class, float par3, float par4, float par5) {
+ this.theEntity = par1EntityCreature;
+ this.targetEntityClass = par2Class;
+ this.distanceFromEntity = par3;
+ this.farSpeed = par4;
+ this.nearSpeed = par5;
+ this.entityPathNavigate = par1EntityCreature.getNavigator();
+ this.setMutexBits(1);
+ }
+
+ /**
+ * Returns whether the EntityAIBase should begin execution.
+ */
+ public boolean shouldExecute() {
+ if (this.targetEntityClass == EntityPlayer.class) {
+ if (this.theEntity instanceof EntityTameable && ((EntityTameable) this.theEntity).isTamed()) {
+ return false;
+ }
+
+ this.closestLivingEntity = this.theEntity.worldObj.getClosestPlayerToEntity(this.theEntity,
+ (double) this.distanceFromEntity);
+
+ if (this.closestLivingEntity == null) {
+ return false;
+ }
+ } else {
+ List var1 = this.theEntity.worldObj.selectEntitiesWithinAABB(this.targetEntityClass,
+ this.theEntity.boundingBox.expand((double) this.distanceFromEntity, 3.0D,
+ (double) this.distanceFromEntity),
+ this.field_98218_a);
+
+ if (var1.isEmpty()) {
+ return false;
+ }
+
+ this.closestLivingEntity = (Entity) var1.get(0);
+ }
+
+ Vec3 var2 = RandomPositionGenerator.findRandomTargetBlockAwayFrom(this.theEntity, 16, 7,
+ this.theEntity.worldObj.getWorldVec3Pool().getVecFromPool(this.closestLivingEntity.posX,
+ this.closestLivingEntity.posY, this.closestLivingEntity.posZ));
+
+ if (var2 == null) {
+ return false;
+ } else if (this.closestLivingEntity.getDistanceSq(var2.xCoord, var2.yCoord,
+ var2.zCoord) < this.closestLivingEntity.getDistanceSqToEntity(this.theEntity)) {
+ return false;
+ } else {
+ this.entityPathEntity = this.entityPathNavigate.getPathToXYZ(var2.xCoord, var2.yCoord, var2.zCoord);
+ return this.entityPathEntity == null ? false : this.entityPathEntity.isDestinationSame(var2);
+ }
+ }
+
+ /**
+ * Returns whether an in-progress EntityAIBase should continue executing
+ */
+ public boolean continueExecuting() {
+ return !this.entityPathNavigate.noPath();
+ }
+
+ /**
+ * Execute a one shot task or start executing a continuous task
+ */
+ public void startExecuting() {
+ this.entityPathNavigate.setPath(this.entityPathEntity, this.farSpeed);
+ }
+
+ /**
+ * Resets the task
+ */
+ public void resetTask() {
+ this.closestLivingEntity = null;
+ }
+
+ /**
+ * Updates the task
+ */
+ public void updateTask() {
+ if (this.theEntity.getDistanceSqToEntity(this.closestLivingEntity) < 49.0D) {
+ this.theEntity.getNavigator().setSpeed(this.nearSpeed);
+ } else {
+ this.theEntity.getNavigator().setSpeed(this.farSpeed);
+ }
+ }
+
+ static EntityCreature func_98217_a(EntityAIAvoidEntity par0EntityAIAvoidEntity) {
+ return par0EntityAIAvoidEntity.theEntity;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAIAvoidEntitySelector.java b/sp-server/src/main/java/net/minecraft/src/EntityAIAvoidEntitySelector.java
new file mode 100644
index 0000000..129cad9
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAIAvoidEntitySelector.java
@@ -0,0 +1,17 @@
+package net.minecraft.src;
+
+class EntityAIAvoidEntitySelector implements IEntitySelector {
+ final EntityAIAvoidEntity entityAvoiderAI;
+
+ EntityAIAvoidEntitySelector(EntityAIAvoidEntity par1EntityAIAvoidEntity) {
+ this.entityAvoiderAI = par1EntityAIAvoidEntity;
+ }
+
+ /**
+ * Return whether the specified entity is applicable to this filter.
+ */
+ public boolean isEntityApplicable(Entity par1Entity) {
+ return par1Entity.isEntityAlive()
+ && EntityAIAvoidEntity.func_98217_a(this.entityAvoiderAI).getEntitySenses().canSee(par1Entity);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAIBase.java b/sp-server/src/main/java/net/minecraft/src/EntityAIBase.java
new file mode 100644
index 0000000..e85a254
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAIBase.java
@@ -0,0 +1,65 @@
+package net.minecraft.src;
+
+public abstract class EntityAIBase {
+ /**
+ * A bitmask telling which other tasks may not run concurrently. The test is a
+ * simple bitwise AND - if it yields zero, the two tasks may run concurrently,
+ * if not - they must run exclusively from each other.
+ */
+ private int mutexBits = 0;
+
+ /**
+ * Returns whether the EntityAIBase should begin execution.
+ */
+ public abstract boolean shouldExecute();
+
+ /**
+ * Returns whether an in-progress EntityAIBase should continue executing
+ */
+ public boolean continueExecuting() {
+ return this.shouldExecute();
+ }
+
+ /**
+ * Returns whether the task requires multiple updates or not
+ */
+ public boolean isContinuous() {
+ return true;
+ }
+
+ /**
+ * Execute a one shot task or start executing a continuous task
+ */
+ public void startExecuting() {
+ }
+
+ /**
+ * Resets the task
+ */
+ public void resetTask() {
+ }
+
+ /**
+ * Updates the task
+ */
+ public void updateTask() {
+ }
+
+ /**
+ * Sets a bitmask telling which other tasks may not run concurrently. The test
+ * is a simple bitwise AND - if it yields zero, the two tasks may run
+ * concurrently, if not - they must run exclusively from each other.
+ */
+ public void setMutexBits(int par1) {
+ this.mutexBits = par1;
+ }
+
+ /**
+ * Get a bitmask telling which other tasks may not run concurrently. The test is
+ * a simple bitwise AND - if it yields zero, the two tasks may run concurrently,
+ * if not - they must run exclusively from each other.
+ */
+ public int getMutexBits() {
+ return this.mutexBits;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAIBeg.java b/sp-server/src/main/java/net/minecraft/src/EntityAIBeg.java
new file mode 100644
index 0000000..d8080c1
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAIBeg.java
@@ -0,0 +1,70 @@
+package net.minecraft.src;
+
+public class EntityAIBeg extends EntityAIBase {
+ private EntityWolf theWolf;
+ private EntityPlayer thePlayer;
+ private World worldObject;
+ private float minPlayerDistance;
+ private int field_75384_e;
+
+ public EntityAIBeg(EntityWolf par1EntityWolf, float par2) {
+ this.theWolf = par1EntityWolf;
+ this.worldObject = par1EntityWolf.worldObj;
+ this.minPlayerDistance = par2;
+ this.setMutexBits(2);
+ }
+
+ /**
+ * Returns whether the EntityAIBase should begin execution.
+ */
+ public boolean shouldExecute() {
+ this.thePlayer = this.worldObject.getClosestPlayerToEntity(this.theWolf, (double) this.minPlayerDistance);
+ return this.thePlayer == null ? false : this.hasPlayerGotBoneInHand(this.thePlayer);
+ }
+
+ /**
+ * Returns whether an in-progress EntityAIBase should continue executing
+ */
+ public boolean continueExecuting() {
+ return !this.thePlayer.isEntityAlive() ? false
+ : (this.theWolf.getDistanceSqToEntity(
+ this.thePlayer) > (double) (this.minPlayerDistance * this.minPlayerDistance) ? false
+ : this.field_75384_e > 0 && this.hasPlayerGotBoneInHand(this.thePlayer));
+ }
+
+ /**
+ * Execute a one shot task or start executing a continuous task
+ */
+ public void startExecuting() {
+ this.theWolf.func_70918_i(true);
+ this.field_75384_e = 40 + this.theWolf.getRNG().nextInt(40);
+ }
+
+ /**
+ * Resets the task
+ */
+ public void resetTask() {
+ this.theWolf.func_70918_i(false);
+ this.thePlayer = null;
+ }
+
+ /**
+ * Updates the task
+ */
+ public void updateTask() {
+ this.theWolf.getLookHelper().setLookPosition(this.thePlayer.posX,
+ this.thePlayer.posY + (double) this.thePlayer.getEyeHeight(), this.thePlayer.posZ, 10.0F,
+ (float) this.theWolf.getVerticalFaceSpeed());
+ --this.field_75384_e;
+ }
+
+ /**
+ * Gets if the Player has the Bone in the hand.
+ */
+ private boolean hasPlayerGotBoneInHand(EntityPlayer par1EntityPlayer) {
+ ItemStack var2 = par1EntityPlayer.inventory.getCurrentItem();
+ return var2 == null ? false
+ : (!this.theWolf.isTamed() && var2.itemID == Item.bone.itemID ? true
+ : this.theWolf.isBreedingItem(var2));
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAIBreakDoor.java b/sp-server/src/main/java/net/minecraft/src/EntityAIBreakDoor.java
new file mode 100644
index 0000000..f82e42c
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAIBreakDoor.java
@@ -0,0 +1,74 @@
+package net.minecraft.src;
+
+public class EntityAIBreakDoor extends EntityAIDoorInteract {
+ private int breakingTime;
+ private int field_75358_j = -1;
+
+ public EntityAIBreakDoor(EntityLiving par1EntityLiving) {
+ super(par1EntityLiving);
+ }
+
+ /**
+ * Returns whether the EntityAIBase should begin execution.
+ */
+ public boolean shouldExecute() {
+ return !super.shouldExecute() ? false
+ : (!this.theEntity.worldObj.getGameRules().getGameRuleBooleanValue("mobGriefing") ? false
+ : !this.targetDoor.isDoorOpen(this.theEntity.worldObj, this.entityPosX, this.entityPosY,
+ this.entityPosZ));
+ }
+
+ /**
+ * Execute a one shot task or start executing a continuous task
+ */
+ public void startExecuting() {
+ super.startExecuting();
+ this.breakingTime = 0;
+ }
+
+ /**
+ * Returns whether an in-progress EntityAIBase should continue executing
+ */
+ public boolean continueExecuting() {
+ double var1 = this.theEntity.getDistanceSq((double) this.entityPosX, (double) this.entityPosY,
+ (double) this.entityPosZ);
+ return this.breakingTime <= 240 && !this.targetDoor.isDoorOpen(this.theEntity.worldObj, this.entityPosX,
+ this.entityPosY, this.entityPosZ) && var1 < 4.0D;
+ }
+
+ /**
+ * Resets the task
+ */
+ public void resetTask() {
+ super.resetTask();
+ this.theEntity.worldObj.destroyBlockInWorldPartially(this.theEntity.entityId, this.entityPosX, this.entityPosY,
+ this.entityPosZ, -1);
+ }
+
+ /**
+ * Updates the task
+ */
+ public void updateTask() {
+ super.updateTask();
+
+ if (this.theEntity.getRNG().nextInt(20) == 0) {
+ this.theEntity.worldObj.playAuxSFX(1010, this.entityPosX, this.entityPosY, this.entityPosZ, 0);
+ }
+
+ ++this.breakingTime;
+ int var1 = (int) ((float) this.breakingTime / 240.0F * 10.0F);
+
+ if (var1 != this.field_75358_j) {
+ this.theEntity.worldObj.destroyBlockInWorldPartially(this.theEntity.entityId, this.entityPosX,
+ this.entityPosY, this.entityPosZ, var1);
+ this.field_75358_j = var1;
+ }
+
+ if (this.breakingTime == 240 && this.theEntity.worldObj.difficultySetting == 3) {
+ this.theEntity.worldObj.setBlockToAir(this.entityPosX, this.entityPosY, this.entityPosZ);
+ this.theEntity.worldObj.playAuxSFX(1012, this.entityPosX, this.entityPosY, this.entityPosZ, 0);
+ this.theEntity.worldObj.playAuxSFX(2001, this.entityPosX, this.entityPosY, this.entityPosZ,
+ this.targetDoor.blockID);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAIControlledByPlayer.java b/sp-server/src/main/java/net/minecraft/src/EntityAIControlledByPlayer.java
new file mode 100644
index 0000000..b8fd495
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAIControlledByPlayer.java
@@ -0,0 +1,198 @@
+package net.minecraft.src;
+
+public class EntityAIControlledByPlayer extends EntityAIBase {
+ private final EntityLiving thisEntity;
+ private final float maxSpeed;
+ private float currentSpeed = 0.0F;
+
+ /** Whether the entity's speed is boosted. */
+ private boolean speedBoosted = false;
+
+ /**
+ * Counter for speed boosting, upon reaching maxSpeedBoostTime the speed boost
+ * will be disabled
+ */
+ private int speedBoostTime = 0;
+
+ /** Maximum time the entity's speed should be boosted for. */
+ private int maxSpeedBoostTime = 0;
+
+ public EntityAIControlledByPlayer(EntityLiving par1EntityLiving, float par2) {
+ this.thisEntity = par1EntityLiving;
+ this.maxSpeed = par2;
+ this.setMutexBits(7);
+ }
+
+ /**
+ * Execute a one shot task or start executing a continuous task
+ */
+ public void startExecuting() {
+ this.currentSpeed = 0.0F;
+ }
+
+ /**
+ * Resets the task
+ */
+ public void resetTask() {
+ this.speedBoosted = false;
+ this.currentSpeed = 0.0F;
+ }
+
+ /**
+ * Returns whether the EntityAIBase should begin execution.
+ */
+ public boolean shouldExecute() {
+ return this.thisEntity.isEntityAlive() && this.thisEntity.riddenByEntity != null
+ && this.thisEntity.riddenByEntity instanceof EntityPlayer
+ && (this.speedBoosted || this.thisEntity.canBeSteered());
+ }
+
+ /**
+ * Updates the task
+ */
+ public void updateTask() {
+ EntityPlayer var1 = (EntityPlayer) this.thisEntity.riddenByEntity;
+ EntityCreature var2 = (EntityCreature) this.thisEntity;
+ float var3 = MathHelper.wrapAngleTo180_float(var1.rotationYaw - this.thisEntity.rotationYaw) * 0.5F;
+
+ if (var3 > 5.0F) {
+ var3 = 5.0F;
+ }
+
+ if (var3 < -5.0F) {
+ var3 = -5.0F;
+ }
+
+ this.thisEntity.rotationYaw = MathHelper.wrapAngleTo180_float(this.thisEntity.rotationYaw + var3);
+
+ if (this.currentSpeed < this.maxSpeed) {
+ this.currentSpeed += (this.maxSpeed - this.currentSpeed) * 0.01F;
+ }
+
+ if (this.currentSpeed > this.maxSpeed) {
+ this.currentSpeed = this.maxSpeed;
+ }
+
+ int var4 = MathHelper.floor_double(this.thisEntity.posX);
+ int var5 = MathHelper.floor_double(this.thisEntity.posY);
+ int var6 = MathHelper.floor_double(this.thisEntity.posZ);
+ float var7 = this.currentSpeed;
+
+ if (this.speedBoosted) {
+ if (this.speedBoostTime++ > this.maxSpeedBoostTime) {
+ this.speedBoosted = false;
+ }
+
+ var7 += var7 * 1.15F
+ * MathHelper.sin((float) this.speedBoostTime / (float) this.maxSpeedBoostTime * (float) Math.PI);
+ }
+
+ float var8 = 0.91F;
+
+ if (this.thisEntity.onGround) {
+ var8 = 0.54600006F;
+ int var9 = this.thisEntity.worldObj.getBlockId(MathHelper.floor_float((float) var4),
+ MathHelper.floor_float((float) var5) - 1, MathHelper.floor_float((float) var6));
+
+ if (var9 > 0) {
+ var8 = Block.blocksList[var9].slipperiness * 0.91F;
+ }
+ }
+
+ float var23 = 0.16277136F / (var8 * var8 * var8);
+ float var10 = MathHelper.sin(var2.rotationYaw * (float) Math.PI / 180.0F);
+ float var11 = MathHelper.cos(var2.rotationYaw * (float) Math.PI / 180.0F);
+ float var12 = var2.getAIMoveSpeed() * var23;
+ float var13 = Math.max(var7, 1.0F);
+ var13 = var12 / var13;
+ float var14 = var7 * var13;
+ float var15 = -(var14 * var10);
+ float var16 = var14 * var11;
+
+ if (MathHelper.abs(var15) > MathHelper.abs(var16)) {
+ if (var15 < 0.0F) {
+ var15 -= this.thisEntity.width / 2.0F;
+ }
+
+ if (var15 > 0.0F) {
+ var15 += this.thisEntity.width / 2.0F;
+ }
+
+ var16 = 0.0F;
+ } else {
+ var15 = 0.0F;
+
+ if (var16 < 0.0F) {
+ var16 -= this.thisEntity.width / 2.0F;
+ }
+
+ if (var16 > 0.0F) {
+ var16 += this.thisEntity.width / 2.0F;
+ }
+ }
+
+ int var17 = MathHelper.floor_double(this.thisEntity.posX + (double) var15);
+ int var18 = MathHelper.floor_double(this.thisEntity.posZ + (double) var16);
+ PathPoint var19 = new PathPoint(MathHelper.floor_float(this.thisEntity.width + 1.0F),
+ MathHelper.floor_float(this.thisEntity.height + var1.height + 1.0F),
+ MathHelper.floor_float(this.thisEntity.width + 1.0F));
+
+ if (var4 != var17 || var6 != var18) {
+ int var20 = this.thisEntity.worldObj.getBlockId(var4, var5, var6);
+ int var21 = this.thisEntity.worldObj.getBlockId(var4, var5 - 1, var6);
+ boolean var22 = this.func_98216_b(var20) || Block.blocksList[var20] == null && this.func_98216_b(var21);
+
+ if (!var22 && PathFinder.func_82565_a(this.thisEntity, var17, var5, var18, var19, false, false, true) == 0
+ && PathFinder.func_82565_a(this.thisEntity, var4, var5 + 1, var6, var19, false, false, true) == 1
+ && PathFinder.func_82565_a(this.thisEntity, var17, var5 + 1, var18, var19, false, false,
+ true) == 1) {
+ var2.getJumpHelper().setJumping();
+ }
+ }
+
+ if (!var1.capabilities.isCreativeMode && this.currentSpeed >= this.maxSpeed * 0.5F
+ && this.thisEntity.getRNG().nextFloat() < 0.006F && !this.speedBoosted) {
+ ItemStack var24 = var1.getHeldItem();
+
+ if (var24 != null && var24.itemID == Item.carrotOnAStick.itemID) {
+ var24.damageItem(1, var1);
+
+ if (var24.stackSize == 0) {
+ ItemStack var25 = new ItemStack(Item.fishingRod);
+ var25.setTagCompound(var24.stackTagCompound);
+ var1.inventory.mainInventory[var1.inventory.currentItem] = var25;
+ }
+ }
+ }
+
+ this.thisEntity.moveEntityWithHeading(0.0F, var7);
+ }
+
+ private boolean func_98216_b(int par1) {
+ return Block.blocksList[par1] != null
+ && (Block.blocksList[par1].getRenderType() == 10 || Block.blocksList[par1] instanceof BlockHalfSlab);
+ }
+
+ /**
+ * Return whether the entity's speed is boosted.
+ */
+ public boolean isSpeedBoosted() {
+ return this.speedBoosted;
+ }
+
+ /**
+ * Boost the entity's movement speed.
+ */
+ public void boostSpeed() {
+ this.speedBoosted = true;
+ this.speedBoostTime = 0;
+ this.maxSpeedBoostTime = this.thisEntity.getRNG().nextInt(841) + 140;
+ }
+
+ /**
+ * Return whether the entity is being controlled by a player.
+ */
+ public boolean isControlledByPlayer() {
+ return !this.isSpeedBoosted() && this.currentSpeed > this.maxSpeed * 0.3F;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAICreeperSwell.java b/sp-server/src/main/java/net/minecraft/src/EntityAICreeperSwell.java
new file mode 100644
index 0000000..9e80db2
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAICreeperSwell.java
@@ -0,0 +1,56 @@
+package net.minecraft.src;
+
+public class EntityAICreeperSwell extends EntityAIBase {
+ /** The creeper that is swelling. */
+ EntityCreeper swellingCreeper;
+
+ /**
+ * The creeper's attack target. This is used for the changing of the creeper's
+ * state.
+ */
+ EntityLiving creeperAttackTarget;
+
+ public EntityAICreeperSwell(EntityCreeper par1EntityCreeper) {
+ this.swellingCreeper = par1EntityCreeper;
+ this.setMutexBits(1);
+ }
+
+ /**
+ * Returns whether the EntityAIBase should begin execution.
+ */
+ public boolean shouldExecute() {
+ EntityLiving var1 = this.swellingCreeper.getAttackTarget();
+ return this.swellingCreeper.getCreeperState() > 0
+ || var1 != null && this.swellingCreeper.getDistanceSqToEntity(var1) < 9.0D;
+ }
+
+ /**
+ * Execute a one shot task or start executing a continuous task
+ */
+ public void startExecuting() {
+ this.swellingCreeper.getNavigator().clearPathEntity();
+ this.creeperAttackTarget = this.swellingCreeper.getAttackTarget();
+ }
+
+ /**
+ * Resets the task
+ */
+ public void resetTask() {
+ this.creeperAttackTarget = null;
+ }
+
+ /**
+ * Updates the task
+ */
+ public void updateTask() {
+ if (this.creeperAttackTarget == null) {
+ this.swellingCreeper.setCreeperState(-1);
+ } else if (this.swellingCreeper.getDistanceSqToEntity(this.creeperAttackTarget) > 49.0D) {
+ this.swellingCreeper.setCreeperState(-1);
+ } else if (!this.swellingCreeper.getEntitySenses().canSee(this.creeperAttackTarget)) {
+ this.swellingCreeper.setCreeperState(-1);
+ } else {
+ this.swellingCreeper.setCreeperState(1);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAIDefendVillage.java b/sp-server/src/main/java/net/minecraft/src/EntityAIDefendVillage.java
new file mode 100644
index 0000000..bfa8121
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAIDefendVillage.java
@@ -0,0 +1,49 @@
+package net.minecraft.src;
+
+public class EntityAIDefendVillage extends EntityAITarget {
+ EntityIronGolem irongolem;
+
+ /**
+ * The aggressor of the iron golem's village which is now the golem's attack
+ * target.
+ */
+ EntityLiving villageAgressorTarget;
+
+ public EntityAIDefendVillage(EntityIronGolem par1EntityIronGolem) {
+ super(par1EntityIronGolem, 16.0F, false, true);
+ this.irongolem = par1EntityIronGolem;
+ this.setMutexBits(1);
+ }
+
+ /**
+ * Returns whether the EntityAIBase should begin execution.
+ */
+ public boolean shouldExecute() {
+ Village var1 = this.irongolem.getVillage();
+
+ if (var1 == null) {
+ return false;
+ } else {
+ this.villageAgressorTarget = var1.findNearestVillageAggressor(this.irongolem);
+
+ if (!this.isSuitableTarget(this.villageAgressorTarget, false)) {
+ if (this.taskOwner.getRNG().nextInt(20) == 0) {
+ this.villageAgressorTarget = var1.func_82685_c(this.irongolem);
+ return this.isSuitableTarget(this.villageAgressorTarget, false);
+ } else {
+ return false;
+ }
+ } else {
+ return true;
+ }
+ }
+ }
+
+ /**
+ * Execute a one shot task or start executing a continuous task
+ */
+ public void startExecuting() {
+ this.irongolem.setAttackTarget(this.villageAgressorTarget);
+ super.startExecuting();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAIDoorInteract.java b/sp-server/src/main/java/net/minecraft/src/EntityAIDoorInteract.java
new file mode 100644
index 0000000..4c3babf
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAIDoorInteract.java
@@ -0,0 +1,97 @@
+package net.minecraft.src;
+
+public abstract class EntityAIDoorInteract extends EntityAIBase {
+ protected EntityLiving theEntity;
+ protected int entityPosX;
+ protected int entityPosY;
+ protected int entityPosZ;
+ protected BlockDoor targetDoor;
+
+ /**
+ * If is true then the Entity has stopped Door Interaction and compoleted the
+ * task.
+ */
+ boolean hasStoppedDoorInteraction;
+ float entityPositionX;
+ float entityPositionZ;
+
+ public EntityAIDoorInteract(EntityLiving par1EntityLiving) {
+ this.theEntity = par1EntityLiving;
+ }
+
+ /**
+ * Returns whether the EntityAIBase should begin execution.
+ */
+ public boolean shouldExecute() {
+ if (!this.theEntity.isCollidedHorizontally) {
+ return false;
+ } else {
+ PathNavigate var1 = this.theEntity.getNavigator();
+ PathEntity var2 = var1.getPath();
+
+ if (var2 != null && !var2.isFinished() && var1.getCanBreakDoors()) {
+ for (int var3 = 0; var3 < Math.min(var2.getCurrentPathIndex() + 2,
+ var2.getCurrentPathLength()); ++var3) {
+ PathPoint var4 = var2.getPathPointFromIndex(var3);
+ this.entityPosX = var4.xCoord;
+ this.entityPosY = var4.yCoord + 1;
+ this.entityPosZ = var4.zCoord;
+
+ if (this.theEntity.getDistanceSq((double) this.entityPosX, this.theEntity.posY,
+ (double) this.entityPosZ) <= 2.25D) {
+ this.targetDoor = this.findUsableDoor(this.entityPosX, this.entityPosY, this.entityPosZ);
+
+ if (this.targetDoor != null) {
+ return true;
+ }
+ }
+ }
+
+ this.entityPosX = MathHelper.floor_double(this.theEntity.posX);
+ this.entityPosY = MathHelper.floor_double(this.theEntity.posY + 1.0D);
+ this.entityPosZ = MathHelper.floor_double(this.theEntity.posZ);
+ this.targetDoor = this.findUsableDoor(this.entityPosX, this.entityPosY, this.entityPosZ);
+ return this.targetDoor != null;
+ } else {
+ return false;
+ }
+ }
+ }
+
+ /**
+ * Returns whether an in-progress EntityAIBase should continue executing
+ */
+ public boolean continueExecuting() {
+ return !this.hasStoppedDoorInteraction;
+ }
+
+ /**
+ * Execute a one shot task or start executing a continuous task
+ */
+ public void startExecuting() {
+ this.hasStoppedDoorInteraction = false;
+ this.entityPositionX = (float) ((double) ((float) this.entityPosX + 0.5F) - this.theEntity.posX);
+ this.entityPositionZ = (float) ((double) ((float) this.entityPosZ + 0.5F) - this.theEntity.posZ);
+ }
+
+ /**
+ * Updates the task
+ */
+ public void updateTask() {
+ float var1 = (float) ((double) ((float) this.entityPosX + 0.5F) - this.theEntity.posX);
+ float var2 = (float) ((double) ((float) this.entityPosZ + 0.5F) - this.theEntity.posZ);
+ float var3 = this.entityPositionX * var1 + this.entityPositionZ * var2;
+
+ if (var3 < 0.0F) {
+ this.hasStoppedDoorInteraction = true;
+ }
+ }
+
+ /**
+ * Determines if a door can be broken with AI.
+ */
+ private BlockDoor findUsableDoor(int par1, int par2, int par3) {
+ int var4 = this.theEntity.worldObj.getBlockId(par1, par2, par3);
+ return var4 != Block.doorWood.blockID ? null : (BlockDoor) Block.blocksList[var4];
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAIEatGrass.java b/sp-server/src/main/java/net/minecraft/src/EntityAIEatGrass.java
new file mode 100644
index 0000000..8901170
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAIEatGrass.java
@@ -0,0 +1,80 @@
+package net.minecraft.src;
+
+public class EntityAIEatGrass extends EntityAIBase {
+ private EntityLiving theEntity;
+ private World theWorld;
+
+ /** A decrementing tick used for the sheep's head offset and animation. */
+ int eatGrassTick = 0;
+
+ public EntityAIEatGrass(EntityLiving par1EntityLiving) {
+ this.theEntity = par1EntityLiving;
+ this.theWorld = par1EntityLiving.worldObj;
+ this.setMutexBits(7);
+ }
+
+ /**
+ * Returns whether the EntityAIBase should begin execution.
+ */
+ public boolean shouldExecute() {
+ if (this.theEntity.getRNG().nextInt(this.theEntity.isChild() ? 50 : 1000) != 0) {
+ return false;
+ } else {
+ int var1 = MathHelper.floor_double(this.theEntity.posX);
+ int var2 = MathHelper.floor_double(this.theEntity.posY);
+ int var3 = MathHelper.floor_double(this.theEntity.posZ);
+ return this.theWorld.getBlockId(var1, var2, var3) == Block.tallGrass.blockID
+ && this.theWorld.getBlockMetadata(var1, var2, var3) == 1 ? true
+ : this.theWorld.getBlockId(var1, var2 - 1, var3) == Block.grass.blockID;
+ }
+ }
+
+ /**
+ * Execute a one shot task or start executing a continuous task
+ */
+ public void startExecuting() {
+ this.eatGrassTick = 40;
+ this.theWorld.setEntityState(this.theEntity, (byte) 10);
+ this.theEntity.getNavigator().clearPathEntity();
+ }
+
+ /**
+ * Resets the task
+ */
+ public void resetTask() {
+ this.eatGrassTick = 0;
+ }
+
+ /**
+ * Returns whether an in-progress EntityAIBase should continue executing
+ */
+ public boolean continueExecuting() {
+ return this.eatGrassTick > 0;
+ }
+
+ public int getEatGrassTick() {
+ return this.eatGrassTick;
+ }
+
+ /**
+ * Updates the task
+ */
+ public void updateTask() {
+ this.eatGrassTick = Math.max(0, this.eatGrassTick - 1);
+
+ if (this.eatGrassTick == 4) {
+ int var1 = MathHelper.floor_double(this.theEntity.posX);
+ int var2 = MathHelper.floor_double(this.theEntity.posY);
+ int var3 = MathHelper.floor_double(this.theEntity.posZ);
+
+ if (this.theWorld.getBlockId(var1, var2, var3) == Block.tallGrass.blockID) {
+ this.theWorld.destroyBlock(var1, var2, var3, false);
+ this.theEntity.eatGrassBonus();
+ } else if (this.theWorld.getBlockId(var1, var2 - 1, var3) == Block.grass.blockID) {
+ this.theWorld.playAuxSFX(2001, var1, var2 - 1, var3, Block.grass.blockID);
+ this.theWorld.setBlock(var1, var2 - 1, var3, Block.dirt.blockID, 0, 2);
+ this.theEntity.eatGrassBonus();
+ }
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAIFleeSun.java b/sp-server/src/main/java/net/minecraft/src/EntityAIFleeSun.java
new file mode 100644
index 0000000..cc2081e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAIFleeSun.java
@@ -0,0 +1,75 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class EntityAIFleeSun extends EntityAIBase {
+ private EntityCreature theCreature;
+ private double shelterX;
+ private double shelterY;
+ private double shelterZ;
+ private float movementSpeed;
+ private World theWorld;
+
+ public EntityAIFleeSun(EntityCreature par1EntityCreature, float par2) {
+ this.theCreature = par1EntityCreature;
+ this.movementSpeed = par2;
+ this.theWorld = par1EntityCreature.worldObj;
+ this.setMutexBits(1);
+ }
+
+ /**
+ * Returns whether the EntityAIBase should begin execution.
+ */
+ public boolean shouldExecute() {
+ if (!this.theWorld.isDaytime()) {
+ return false;
+ } else if (!this.theCreature.isBurning()) {
+ return false;
+ } else if (!this.theWorld.canBlockSeeTheSky(MathHelper.floor_double(this.theCreature.posX),
+ (int) this.theCreature.boundingBox.minY, MathHelper.floor_double(this.theCreature.posZ))) {
+ return false;
+ } else {
+ Vec3 var1 = this.findPossibleShelter();
+
+ if (var1 == null) {
+ return false;
+ } else {
+ this.shelterX = var1.xCoord;
+ this.shelterY = var1.yCoord;
+ this.shelterZ = var1.zCoord;
+ return true;
+ }
+ }
+ }
+
+ /**
+ * Returns whether an in-progress EntityAIBase should continue executing
+ */
+ public boolean continueExecuting() {
+ return !this.theCreature.getNavigator().noPath();
+ }
+
+ /**
+ * Execute a one shot task or start executing a continuous task
+ */
+ public void startExecuting() {
+ this.theCreature.getNavigator().tryMoveToXYZ(this.shelterX, this.shelterY, this.shelterZ, this.movementSpeed);
+ }
+
+ private Vec3 findPossibleShelter() {
+ EaglercraftRandom var1 = this.theCreature.getRNG();
+
+ for (int var2 = 0; var2 < 10; ++var2) {
+ int var3 = MathHelper.floor_double(this.theCreature.posX + (double) var1.nextInt(20) - 10.0D);
+ int var4 = MathHelper.floor_double(this.theCreature.boundingBox.minY + (double) var1.nextInt(6) - 3.0D);
+ int var5 = MathHelper.floor_double(this.theCreature.posZ + (double) var1.nextInt(20) - 10.0D);
+
+ if (!this.theWorld.canBlockSeeTheSky(var3, var4, var5)
+ && this.theCreature.getBlockPathWeight(var3, var4, var5) < 0.0F) {
+ return this.theWorld.getWorldVec3Pool().getVecFromPool((double) var3, (double) var4, (double) var5);
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAIFollowGolem.java b/sp-server/src/main/java/net/minecraft/src/EntityAIFollowGolem.java
new file mode 100644
index 0000000..34acc6b
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAIFollowGolem.java
@@ -0,0 +1,88 @@
+package net.minecraft.src;
+
+import java.util.Iterator;
+import java.util.List;
+
+public class EntityAIFollowGolem extends EntityAIBase {
+ private EntityVillager theVillager;
+ private EntityIronGolem theGolem;
+ private int takeGolemRoseTick;
+ private boolean tookGolemRose = false;
+
+ public EntityAIFollowGolem(EntityVillager par1EntityVillager) {
+ this.theVillager = par1EntityVillager;
+ this.setMutexBits(3);
+ }
+
+ /**
+ * Returns whether the EntityAIBase should begin execution.
+ */
+ public boolean shouldExecute() {
+ if (this.theVillager.getGrowingAge() >= 0) {
+ return false;
+ } else if (!this.theVillager.worldObj.isDaytime()) {
+ return false;
+ } else {
+ List var1 = this.theVillager.worldObj.getEntitiesWithinAABB(EntityIronGolem.class,
+ this.theVillager.boundingBox.expand(6.0D, 2.0D, 6.0D));
+
+ if (var1.isEmpty()) {
+ return false;
+ } else {
+ Iterator var2 = var1.iterator();
+
+ while (var2.hasNext()) {
+ EntityIronGolem var3 = (EntityIronGolem) var2.next();
+
+ if (var3.getHoldRoseTick() > 0) {
+ this.theGolem = var3;
+ break;
+ }
+ }
+
+ return this.theGolem != null;
+ }
+ }
+ }
+
+ /**
+ * Returns whether an in-progress EntityAIBase should continue executing
+ */
+ public boolean continueExecuting() {
+ return this.theGolem.getHoldRoseTick() > 0;
+ }
+
+ /**
+ * Execute a one shot task or start executing a continuous task
+ */
+ public void startExecuting() {
+ this.takeGolemRoseTick = this.theVillager.getRNG().nextInt(320);
+ this.tookGolemRose = false;
+ this.theGolem.getNavigator().clearPathEntity();
+ }
+
+ /**
+ * Resets the task
+ */
+ public void resetTask() {
+ this.theGolem = null;
+ this.theVillager.getNavigator().clearPathEntity();
+ }
+
+ /**
+ * Updates the task
+ */
+ public void updateTask() {
+ this.theVillager.getLookHelper().setLookPositionWithEntity(this.theGolem, 30.0F, 30.0F);
+
+ if (this.theGolem.getHoldRoseTick() == this.takeGolemRoseTick) {
+ this.theVillager.getNavigator().tryMoveToEntityLiving(this.theGolem, 0.15F);
+ this.tookGolemRose = true;
+ }
+
+ if (this.tookGolemRose && this.theVillager.getDistanceSqToEntity(this.theGolem) < 4.0D) {
+ this.theGolem.setHoldingRose(false);
+ this.theVillager.getNavigator().clearPathEntity();
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAIFollowOwner.java b/sp-server/src/main/java/net/minecraft/src/EntityAIFollowOwner.java
new file mode 100644
index 0000000..bff6142
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAIFollowOwner.java
@@ -0,0 +1,106 @@
+package net.minecraft.src;
+
+public class EntityAIFollowOwner extends EntityAIBase {
+ private EntityTameable thePet;
+ private EntityLiving theOwner;
+ World theWorld;
+ private float field_75336_f;
+ private PathNavigate petPathfinder;
+ private int field_75343_h;
+ float maxDist;
+ float minDist;
+ private boolean field_75344_i;
+
+ public EntityAIFollowOwner(EntityTameable par1EntityTameable, float par2, float par3, float par4) {
+ this.thePet = par1EntityTameable;
+ this.theWorld = par1EntityTameable.worldObj;
+ this.field_75336_f = par2;
+ this.petPathfinder = par1EntityTameable.getNavigator();
+ this.minDist = par3;
+ this.maxDist = par4;
+ this.setMutexBits(3);
+ }
+
+ /**
+ * Returns whether the EntityAIBase should begin execution.
+ */
+ public boolean shouldExecute() {
+ EntityLiving var1 = this.thePet.getOwner();
+
+ if (var1 == null) {
+ return false;
+ } else if (this.thePet.isSitting()) {
+ return false;
+ } else if (this.thePet.getDistanceSqToEntity(var1) < (double) (this.minDist * this.minDist)) {
+ return false;
+ } else {
+ this.theOwner = var1;
+ return true;
+ }
+ }
+
+ /**
+ * Returns whether an in-progress EntityAIBase should continue executing
+ */
+ public boolean continueExecuting() {
+ return !this.petPathfinder.noPath()
+ && this.thePet.getDistanceSqToEntity(this.theOwner) > (double) (this.maxDist * this.maxDist)
+ && !this.thePet.isSitting();
+ }
+
+ /**
+ * Execute a one shot task or start executing a continuous task
+ */
+ public void startExecuting() {
+ this.field_75343_h = 0;
+ this.field_75344_i = this.thePet.getNavigator().getAvoidsWater();
+ this.thePet.getNavigator().setAvoidsWater(false);
+ }
+
+ /**
+ * Resets the task
+ */
+ public void resetTask() {
+ this.theOwner = null;
+ this.petPathfinder.clearPathEntity();
+ this.thePet.getNavigator().setAvoidsWater(this.field_75344_i);
+ }
+
+ /**
+ * Updates the task
+ */
+ public void updateTask() {
+ this.thePet.getLookHelper().setLookPositionWithEntity(this.theOwner, 10.0F,
+ (float) this.thePet.getVerticalFaceSpeed());
+
+ if (!this.thePet.isSitting()) {
+ if (--this.field_75343_h <= 0) {
+ this.field_75343_h = 10;
+
+ if (!this.petPathfinder.tryMoveToEntityLiving(this.theOwner, this.field_75336_f)) {
+ if (this.thePet.getDistanceSqToEntity(this.theOwner) >= 144.0D) {
+ int var1 = MathHelper.floor_double(this.theOwner.posX) - 2;
+ int var2 = MathHelper.floor_double(this.theOwner.posZ) - 2;
+ int var3 = MathHelper.floor_double(this.theOwner.boundingBox.minY);
+
+ for (int var4 = 0; var4 <= 4; ++var4) {
+ for (int var5 = 0; var5 <= 4; ++var5) {
+ if ((var4 < 1 || var5 < 1 || var4 > 3 || var5 > 3)
+ && this.theWorld.doesBlockHaveSolidTopSurface(var1 + var4, var3 - 1,
+ var2 + var5)
+ && !this.theWorld.isBlockNormalCube(var1 + var4, var3, var2 + var5)
+ && !this.theWorld.isBlockNormalCube(var1 + var4, var3 + 1, var2 + var5)) {
+ this.thePet.setLocationAndAngles((double) ((float) (var1 + var4) + 0.5F),
+ (double) var3, (double) ((float) (var2 + var5) + 0.5F),
+ this.thePet.rotationYaw, this.thePet.rotationPitch);
+ this.petPathfinder.clearPathEntity();
+ return;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAIFollowParent.java b/sp-server/src/main/java/net/minecraft/src/EntityAIFollowParent.java
new file mode 100644
index 0000000..5d4d9e1
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAIFollowParent.java
@@ -0,0 +1,90 @@
+package net.minecraft.src;
+
+import java.util.Iterator;
+import java.util.List;
+
+public class EntityAIFollowParent extends EntityAIBase {
+ /** The child that is following its parent. */
+ EntityAnimal childAnimal;
+ EntityAnimal parentAnimal;
+ float field_75347_c;
+ private int field_75345_d;
+
+ public EntityAIFollowParent(EntityAnimal par1EntityAnimal, float par2) {
+ this.childAnimal = par1EntityAnimal;
+ this.field_75347_c = par2;
+ }
+
+ /**
+ * Returns whether the EntityAIBase should begin execution.
+ */
+ public boolean shouldExecute() {
+ if (this.childAnimal.getGrowingAge() >= 0) {
+ return false;
+ } else {
+ List var1 = this.childAnimal.worldObj.getEntitiesWithinAABB(this.childAnimal.getClass(),
+ this.childAnimal.boundingBox.expand(8.0D, 4.0D, 8.0D));
+ EntityAnimal var2 = null;
+ double var3 = Double.MAX_VALUE;
+ Iterator var5 = var1.iterator();
+
+ while (var5.hasNext()) {
+ EntityAnimal var6 = (EntityAnimal) var5.next();
+
+ if (var6.getGrowingAge() >= 0) {
+ double var7 = this.childAnimal.getDistanceSqToEntity(var6);
+
+ if (var7 <= var3) {
+ var3 = var7;
+ var2 = var6;
+ }
+ }
+ }
+
+ if (var2 == null) {
+ return false;
+ } else if (var3 < 9.0D) {
+ return false;
+ } else {
+ this.parentAnimal = var2;
+ return true;
+ }
+ }
+ }
+
+ /**
+ * Returns whether an in-progress EntityAIBase should continue executing
+ */
+ public boolean continueExecuting() {
+ if (!this.parentAnimal.isEntityAlive()) {
+ return false;
+ } else {
+ double var1 = this.childAnimal.getDistanceSqToEntity(this.parentAnimal);
+ return var1 >= 9.0D && var1 <= 256.0D;
+ }
+ }
+
+ /**
+ * Execute a one shot task or start executing a continuous task
+ */
+ public void startExecuting() {
+ this.field_75345_d = 0;
+ }
+
+ /**
+ * Resets the task
+ */
+ public void resetTask() {
+ this.parentAnimal = null;
+ }
+
+ /**
+ * Updates the task
+ */
+ public void updateTask() {
+ if (--this.field_75345_d <= 0) {
+ this.field_75345_d = 10;
+ this.childAnimal.getNavigator().tryMoveToEntityLiving(this.parentAnimal, this.field_75347_c);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAIHurtByTarget.java b/sp-server/src/main/java/net/minecraft/src/EntityAIHurtByTarget.java
new file mode 100644
index 0000000..feee351
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAIHurtByTarget.java
@@ -0,0 +1,68 @@
+package net.minecraft.src;
+
+import java.util.Iterator;
+import java.util.List;
+
+public class EntityAIHurtByTarget extends EntityAITarget {
+ boolean field_75312_a;
+
+ /** The PathNavigate of our entity. */
+ EntityLiving entityPathNavigate;
+
+ public EntityAIHurtByTarget(EntityLiving par1EntityLiving, boolean par2) {
+ super(par1EntityLiving, 16.0F, false);
+ this.field_75312_a = par2;
+ this.setMutexBits(1);
+ }
+
+ /**
+ * Returns whether the EntityAIBase should begin execution.
+ */
+ public boolean shouldExecute() {
+ return this.isSuitableTarget(this.taskOwner.getAITarget(), true);
+ }
+
+ /**
+ * Returns whether an in-progress EntityAIBase should continue executing
+ */
+ public boolean continueExecuting() {
+ return this.taskOwner.getAITarget() != null && this.taskOwner.getAITarget() != this.entityPathNavigate;
+ }
+
+ /**
+ * Execute a one shot task or start executing a continuous task
+ */
+ public void startExecuting() {
+ this.taskOwner.setAttackTarget(this.taskOwner.getAITarget());
+ this.entityPathNavigate = this.taskOwner.getAITarget();
+
+ if (this.field_75312_a) {
+ List var1 = this.taskOwner.worldObj.getEntitiesWithinAABB(this.taskOwner.getClass(),
+ AxisAlignedBB.getAABBPool()
+ .getAABB(this.taskOwner.posX, this.taskOwner.posY, this.taskOwner.posZ,
+ this.taskOwner.posX + 1.0D, this.taskOwner.posY + 1.0D, this.taskOwner.posZ + 1.0D)
+ .expand((double) this.targetDistance, 10.0D, (double) this.targetDistance));
+ Iterator var2 = var1.iterator();
+
+ while (var2.hasNext()) {
+ EntityLiving var3 = (EntityLiving) var2.next();
+
+ if (this.taskOwner != var3 && var3.getAttackTarget() == null) {
+ var3.setAttackTarget(this.taskOwner.getAITarget());
+ }
+ }
+ }
+
+ super.startExecuting();
+ }
+
+ /**
+ * Resets the task
+ */
+ public void resetTask() {
+ if (this.taskOwner.getAttackTarget() != null && this.taskOwner.getAttackTarget() instanceof EntityPlayer
+ && ((EntityPlayer) this.taskOwner.getAttackTarget()).capabilities.disableDamage) {
+ super.resetTask();
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAILeapAtTarget.java b/sp-server/src/main/java/net/minecraft/src/EntityAILeapAtTarget.java
new file mode 100644
index 0000000..83cdcde
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAILeapAtTarget.java
@@ -0,0 +1,55 @@
+package net.minecraft.src;
+
+public class EntityAILeapAtTarget extends EntityAIBase {
+ /** The entity that is leaping. */
+ EntityLiving leaper;
+
+ /** The entity that the leaper is leaping towards. */
+ EntityLiving leapTarget;
+
+ /** The entity's motionY after leaping. */
+ float leapMotionY;
+
+ public EntityAILeapAtTarget(EntityLiving par1EntityLiving, float par2) {
+ this.leaper = par1EntityLiving;
+ this.leapMotionY = par2;
+ this.setMutexBits(5);
+ }
+
+ /**
+ * Returns whether the EntityAIBase should begin execution.
+ */
+ public boolean shouldExecute() {
+ this.leapTarget = this.leaper.getAttackTarget();
+
+ if (this.leapTarget == null) {
+ return false;
+ } else {
+ double var1 = this.leaper.getDistanceSqToEntity(this.leapTarget);
+ return var1 >= 4.0D && var1 <= 16.0D
+ ? (!this.leaper.onGround ? false : this.leaper.getRNG().nextInt(5) == 0)
+ : false;
+ }
+ }
+
+ /**
+ * Returns whether an in-progress EntityAIBase should continue executing
+ */
+ public boolean continueExecuting() {
+ return !this.leaper.onGround;
+ }
+
+ /**
+ * Execute a one shot task or start executing a continuous task
+ */
+ public void startExecuting() {
+ double var1 = this.leapTarget.posX - this.leaper.posX;
+ double var3 = this.leapTarget.posZ - this.leaper.posZ;
+ float var5 = MathHelper.sqrt_double(var1 * var1 + var3 * var3);
+ this.leaper.motionX += var1 / (double) var5 * 0.5D * 0.800000011920929D
+ + this.leaper.motionX * 0.20000000298023224D;
+ this.leaper.motionZ += var3 / (double) var5 * 0.5D * 0.800000011920929D
+ + this.leaper.motionZ * 0.20000000298023224D;
+ this.leaper.motionY = (double) this.leapMotionY;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAILookAtTradePlayer.java b/sp-server/src/main/java/net/minecraft/src/EntityAILookAtTradePlayer.java
new file mode 100644
index 0000000..c0d438a
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAILookAtTradePlayer.java
@@ -0,0 +1,22 @@
+package net.minecraft.src;
+
+public class EntityAILookAtTradePlayer extends EntityAIWatchClosest {
+ private final EntityVillager theMerchant;
+
+ public EntityAILookAtTradePlayer(EntityVillager par1EntityVillager) {
+ super(par1EntityVillager, EntityPlayer.class, 8.0F);
+ this.theMerchant = par1EntityVillager;
+ }
+
+ /**
+ * Returns whether the EntityAIBase should begin execution.
+ */
+ public boolean shouldExecute() {
+ if (this.theMerchant.isTrading()) {
+ this.closestEntity = this.theMerchant.getCustomer();
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAILookAtVillager.java b/sp-server/src/main/java/net/minecraft/src/EntityAILookAtVillager.java
new file mode 100644
index 0000000..37c4ab5
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAILookAtVillager.java
@@ -0,0 +1,58 @@
+package net.minecraft.src;
+
+public class EntityAILookAtVillager extends EntityAIBase {
+ private EntityIronGolem theGolem;
+ private EntityVillager theVillager;
+ private int lookTime;
+
+ public EntityAILookAtVillager(EntityIronGolem par1EntityIronGolem) {
+ this.theGolem = par1EntityIronGolem;
+ this.setMutexBits(3);
+ }
+
+ /**
+ * Returns whether the EntityAIBase should begin execution.
+ */
+ public boolean shouldExecute() {
+ if (!this.theGolem.worldObj.isDaytime()) {
+ return false;
+ } else if (this.theGolem.getRNG().nextInt(8000) != 0) {
+ return false;
+ } else {
+ this.theVillager = (EntityVillager) this.theGolem.worldObj.findNearestEntityWithinAABB(EntityVillager.class,
+ this.theGolem.boundingBox.expand(6.0D, 2.0D, 6.0D), this.theGolem);
+ return this.theVillager != null;
+ }
+ }
+
+ /**
+ * Returns whether an in-progress EntityAIBase should continue executing
+ */
+ public boolean continueExecuting() {
+ return this.lookTime > 0;
+ }
+
+ /**
+ * Execute a one shot task or start executing a continuous task
+ */
+ public void startExecuting() {
+ this.lookTime = 400;
+ this.theGolem.setHoldingRose(true);
+ }
+
+ /**
+ * Resets the task
+ */
+ public void resetTask() {
+ this.theGolem.setHoldingRose(false);
+ this.theVillager = null;
+ }
+
+ /**
+ * Updates the task
+ */
+ public void updateTask() {
+ this.theGolem.getLookHelper().setLookPositionWithEntity(this.theVillager, 30.0F, 30.0F);
+ --this.lookTime;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAILookIdle.java b/sp-server/src/main/java/net/minecraft/src/EntityAILookIdle.java
new file mode 100644
index 0000000..2e49999
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAILookIdle.java
@@ -0,0 +1,56 @@
+package net.minecraft.src;
+
+public class EntityAILookIdle extends EntityAIBase {
+ /** The entity that is looking idle. */
+ private EntityLiving idleEntity;
+
+ /** X offset to look at */
+ private double lookX;
+
+ /** Z offset to look at */
+ private double lookZ;
+
+ /**
+ * A decrementing tick that stops the entity from being idle once it reaches 0.
+ */
+ private int idleTime = 0;
+
+ public EntityAILookIdle(EntityLiving par1EntityLiving) {
+ this.idleEntity = par1EntityLiving;
+ this.setMutexBits(3);
+ }
+
+ /**
+ * Returns whether the EntityAIBase should begin execution.
+ */
+ public boolean shouldExecute() {
+ return this.idleEntity.getRNG().nextFloat() < 0.02F;
+ }
+
+ /**
+ * Returns whether an in-progress EntityAIBase should continue executing
+ */
+ public boolean continueExecuting() {
+ return this.idleTime >= 0;
+ }
+
+ /**
+ * Execute a one shot task or start executing a continuous task
+ */
+ public void startExecuting() {
+ double var1 = (Math.PI * 2D) * this.idleEntity.getRNG().nextDouble();
+ this.lookX = Math.cos(var1);
+ this.lookZ = Math.sin(var1);
+ this.idleTime = 20 + this.idleEntity.getRNG().nextInt(20);
+ }
+
+ /**
+ * Updates the task
+ */
+ public void updateTask() {
+ --this.idleTime;
+ this.idleEntity.getLookHelper().setLookPosition(this.idleEntity.posX + this.lookX,
+ this.idleEntity.posY + (double) this.idleEntity.getEyeHeight(), this.idleEntity.posZ + this.lookZ,
+ 10.0F, (float) this.idleEntity.getVerticalFaceSpeed());
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAIMate.java b/sp-server/src/main/java/net/minecraft/src/EntityAIMate.java
new file mode 100644
index 0000000..74deb71
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAIMate.java
@@ -0,0 +1,127 @@
+package net.minecraft.src;
+
+import java.util.Iterator;
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class EntityAIMate extends EntityAIBase {
+ private EntityAnimal theAnimal;
+ World theWorld;
+ private EntityAnimal targetMate;
+
+ /**
+ * Delay preventing a baby from spawning immediately when two mate-able animals
+ * find each other.
+ */
+ int spawnBabyDelay = 0;
+
+ /** The speed the creature moves at during mating behavior. */
+ float moveSpeed;
+
+ public EntityAIMate(EntityAnimal par1EntityAnimal, float par2) {
+ this.theAnimal = par1EntityAnimal;
+ this.theWorld = par1EntityAnimal.worldObj;
+ this.moveSpeed = par2;
+ this.setMutexBits(3);
+ }
+
+ /**
+ * Returns whether the EntityAIBase should begin execution.
+ */
+ public boolean shouldExecute() {
+ if (!this.theAnimal.isInLove()) {
+ return false;
+ } else {
+ this.targetMate = this.getNearbyMate();
+ return this.targetMate != null;
+ }
+ }
+
+ /**
+ * Returns whether an in-progress EntityAIBase should continue executing
+ */
+ public boolean continueExecuting() {
+ return this.targetMate.isEntityAlive() && this.targetMate.isInLove() && this.spawnBabyDelay < 60;
+ }
+
+ /**
+ * Resets the task
+ */
+ public void resetTask() {
+ this.targetMate = null;
+ this.spawnBabyDelay = 0;
+ }
+
+ /**
+ * Updates the task
+ */
+ public void updateTask() {
+ this.theAnimal.getLookHelper().setLookPositionWithEntity(this.targetMate, 10.0F,
+ (float) this.theAnimal.getVerticalFaceSpeed());
+ this.theAnimal.getNavigator().tryMoveToEntityLiving(this.targetMate, this.moveSpeed);
+ ++this.spawnBabyDelay;
+
+ if (this.spawnBabyDelay >= 60 && this.theAnimal.getDistanceSqToEntity(this.targetMate) < 9.0D) {
+ this.spawnBaby();
+ }
+ }
+
+ /**
+ * Loops through nearby animals and finds another animal of the same type that
+ * can be mated with. Returns the first valid mate found.
+ */
+ private EntityAnimal getNearbyMate() {
+ float var1 = 8.0F;
+ List var2 = this.theWorld.getEntitiesWithinAABB(this.theAnimal.getClass(),
+ this.theAnimal.boundingBox.expand((double) var1, (double) var1, (double) var1));
+ double var3 = Double.MAX_VALUE;
+ EntityAnimal var5 = null;
+ Iterator var6 = var2.iterator();
+
+ while (var6.hasNext()) {
+ EntityAnimal var7 = (EntityAnimal) var6.next();
+
+ if (this.theAnimal.canMateWith(var7) && this.theAnimal.getDistanceSqToEntity(var7) < var3) {
+ var5 = var7;
+ var3 = this.theAnimal.getDistanceSqToEntity(var7);
+ }
+ }
+
+ return var5;
+ }
+
+ /**
+ * Spawns a baby animal of the same type.
+ */
+ private void spawnBaby() {
+ EntityAgeable var1 = this.theAnimal.createChild(this.targetMate);
+
+ if (var1 != null) {
+ this.theAnimal.setGrowingAge(6000);
+ this.targetMate.setGrowingAge(6000);
+ this.theAnimal.resetInLove();
+ this.targetMate.resetInLove();
+ var1.setGrowingAge(-24000);
+ var1.setLocationAndAngles(this.theAnimal.posX, this.theAnimal.posY, this.theAnimal.posZ, 0.0F, 0.0F);
+ this.theWorld.spawnEntityInWorld(var1);
+ EaglercraftRandom var2 = this.theAnimal.getRNG();
+
+ for (int var3 = 0; var3 < 7; ++var3) {
+ double var4 = var2.nextGaussian() * 0.02D;
+ double var6 = var2.nextGaussian() * 0.02D;
+ double var8 = var2.nextGaussian() * 0.02D;
+ this.theWorld.spawnParticle("heart",
+ this.theAnimal.posX + (double) (var2.nextFloat() * this.theAnimal.width * 2.0F)
+ - (double) this.theAnimal.width,
+ this.theAnimal.posY + 0.5D + (double) (var2.nextFloat() * this.theAnimal.height),
+ this.theAnimal.posZ + (double) (var2.nextFloat() * this.theAnimal.width * 2.0F)
+ - (double) this.theAnimal.width,
+ var4, var6, var8);
+ }
+
+ this.theWorld.spawnEntityInWorld(new EntityXPOrb(this.theWorld, this.theAnimal.posX, this.theAnimal.posY,
+ this.theAnimal.posZ, var2.nextInt(7) + 1));
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAIMoveIndoors.java b/sp-server/src/main/java/net/minecraft/src/EntityAIMoveIndoors.java
new file mode 100644
index 0000000..a12ba6a
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAIMoveIndoors.java
@@ -0,0 +1,80 @@
+package net.minecraft.src;
+
+public class EntityAIMoveIndoors extends EntityAIBase {
+ private EntityCreature entityObj;
+ private VillageDoorInfo doorInfo;
+ private int insidePosX = -1;
+ private int insidePosZ = -1;
+
+ public EntityAIMoveIndoors(EntityCreature par1EntityCreature) {
+ this.entityObj = par1EntityCreature;
+ this.setMutexBits(1);
+ }
+
+ /**
+ * Returns whether the EntityAIBase should begin execution.
+ */
+ public boolean shouldExecute() {
+ if ((!this.entityObj.worldObj.isDaytime() || this.entityObj.worldObj.isRaining())
+ && !this.entityObj.worldObj.provider.hasNoSky) {
+ if (this.entityObj.getRNG().nextInt(50) != 0) {
+ return false;
+ } else if (this.insidePosX != -1 && this.entityObj.getDistanceSq((double) this.insidePosX,
+ this.entityObj.posY, (double) this.insidePosZ) < 4.0D) {
+ return false;
+ } else {
+ Village var1 = this.entityObj.worldObj.villageCollectionObj.findNearestVillage(
+ MathHelper.floor_double(this.entityObj.posX), MathHelper.floor_double(this.entityObj.posY),
+ MathHelper.floor_double(this.entityObj.posZ), 14);
+
+ if (var1 == null) {
+ return false;
+ } else {
+ this.doorInfo = var1.findNearestDoorUnrestricted(MathHelper.floor_double(this.entityObj.posX),
+ MathHelper.floor_double(this.entityObj.posY), MathHelper.floor_double(this.entityObj.posZ));
+ return this.doorInfo != null;
+ }
+ }
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Returns whether an in-progress EntityAIBase should continue executing
+ */
+ public boolean continueExecuting() {
+ return !this.entityObj.getNavigator().noPath();
+ }
+
+ /**
+ * Execute a one shot task or start executing a continuous task
+ */
+ public void startExecuting() {
+ this.insidePosX = -1;
+
+ if (this.entityObj.getDistanceSq((double) this.doorInfo.getInsidePosX(), (double) this.doorInfo.posY,
+ (double) this.doorInfo.getInsidePosZ()) > 256.0D) {
+ Vec3 var1 = RandomPositionGenerator.findRandomTargetBlockTowards(this.entityObj, 14, 3,
+ this.entityObj.worldObj.getWorldVec3Pool().getVecFromPool(
+ (double) this.doorInfo.getInsidePosX() + 0.5D, (double) this.doorInfo.getInsidePosY(),
+ (double) this.doorInfo.getInsidePosZ() + 0.5D));
+
+ if (var1 != null) {
+ this.entityObj.getNavigator().tryMoveToXYZ(var1.xCoord, var1.yCoord, var1.zCoord, 0.3F);
+ }
+ } else {
+ this.entityObj.getNavigator().tryMoveToXYZ((double) this.doorInfo.getInsidePosX() + 0.5D,
+ (double) this.doorInfo.getInsidePosY(), (double) this.doorInfo.getInsidePosZ() + 0.5D, 0.3F);
+ }
+ }
+
+ /**
+ * Resets the task
+ */
+ public void resetTask() {
+ this.insidePosX = this.doorInfo.getInsidePosX();
+ this.insidePosZ = this.doorInfo.getInsidePosZ();
+ this.doorInfo = null;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAIMoveThroughVillage.java b/sp-server/src/main/java/net/minecraft/src/EntityAIMoveThroughVillage.java
new file mode 100644
index 0000000..c785df2
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAIMoveThroughVillage.java
@@ -0,0 +1,144 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+public class EntityAIMoveThroughVillage extends EntityAIBase {
+ private EntityCreature theEntity;
+ private float movementSpeed;
+
+ /** The PathNavigate of our entity. */
+ private PathEntity entityPathNavigate;
+ private VillageDoorInfo doorInfo;
+ private boolean isNocturnal;
+ private List doorList = new ArrayList();
+
+ public EntityAIMoveThroughVillage(EntityCreature par1EntityCreature, float par2, boolean par3) {
+ this.theEntity = par1EntityCreature;
+ this.movementSpeed = par2;
+ this.isNocturnal = par3;
+ this.setMutexBits(1);
+ }
+
+ /**
+ * Returns whether the EntityAIBase should begin execution.
+ */
+ public boolean shouldExecute() {
+ this.func_75414_f();
+
+ if (this.isNocturnal && this.theEntity.worldObj.isDaytime()) {
+ return false;
+ } else {
+ Village var1 = this.theEntity.worldObj.villageCollectionObj.findNearestVillage(
+ MathHelper.floor_double(this.theEntity.posX), MathHelper.floor_double(this.theEntity.posY),
+ MathHelper.floor_double(this.theEntity.posZ), 0);
+
+ if (var1 == null) {
+ return false;
+ } else {
+ this.doorInfo = this.func_75412_a(var1);
+
+ if (this.doorInfo == null) {
+ return false;
+ } else {
+ boolean var2 = this.theEntity.getNavigator().getCanBreakDoors();
+ this.theEntity.getNavigator().setBreakDoors(false);
+ this.entityPathNavigate = this.theEntity.getNavigator().getPathToXYZ((double) this.doorInfo.posX,
+ (double) this.doorInfo.posY, (double) this.doorInfo.posZ);
+ this.theEntity.getNavigator().setBreakDoors(var2);
+
+ if (this.entityPathNavigate != null) {
+ return true;
+ } else {
+ Vec3 var3 = RandomPositionGenerator.findRandomTargetBlockTowards(this.theEntity, 10, 7,
+ this.theEntity.worldObj.getWorldVec3Pool().getVecFromPool((double) this.doorInfo.posX,
+ (double) this.doorInfo.posY, (double) this.doorInfo.posZ));
+
+ if (var3 == null) {
+ return false;
+ } else {
+ this.theEntity.getNavigator().setBreakDoors(false);
+ this.entityPathNavigate = this.theEntity.getNavigator().getPathToXYZ(var3.xCoord,
+ var3.yCoord, var3.zCoord);
+ this.theEntity.getNavigator().setBreakDoors(var2);
+ return this.entityPathNavigate != null;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns whether an in-progress EntityAIBase should continue executing
+ */
+ public boolean continueExecuting() {
+ if (this.theEntity.getNavigator().noPath()) {
+ return false;
+ } else {
+ float var1 = this.theEntity.width + 4.0F;
+ return this.theEntity.getDistanceSq((double) this.doorInfo.posX, (double) this.doorInfo.posY,
+ (double) this.doorInfo.posZ) > (double) (var1 * var1);
+ }
+ }
+
+ /**
+ * Execute a one shot task or start executing a continuous task
+ */
+ public void startExecuting() {
+ this.theEntity.getNavigator().setPath(this.entityPathNavigate, this.movementSpeed);
+ }
+
+ /**
+ * Resets the task
+ */
+ public void resetTask() {
+ if (this.theEntity.getNavigator().noPath() || this.theEntity.getDistanceSq((double) this.doorInfo.posX,
+ (double) this.doorInfo.posY, (double) this.doorInfo.posZ) < 16.0D) {
+ this.doorList.add(this.doorInfo);
+ }
+ }
+
+ private VillageDoorInfo func_75412_a(Village par1Village) {
+ VillageDoorInfo var2 = null;
+ int var3 = Integer.MAX_VALUE;
+ List var4 = par1Village.getVillageDoorInfoList();
+ Iterator var5 = var4.iterator();
+
+ while (var5.hasNext()) {
+ VillageDoorInfo var6 = (VillageDoorInfo) var5.next();
+ int var7 = var6.getDistanceSquared(MathHelper.floor_double(this.theEntity.posX),
+ MathHelper.floor_double(this.theEntity.posY), MathHelper.floor_double(this.theEntity.posZ));
+
+ if (var7 < var3 && !this.func_75413_a(var6)) {
+ var2 = var6;
+ var3 = var7;
+ }
+ }
+
+ return var2;
+ }
+
+ private boolean func_75413_a(VillageDoorInfo par1VillageDoorInfo) {
+ Iterator var2 = this.doorList.iterator();
+ VillageDoorInfo var3;
+
+ do {
+ if (!var2.hasNext()) {
+ return false;
+ }
+
+ var3 = (VillageDoorInfo) var2.next();
+ } while (par1VillageDoorInfo.posX != var3.posX || par1VillageDoorInfo.posY != var3.posY
+ || par1VillageDoorInfo.posZ != var3.posZ);
+
+ return true;
+ }
+
+ private void func_75414_f() {
+ if (this.doorList.size() > 15) {
+ this.doorList.remove(0);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAIMoveTowardsTarget.java b/sp-server/src/main/java/net/minecraft/src/EntityAIMoveTowardsTarget.java
new file mode 100644
index 0000000..f10effc
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAIMoveTowardsTarget.java
@@ -0,0 +1,67 @@
+package net.minecraft.src;
+
+public class EntityAIMoveTowardsTarget extends EntityAIBase {
+ private EntityCreature theEntity;
+ private EntityLiving targetEntity;
+ private double movePosX;
+ private double movePosY;
+ private double movePosZ;
+ private float field_75425_f;
+ private float field_75426_g;
+
+ public EntityAIMoveTowardsTarget(EntityCreature par1EntityCreature, float par2, float par3) {
+ this.theEntity = par1EntityCreature;
+ this.field_75425_f = par2;
+ this.field_75426_g = par3;
+ this.setMutexBits(1);
+ }
+
+ /**
+ * Returns whether the EntityAIBase should begin execution.
+ */
+ public boolean shouldExecute() {
+ this.targetEntity = this.theEntity.getAttackTarget();
+
+ if (this.targetEntity == null) {
+ return false;
+ } else if (this.targetEntity
+ .getDistanceSqToEntity(this.theEntity) > (double) (this.field_75426_g * this.field_75426_g)) {
+ return false;
+ } else {
+ Vec3 var1 = RandomPositionGenerator.findRandomTargetBlockTowards(this.theEntity, 16, 7,
+ this.theEntity.worldObj.getWorldVec3Pool().getVecFromPool(this.targetEntity.posX,
+ this.targetEntity.posY, this.targetEntity.posZ));
+
+ if (var1 == null) {
+ return false;
+ } else {
+ this.movePosX = var1.xCoord;
+ this.movePosY = var1.yCoord;
+ this.movePosZ = var1.zCoord;
+ return true;
+ }
+ }
+ }
+
+ /**
+ * Returns whether an in-progress EntityAIBase should continue executing
+ */
+ public boolean continueExecuting() {
+ return !this.theEntity.getNavigator().noPath() && this.targetEntity.isEntityAlive() && this.targetEntity
+ .getDistanceSqToEntity(this.theEntity) < (double) (this.field_75426_g * this.field_75426_g);
+ }
+
+ /**
+ * Resets the task
+ */
+ public void resetTask() {
+ this.targetEntity = null;
+ }
+
+ /**
+ * Execute a one shot task or start executing a continuous task
+ */
+ public void startExecuting() {
+ this.theEntity.getNavigator().tryMoveToXYZ(this.movePosX, this.movePosY, this.movePosZ, this.field_75425_f);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAIMoveTwardsRestriction.java b/sp-server/src/main/java/net/minecraft/src/EntityAIMoveTwardsRestriction.java
new file mode 100644
index 0000000..f8f1c1d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAIMoveTwardsRestriction.java
@@ -0,0 +1,52 @@
+package net.minecraft.src;
+
+public class EntityAIMoveTwardsRestriction extends EntityAIBase {
+ private EntityCreature theEntity;
+ private double movePosX;
+ private double movePosY;
+ private double movePosZ;
+ private float movementSpeed;
+
+ public EntityAIMoveTwardsRestriction(EntityCreature par1EntityCreature, float par2) {
+ this.theEntity = par1EntityCreature;
+ this.movementSpeed = par2;
+ this.setMutexBits(1);
+ }
+
+ /**
+ * Returns whether the EntityAIBase should begin execution.
+ */
+ public boolean shouldExecute() {
+ if (this.theEntity.isWithinHomeDistanceCurrentPosition()) {
+ return false;
+ } else {
+ ChunkCoordinates var1 = this.theEntity.getHomePosition();
+ Vec3 var2 = RandomPositionGenerator.findRandomTargetBlockTowards(this.theEntity, 16, 7,
+ this.theEntity.worldObj.getWorldVec3Pool().getVecFromPool((double) var1.posX, (double) var1.posY,
+ (double) var1.posZ));
+
+ if (var2 == null) {
+ return false;
+ } else {
+ this.movePosX = var2.xCoord;
+ this.movePosY = var2.yCoord;
+ this.movePosZ = var2.zCoord;
+ return true;
+ }
+ }
+ }
+
+ /**
+ * Returns whether an in-progress EntityAIBase should continue executing
+ */
+ public boolean continueExecuting() {
+ return !this.theEntity.getNavigator().noPath();
+ }
+
+ /**
+ * Execute a one shot task or start executing a continuous task
+ */
+ public void startExecuting() {
+ this.theEntity.getNavigator().tryMoveToXYZ(this.movePosX, this.movePosY, this.movePosZ, this.movementSpeed);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAINearestAttackableTarget.java b/sp-server/src/main/java/net/minecraft/src/EntityAINearestAttackableTarget.java
new file mode 100644
index 0000000..57dd7f1
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAINearestAttackableTarget.java
@@ -0,0 +1,82 @@
+package net.minecraft.src;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+public class EntityAINearestAttackableTarget extends EntityAITarget {
+ EntityLiving targetEntity;
+ Class targetClass;
+ int targetChance;
+ private final IEntitySelector field_82643_g;
+
+ /** Instance of EntityAINearestAttackableTargetSorter. */
+ private EntityAINearestAttackableTargetSorter theNearestAttackableTargetSorter;
+
+ public EntityAINearestAttackableTarget(EntityLiving par1EntityLiving, Class par2Class, float par3, int par4,
+ boolean par5) {
+ this(par1EntityLiving, par2Class, par3, par4, par5, false);
+ }
+
+ public EntityAINearestAttackableTarget(EntityLiving par1EntityLiving, Class par2Class, float par3, int par4,
+ boolean par5, boolean par6) {
+ this(par1EntityLiving, par2Class, par3, par4, par5, par6, (IEntitySelector) null);
+ }
+
+ public EntityAINearestAttackableTarget(EntityLiving par1, Class par2, float par3, int par4, boolean par5,
+ boolean par6, IEntitySelector par7IEntitySelector) {
+ super(par1, par3, par5, par6);
+ this.targetClass = par2;
+ this.targetDistance = par3;
+ this.targetChance = par4;
+ this.theNearestAttackableTargetSorter = new EntityAINearestAttackableTargetSorter(this, par1);
+ this.field_82643_g = par7IEntitySelector;
+ this.setMutexBits(1);
+ }
+
+ /**
+ * Returns whether the EntityAIBase should begin execution.
+ */
+ public boolean shouldExecute() {
+ if (this.targetChance > 0 && this.taskOwner.getRNG().nextInt(this.targetChance) != 0) {
+ return false;
+ } else {
+ if (this.targetClass == EntityPlayer.class) {
+ EntityPlayer var1 = this.taskOwner.worldObj.getClosestVulnerablePlayerToEntity(this.taskOwner,
+ (double) this.targetDistance);
+
+ if (this.isSuitableTarget(var1, false)) {
+ this.targetEntity = var1;
+ return true;
+ }
+ } else {
+ List var5 = this.taskOwner.worldObj.selectEntitiesWithinAABB(this.targetClass,
+ this.taskOwner.boundingBox.expand((double) this.targetDistance, 4.0D,
+ (double) this.targetDistance),
+ this.field_82643_g);
+ Collections.sort(var5, this.theNearestAttackableTargetSorter);
+ Iterator var2 = var5.iterator();
+
+ while (var2.hasNext()) {
+ Entity var3 = (Entity) var2.next();
+ EntityLiving var4 = (EntityLiving) var3;
+
+ if (this.isSuitableTarget(var4, false)) {
+ this.targetEntity = var4;
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+ }
+
+ /**
+ * Execute a one shot task or start executing a continuous task
+ */
+ public void startExecuting() {
+ this.taskOwner.setAttackTarget(this.targetEntity);
+ super.startExecuting();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAINearestAttackableTargetSorter.java b/sp-server/src/main/java/net/minecraft/src/EntityAINearestAttackableTargetSorter.java
new file mode 100644
index 0000000..b9c8650
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAINearestAttackableTargetSorter.java
@@ -0,0 +1,25 @@
+package net.minecraft.src;
+
+import java.util.Comparator;
+
+public class EntityAINearestAttackableTargetSorter implements Comparator {
+ private Entity theEntity;
+
+ final EntityAINearestAttackableTarget parent;
+
+ public EntityAINearestAttackableTargetSorter(EntityAINearestAttackableTarget par1EntityAINearestAttackableTarget,
+ Entity par2Entity) {
+ this.parent = par1EntityAINearestAttackableTarget;
+ this.theEntity = par2Entity;
+ }
+
+ public int compareDistanceSq(Entity par1Entity, Entity par2Entity) {
+ double var3 = this.theEntity.getDistanceSqToEntity(par1Entity);
+ double var5 = this.theEntity.getDistanceSqToEntity(par2Entity);
+ return var3 < var5 ? -1 : (var3 > var5 ? 1 : 0);
+ }
+
+ public int compare(Object par1Obj, Object par2Obj) {
+ return this.compareDistanceSq((Entity) par1Obj, (Entity) par2Obj);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAIOcelotAttack.java b/sp-server/src/main/java/net/minecraft/src/EntityAIOcelotAttack.java
new file mode 100644
index 0000000..5a5dc5c
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAIOcelotAttack.java
@@ -0,0 +1,72 @@
+package net.minecraft.src;
+
+public class EntityAIOcelotAttack extends EntityAIBase {
+ World theWorld;
+ EntityLiving theEntity;
+ EntityLiving theVictim;
+ int attackCountdown = 0;
+
+ public EntityAIOcelotAttack(EntityLiving par1EntityLiving) {
+ this.theEntity = par1EntityLiving;
+ this.theWorld = par1EntityLiving.worldObj;
+ this.setMutexBits(3);
+ }
+
+ /**
+ * Returns whether the EntityAIBase should begin execution.
+ */
+ public boolean shouldExecute() {
+ EntityLiving var1 = this.theEntity.getAttackTarget();
+
+ if (var1 == null) {
+ return false;
+ } else {
+ this.theVictim = var1;
+ return true;
+ }
+ }
+
+ /**
+ * Returns whether an in-progress EntityAIBase should continue executing
+ */
+ public boolean continueExecuting() {
+ return !this.theVictim.isEntityAlive() ? false
+ : (this.theEntity.getDistanceSqToEntity(this.theVictim) > 225.0D ? false
+ : !this.theEntity.getNavigator().noPath() || this.shouldExecute());
+ }
+
+ /**
+ * Resets the task
+ */
+ public void resetTask() {
+ this.theVictim = null;
+ this.theEntity.getNavigator().clearPathEntity();
+ }
+
+ /**
+ * Updates the task
+ */
+ public void updateTask() {
+ this.theEntity.getLookHelper().setLookPositionWithEntity(this.theVictim, 30.0F, 30.0F);
+ double var1 = (double) (this.theEntity.width * 2.0F * this.theEntity.width * 2.0F);
+ double var3 = this.theEntity.getDistanceSq(this.theVictim.posX, this.theVictim.boundingBox.minY,
+ this.theVictim.posZ);
+ float var5 = 0.23F;
+
+ if (var3 > var1 && var3 < 16.0D) {
+ var5 = 0.4F;
+ } else if (var3 < 225.0D) {
+ var5 = 0.18F;
+ }
+
+ this.theEntity.getNavigator().tryMoveToEntityLiving(this.theVictim, var5);
+ this.attackCountdown = Math.max(this.attackCountdown - 1, 0);
+
+ if (var3 <= var1) {
+ if (this.attackCountdown <= 0) {
+ this.attackCountdown = 20;
+ this.theEntity.attackEntityAsMob(this.theVictim);
+ }
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAIOcelotSit.java b/sp-server/src/main/java/net/minecraft/src/EntityAIOcelotSit.java
new file mode 100644
index 0000000..8c7fc6c
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAIOcelotSit.java
@@ -0,0 +1,138 @@
+package net.minecraft.src;
+
+public class EntityAIOcelotSit extends EntityAIBase {
+ private final EntityOcelot theOcelot;
+ private final float field_75404_b;
+
+ /** Tracks for how long the task has been executing */
+ private int currentTick = 0;
+ private int field_75402_d = 0;
+
+ /** For how long the Ocelot should be sitting */
+ private int maxSittingTicks = 0;
+
+ /** X Coordinate of a nearby sitable block */
+ private int sitableBlockX = 0;
+
+ /** Y Coordinate of a nearby sitable block */
+ private int sitableBlockY = 0;
+
+ /** Z Coordinate of a nearby sitable block */
+ private int sitableBlockZ = 0;
+
+ public EntityAIOcelotSit(EntityOcelot par1EntityOcelot, float par2) {
+ this.theOcelot = par1EntityOcelot;
+ this.field_75404_b = par2;
+ this.setMutexBits(5);
+ }
+
+ /**
+ * Returns whether the EntityAIBase should begin execution.
+ */
+ public boolean shouldExecute() {
+ return this.theOcelot.isTamed() && !this.theOcelot.isSitting()
+ && this.theOcelot.getRNG().nextDouble() <= 0.006500000134110451D
+ && this.getNearbySitableBlockDistance();
+ }
+
+ /**
+ * Returns whether an in-progress EntityAIBase should continue executing
+ */
+ public boolean continueExecuting() {
+ return this.currentTick <= this.maxSittingTicks && this.field_75402_d <= 60 && this
+ .isSittableBlock(this.theOcelot.worldObj, this.sitableBlockX, this.sitableBlockY, this.sitableBlockZ);
+ }
+
+ /**
+ * Execute a one shot task or start executing a continuous task
+ */
+ public void startExecuting() {
+ this.theOcelot.getNavigator().tryMoveToXYZ((double) ((float) this.sitableBlockX) + 0.5D,
+ (double) (this.sitableBlockY + 1), (double) ((float) this.sitableBlockZ) + 0.5D, this.field_75404_b);
+ this.currentTick = 0;
+ this.field_75402_d = 0;
+ this.maxSittingTicks = this.theOcelot.getRNG().nextInt(this.theOcelot.getRNG().nextInt(1200) + 1200) + 1200;
+ this.theOcelot.func_70907_r().setSitting(false);
+ }
+
+ /**
+ * Resets the task
+ */
+ public void resetTask() {
+ this.theOcelot.setSitting(false);
+ }
+
+ /**
+ * Updates the task
+ */
+ public void updateTask() {
+ ++this.currentTick;
+ this.theOcelot.func_70907_r().setSitting(false);
+
+ if (this.theOcelot.getDistanceSq((double) this.sitableBlockX, (double) (this.sitableBlockY + 1),
+ (double) this.sitableBlockZ) > 1.0D) {
+ this.theOcelot.setSitting(false);
+ this.theOcelot.getNavigator().tryMoveToXYZ((double) ((float) this.sitableBlockX) + 0.5D,
+ (double) (this.sitableBlockY + 1), (double) ((float) this.sitableBlockZ) + 0.5D,
+ this.field_75404_b);
+ ++this.field_75402_d;
+ } else if (!this.theOcelot.isSitting()) {
+ this.theOcelot.setSitting(true);
+ } else {
+ --this.field_75402_d;
+ }
+ }
+
+ /**
+ * Searches for a block to sit on within a 8 block range, returns 0 if none
+ * found
+ */
+ private boolean getNearbySitableBlockDistance() {
+ int var1 = (int) this.theOcelot.posY;
+ double var2 = 2.147483647E9D;
+
+ for (int var4 = (int) this.theOcelot.posX - 8; (double) var4 < this.theOcelot.posX + 8.0D; ++var4) {
+ for (int var5 = (int) this.theOcelot.posZ - 8; (double) var5 < this.theOcelot.posZ + 8.0D; ++var5) {
+ if (this.isSittableBlock(this.theOcelot.worldObj, var4, var1, var5)
+ && this.theOcelot.worldObj.isAirBlock(var4, var1 + 1, var5)) {
+ double var6 = this.theOcelot.getDistanceSq((double) var4, (double) var1, (double) var5);
+
+ if (var6 < var2) {
+ this.sitableBlockX = var4;
+ this.sitableBlockY = var1;
+ this.sitableBlockZ = var5;
+ var2 = var6;
+ }
+ }
+ }
+ }
+
+ return var2 < 2.147483647E9D;
+ }
+
+ /**
+ * Determines whether the Ocelot wants to sit on the block at given coordinate
+ */
+ private boolean isSittableBlock(World par1World, int par2, int par3, int par4) {
+ int var5 = par1World.getBlockId(par2, par3, par4);
+ int var6 = par1World.getBlockMetadata(par2, par3, par4);
+
+ if (var5 == Block.chest.blockID) {
+ TileEntityChest var7 = (TileEntityChest) par1World.getBlockTileEntity(par2, par3, par4);
+
+ if (var7.numUsingPlayers < 1) {
+ return true;
+ }
+ } else {
+ if (var5 == Block.furnaceBurning.blockID) {
+ return true;
+ }
+
+ if (var5 == Block.bed.blockID && !BlockBed.isBlockHeadOfBed(var6)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAIOpenDoor.java b/sp-server/src/main/java/net/minecraft/src/EntityAIOpenDoor.java
new file mode 100644
index 0000000..1322b73
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAIOpenDoor.java
@@ -0,0 +1,46 @@
+package net.minecraft.src;
+
+public class EntityAIOpenDoor extends EntityAIDoorInteract {
+ boolean field_75361_i;
+ int field_75360_j;
+
+ public EntityAIOpenDoor(EntityLiving par1EntityLiving, boolean par2) {
+ super(par1EntityLiving);
+ this.theEntity = par1EntityLiving;
+ this.field_75361_i = par2;
+ }
+
+ /**
+ * Returns whether an in-progress EntityAIBase should continue executing
+ */
+ public boolean continueExecuting() {
+ return this.field_75361_i && this.field_75360_j > 0 && super.continueExecuting();
+ }
+
+ /**
+ * Execute a one shot task or start executing a continuous task
+ */
+ public void startExecuting() {
+ this.field_75360_j = 20;
+ this.targetDoor.onPoweredBlockChange(this.theEntity.worldObj, this.entityPosX, this.entityPosY, this.entityPosZ,
+ true);
+ }
+
+ /**
+ * Resets the task
+ */
+ public void resetTask() {
+ if (this.field_75361_i) {
+ this.targetDoor.onPoweredBlockChange(this.theEntity.worldObj, this.entityPosX, this.entityPosY,
+ this.entityPosZ, false);
+ }
+ }
+
+ /**
+ * Updates the task
+ */
+ public void updateTask() {
+ --this.field_75360_j;
+ super.updateTask();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAIOwnerHurtByTarget.java b/sp-server/src/main/java/net/minecraft/src/EntityAIOwnerHurtByTarget.java
new file mode 100644
index 0000000..24b6915
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAIOwnerHurtByTarget.java
@@ -0,0 +1,38 @@
+package net.minecraft.src;
+
+public class EntityAIOwnerHurtByTarget extends EntityAITarget {
+ EntityTameable theDefendingTameable;
+ EntityLiving theOwnerAttacker;
+
+ public EntityAIOwnerHurtByTarget(EntityTameable par1EntityTameable) {
+ super(par1EntityTameable, 32.0F, false);
+ this.theDefendingTameable = par1EntityTameable;
+ this.setMutexBits(1);
+ }
+
+ /**
+ * Returns whether the EntityAIBase should begin execution.
+ */
+ public boolean shouldExecute() {
+ if (!this.theDefendingTameable.isTamed()) {
+ return false;
+ } else {
+ EntityLiving var1 = this.theDefendingTameable.getOwner();
+
+ if (var1 == null) {
+ return false;
+ } else {
+ this.theOwnerAttacker = var1.getAITarget();
+ return this.isSuitableTarget(this.theOwnerAttacker, false);
+ }
+ }
+ }
+
+ /**
+ * Execute a one shot task or start executing a continuous task
+ */
+ public void startExecuting() {
+ this.taskOwner.setAttackTarget(this.theOwnerAttacker);
+ super.startExecuting();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAIOwnerHurtTarget.java b/sp-server/src/main/java/net/minecraft/src/EntityAIOwnerHurtTarget.java
new file mode 100644
index 0000000..d85bb99
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAIOwnerHurtTarget.java
@@ -0,0 +1,38 @@
+package net.minecraft.src;
+
+public class EntityAIOwnerHurtTarget extends EntityAITarget {
+ EntityTameable theEntityTameable;
+ EntityLiving theTarget;
+
+ public EntityAIOwnerHurtTarget(EntityTameable par1EntityTameable) {
+ super(par1EntityTameable, 32.0F, false);
+ this.theEntityTameable = par1EntityTameable;
+ this.setMutexBits(1);
+ }
+
+ /**
+ * Returns whether the EntityAIBase should begin execution.
+ */
+ public boolean shouldExecute() {
+ if (!this.theEntityTameable.isTamed()) {
+ return false;
+ } else {
+ EntityLiving var1 = this.theEntityTameable.getOwner();
+
+ if (var1 == null) {
+ return false;
+ } else {
+ this.theTarget = var1.getLastAttackingEntity();
+ return this.isSuitableTarget(this.theTarget, false);
+ }
+ }
+ }
+
+ /**
+ * Execute a one shot task or start executing a continuous task
+ */
+ public void startExecuting() {
+ this.taskOwner.setAttackTarget(this.theTarget);
+ super.startExecuting();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAIPanic.java b/sp-server/src/main/java/net/minecraft/src/EntityAIPanic.java
new file mode 100644
index 0000000..196cf8d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAIPanic.java
@@ -0,0 +1,49 @@
+package net.minecraft.src;
+
+public class EntityAIPanic extends EntityAIBase {
+ private EntityCreature theEntityCreature;
+ private float speed;
+ private double randPosX;
+ private double randPosY;
+ private double randPosZ;
+
+ public EntityAIPanic(EntityCreature par1EntityCreature, float par2) {
+ this.theEntityCreature = par1EntityCreature;
+ this.speed = par2;
+ this.setMutexBits(1);
+ }
+
+ /**
+ * Returns whether the EntityAIBase should begin execution.
+ */
+ public boolean shouldExecute() {
+ if (this.theEntityCreature.getAITarget() == null && !this.theEntityCreature.isBurning()) {
+ return false;
+ } else {
+ Vec3 var1 = RandomPositionGenerator.findRandomTarget(this.theEntityCreature, 5, 4);
+
+ if (var1 == null) {
+ return false;
+ } else {
+ this.randPosX = var1.xCoord;
+ this.randPosY = var1.yCoord;
+ this.randPosZ = var1.zCoord;
+ return true;
+ }
+ }
+ }
+
+ /**
+ * Execute a one shot task or start executing a continuous task
+ */
+ public void startExecuting() {
+ this.theEntityCreature.getNavigator().tryMoveToXYZ(this.randPosX, this.randPosY, this.randPosZ, this.speed);
+ }
+
+ /**
+ * Returns whether an in-progress EntityAIBase should continue executing
+ */
+ public boolean continueExecuting() {
+ return !this.theEntityCreature.getNavigator().noPath();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAIPlay.java b/sp-server/src/main/java/net/minecraft/src/EntityAIPlay.java
new file mode 100644
index 0000000..916d958
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAIPlay.java
@@ -0,0 +1,103 @@
+package net.minecraft.src;
+
+import java.util.Iterator;
+import java.util.List;
+
+public class EntityAIPlay extends EntityAIBase {
+ private EntityVillager villagerObj;
+ private EntityLiving targetVillager;
+ private float field_75261_c;
+ private int playTime;
+
+ public EntityAIPlay(EntityVillager par1EntityVillager, float par2) {
+ this.villagerObj = par1EntityVillager;
+ this.field_75261_c = par2;
+ this.setMutexBits(1);
+ }
+
+ /**
+ * Returns whether the EntityAIBase should begin execution.
+ */
+ public boolean shouldExecute() {
+ if (this.villagerObj.getGrowingAge() >= 0) {
+ return false;
+ } else if (this.villagerObj.getRNG().nextInt(400) != 0) {
+ return false;
+ } else {
+ List var1 = this.villagerObj.worldObj.getEntitiesWithinAABB(EntityVillager.class,
+ this.villagerObj.boundingBox.expand(6.0D, 3.0D, 6.0D));
+ double var2 = Double.MAX_VALUE;
+ Iterator var4 = var1.iterator();
+
+ while (var4.hasNext()) {
+ EntityVillager var5 = (EntityVillager) var4.next();
+
+ if (var5 != this.villagerObj && !var5.isPlaying() && var5.getGrowingAge() < 0) {
+ double var6 = var5.getDistanceSqToEntity(this.villagerObj);
+
+ if (var6 <= var2) {
+ var2 = var6;
+ this.targetVillager = var5;
+ }
+ }
+ }
+
+ if (this.targetVillager == null) {
+ Vec3 var8 = RandomPositionGenerator.findRandomTarget(this.villagerObj, 16, 3);
+
+ if (var8 == null) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ }
+
+ /**
+ * Returns whether an in-progress EntityAIBase should continue executing
+ */
+ public boolean continueExecuting() {
+ return this.playTime > 0;
+ }
+
+ /**
+ * Execute a one shot task or start executing a continuous task
+ */
+ public void startExecuting() {
+ if (this.targetVillager != null) {
+ this.villagerObj.setPlaying(true);
+ }
+
+ this.playTime = 1000;
+ }
+
+ /**
+ * Resets the task
+ */
+ public void resetTask() {
+ this.villagerObj.setPlaying(false);
+ this.targetVillager = null;
+ }
+
+ /**
+ * Updates the task
+ */
+ public void updateTask() {
+ --this.playTime;
+
+ if (this.targetVillager != null) {
+ if (this.villagerObj.getDistanceSqToEntity(this.targetVillager) > 4.0D) {
+ this.villagerObj.getNavigator().tryMoveToEntityLiving(this.targetVillager, this.field_75261_c);
+ }
+ } else if (this.villagerObj.getNavigator().noPath()) {
+ Vec3 var1 = RandomPositionGenerator.findRandomTarget(this.villagerObj, 16, 3);
+
+ if (var1 == null) {
+ return;
+ }
+
+ this.villagerObj.getNavigator().tryMoveToXYZ(var1.xCoord, var1.yCoord, var1.zCoord, this.field_75261_c);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAIRestrictOpenDoor.java b/sp-server/src/main/java/net/minecraft/src/EntityAIRestrictOpenDoor.java
new file mode 100644
index 0000000..afbe620
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAIRestrictOpenDoor.java
@@ -0,0 +1,67 @@
+package net.minecraft.src;
+
+public class EntityAIRestrictOpenDoor extends EntityAIBase {
+ private EntityCreature entityObj;
+ private VillageDoorInfo frontDoor;
+
+ public EntityAIRestrictOpenDoor(EntityCreature par1EntityCreature) {
+ this.entityObj = par1EntityCreature;
+ }
+
+ /**
+ * Returns whether the EntityAIBase should begin execution.
+ */
+ public boolean shouldExecute() {
+ if (this.entityObj.worldObj.isDaytime()) {
+ return false;
+ } else {
+ Village var1 = this.entityObj.worldObj.villageCollectionObj.findNearestVillage(
+ MathHelper.floor_double(this.entityObj.posX), MathHelper.floor_double(this.entityObj.posY),
+ MathHelper.floor_double(this.entityObj.posZ), 16);
+
+ if (var1 == null) {
+ return false;
+ } else {
+ this.frontDoor = var1.findNearestDoor(MathHelper.floor_double(this.entityObj.posX),
+ MathHelper.floor_double(this.entityObj.posY), MathHelper.floor_double(this.entityObj.posZ));
+ return this.frontDoor == null ? false
+ : (double) this.frontDoor.getInsideDistanceSquare(MathHelper.floor_double(this.entityObj.posX),
+ MathHelper.floor_double(this.entityObj.posY),
+ MathHelper.floor_double(this.entityObj.posZ)) < 2.25D;
+ }
+ }
+ }
+
+ /**
+ * Returns whether an in-progress EntityAIBase should continue executing
+ */
+ public boolean continueExecuting() {
+ return this.entityObj.worldObj.isDaytime() ? false
+ : !this.frontDoor.isDetachedFromVillageFlag && this.frontDoor.isInside(
+ MathHelper.floor_double(this.entityObj.posX), MathHelper.floor_double(this.entityObj.posZ));
+ }
+
+ /**
+ * Execute a one shot task or start executing a continuous task
+ */
+ public void startExecuting() {
+ this.entityObj.getNavigator().setBreakDoors(false);
+ this.entityObj.getNavigator().setEnterDoors(false);
+ }
+
+ /**
+ * Resets the task
+ */
+ public void resetTask() {
+ this.entityObj.getNavigator().setBreakDoors(true);
+ this.entityObj.getNavigator().setEnterDoors(true);
+ this.frontDoor = null;
+ }
+
+ /**
+ * Updates the task
+ */
+ public void updateTask() {
+ this.frontDoor.incrementDoorOpeningRestrictionCounter();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAIRestrictSun.java b/sp-server/src/main/java/net/minecraft/src/EntityAIRestrictSun.java
new file mode 100644
index 0000000..fe4e1bb
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAIRestrictSun.java
@@ -0,0 +1,30 @@
+package net.minecraft.src;
+
+public class EntityAIRestrictSun extends EntityAIBase {
+ private EntityCreature theEntity;
+
+ public EntityAIRestrictSun(EntityCreature par1EntityCreature) {
+ this.theEntity = par1EntityCreature;
+ }
+
+ /**
+ * Returns whether the EntityAIBase should begin execution.
+ */
+ public boolean shouldExecute() {
+ return this.theEntity.worldObj.isDaytime();
+ }
+
+ /**
+ * Execute a one shot task or start executing a continuous task
+ */
+ public void startExecuting() {
+ this.theEntity.getNavigator().setAvoidSun(true);
+ }
+
+ /**
+ * Resets the task
+ */
+ public void resetTask() {
+ this.theEntity.getNavigator().setAvoidSun(false);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAISit.java b/sp-server/src/main/java/net/minecraft/src/EntityAISit.java
new file mode 100644
index 0000000..7e4882c
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAISit.java
@@ -0,0 +1,53 @@
+package net.minecraft.src;
+
+public class EntityAISit extends EntityAIBase {
+ private EntityTameable theEntity;
+
+ /** If the EntityTameable is sitting. */
+ private boolean isSitting = false;
+
+ public EntityAISit(EntityTameable par1EntityTameable) {
+ this.theEntity = par1EntityTameable;
+ this.setMutexBits(5);
+ }
+
+ /**
+ * Returns whether the EntityAIBase should begin execution.
+ */
+ public boolean shouldExecute() {
+ if (!this.theEntity.isTamed()) {
+ return false;
+ } else if (this.theEntity.isInWater()) {
+ return false;
+ } else if (!this.theEntity.onGround) {
+ return false;
+ } else {
+ EntityLiving var1 = this.theEntity.getOwner();
+ return var1 == null ? true
+ : (this.theEntity.getDistanceSqToEntity(var1) < 144.0D && var1.getAITarget() != null ? false
+ : this.isSitting);
+ }
+ }
+
+ /**
+ * Execute a one shot task or start executing a continuous task
+ */
+ public void startExecuting() {
+ this.theEntity.getNavigator().clearPathEntity();
+ this.theEntity.setSitting(true);
+ }
+
+ /**
+ * Resets the task
+ */
+ public void resetTask() {
+ this.theEntity.setSitting(false);
+ }
+
+ /**
+ * Sets the sitting flag.
+ */
+ public void setSitting(boolean par1) {
+ this.isSitting = par1;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAISwimming.java b/sp-server/src/main/java/net/minecraft/src/EntityAISwimming.java
new file mode 100644
index 0000000..dbcdd6a
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAISwimming.java
@@ -0,0 +1,27 @@
+package net.minecraft.src;
+
+public class EntityAISwimming extends EntityAIBase {
+ private EntityLiving theEntity;
+
+ public EntityAISwimming(EntityLiving par1EntityLiving) {
+ this.theEntity = par1EntityLiving;
+ this.setMutexBits(4);
+ par1EntityLiving.getNavigator().setCanSwim(true);
+ }
+
+ /**
+ * Returns whether the EntityAIBase should begin execution.
+ */
+ public boolean shouldExecute() {
+ return this.theEntity.isInWater() || this.theEntity.handleLavaMovement();
+ }
+
+ /**
+ * Updates the task
+ */
+ public void updateTask() {
+ if (this.theEntity.getRNG().nextFloat() < 0.8F) {
+ this.theEntity.getJumpHelper().setJumping();
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAITarget.java b/sp-server/src/main/java/net/minecraft/src/EntityAITarget.java
new file mode 100644
index 0000000..279e661
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAITarget.java
@@ -0,0 +1,143 @@
+package net.minecraft.src;
+
+public abstract class EntityAITarget extends EntityAIBase {
+ /** The entity that this task belongs to */
+ protected EntityLiving taskOwner;
+ protected float targetDistance;
+
+ /**
+ * If true, EntityAI targets must be able to be seen (cannot be blocked by
+ * walls) to be suitable targets.
+ */
+ protected boolean shouldCheckSight;
+ private boolean field_75303_a;
+ private int field_75301_b;
+ private int field_75302_c;
+ private int field_75298_g;
+
+ public EntityAITarget(EntityLiving par1EntityLiving, float par2, boolean par3) {
+ this(par1EntityLiving, par2, par3, false);
+ }
+
+ public EntityAITarget(EntityLiving par1EntityLiving, float par2, boolean par3, boolean par4) {
+ this.field_75301_b = 0;
+ this.field_75302_c = 0;
+ this.field_75298_g = 0;
+ this.taskOwner = par1EntityLiving;
+ this.targetDistance = par2;
+ this.shouldCheckSight = par3;
+ this.field_75303_a = par4;
+ }
+
+ /**
+ * Returns whether an in-progress EntityAIBase should continue executing
+ */
+ public boolean continueExecuting() {
+ EntityLiving var1 = this.taskOwner.getAttackTarget();
+
+ if (var1 == null) {
+ return false;
+ } else if (!var1.isEntityAlive()) {
+ return false;
+ } else if (this.taskOwner.getDistanceSqToEntity(var1) > (double) (this.targetDistance * this.targetDistance)) {
+ return false;
+ } else {
+ if (this.shouldCheckSight) {
+ if (this.taskOwner.getEntitySenses().canSee(var1)) {
+ this.field_75298_g = 0;
+ } else if (++this.field_75298_g > 60) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ }
+
+ /**
+ * Execute a one shot task or start executing a continuous task
+ */
+ public void startExecuting() {
+ this.field_75301_b = 0;
+ this.field_75302_c = 0;
+ this.field_75298_g = 0;
+ }
+
+ /**
+ * Resets the task
+ */
+ public void resetTask() {
+ this.taskOwner.setAttackTarget((EntityLiving) null);
+ }
+
+ /**
+ * A method used to see if an entity is a suitable target through a number of
+ * checks.
+ */
+ protected boolean isSuitableTarget(EntityLiving par1EntityLiving, boolean par2) {
+ if (par1EntityLiving == null) {
+ return false;
+ } else if (par1EntityLiving == this.taskOwner) {
+ return false;
+ } else if (!par1EntityLiving.isEntityAlive()) {
+ return false;
+ } else if (!this.taskOwner.canAttackClass(par1EntityLiving.getClass())) {
+ return false;
+ } else {
+ if (this.taskOwner instanceof EntityTameable && ((EntityTameable) this.taskOwner).isTamed()) {
+ if (par1EntityLiving instanceof EntityTameable && ((EntityTameable) par1EntityLiving).isTamed()) {
+ return false;
+ }
+
+ if (par1EntityLiving == ((EntityTameable) this.taskOwner).getOwner()) {
+ return false;
+ }
+ } else if (par1EntityLiving instanceof EntityPlayer && !par2
+ && ((EntityPlayer) par1EntityLiving).capabilities.disableDamage) {
+ return false;
+ }
+
+ if (!this.taskOwner.isWithinHomeDistance(MathHelper.floor_double(par1EntityLiving.posX),
+ MathHelper.floor_double(par1EntityLiving.posY), MathHelper.floor_double(par1EntityLiving.posZ))) {
+ return false;
+ } else if (this.shouldCheckSight && !this.taskOwner.getEntitySenses().canSee(par1EntityLiving)) {
+ return false;
+ } else {
+ if (this.field_75303_a) {
+ if (--this.field_75302_c <= 0) {
+ this.field_75301_b = 0;
+ }
+
+ if (this.field_75301_b == 0) {
+ this.field_75301_b = this.func_75295_a(par1EntityLiving) ? 1 : 2;
+ }
+
+ if (this.field_75301_b == 2) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ }
+ }
+
+ private boolean func_75295_a(EntityLiving par1EntityLiving) {
+ this.field_75302_c = 10 + this.taskOwner.getRNG().nextInt(5);
+ PathEntity var2 = this.taskOwner.getNavigator().getPathToEntityLiving(par1EntityLiving);
+
+ if (var2 == null) {
+ return false;
+ } else {
+ PathPoint var3 = var2.getFinalPathPoint();
+
+ if (var3 == null) {
+ return false;
+ } else {
+ int var4 = var3.xCoord - MathHelper.floor_double(par1EntityLiving.posX);
+ int var5 = var3.zCoord - MathHelper.floor_double(par1EntityLiving.posZ);
+ return (double) (var4 * var4 + var5 * var5) <= 2.25D;
+ }
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAITargetNonTamed.java b/sp-server/src/main/java/net/minecraft/src/EntityAITargetNonTamed.java
new file mode 100644
index 0000000..9079c77
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAITargetNonTamed.java
@@ -0,0 +1,18 @@
+package net.minecraft.src;
+
+public class EntityAITargetNonTamed extends EntityAINearestAttackableTarget {
+ private EntityTameable theTameable;
+
+ public EntityAITargetNonTamed(EntityTameable par1EntityTameable, Class par2Class, float par3, int par4,
+ boolean par5) {
+ super(par1EntityTameable, par2Class, par3, par4, par5);
+ this.theTameable = par1EntityTameable;
+ }
+
+ /**
+ * Returns whether the EntityAIBase should begin execution.
+ */
+ public boolean shouldExecute() {
+ return this.theTameable.isTamed() ? false : super.shouldExecute();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAITaskEntry.java b/sp-server/src/main/java/net/minecraft/src/EntityAITaskEntry.java
new file mode 100644
index 0000000..5f9022a
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAITaskEntry.java
@@ -0,0 +1,18 @@
+package net.minecraft.src;
+
+class EntityAITaskEntry {
+ /** The EntityAIBase object. */
+ public EntityAIBase action;
+
+ /** Priority of the EntityAIBase */
+ public int priority;
+
+ /** The EntityAITasks object of which this is an entry. */
+ final EntityAITasks tasks;
+
+ public EntityAITaskEntry(EntityAITasks par1EntityAITasks, int par2, EntityAIBase par3EntityAIBase) {
+ this.tasks = par1EntityAITasks;
+ this.priority = par2;
+ this.action = par3EntityAIBase;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAITasks.java b/sp-server/src/main/java/net/minecraft/src/EntityAITasks.java
new file mode 100644
index 0000000..8539f87
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAITasks.java
@@ -0,0 +1,136 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+public class EntityAITasks {
+ /** A list of EntityAITaskEntrys in EntityAITasks. */
+ private List taskEntries = new ArrayList();
+
+ /** A list of EntityAITaskEntrys that are currently being executed. */
+ private List executingTaskEntries = new ArrayList();
+
+ private int field_75778_d = 0;
+ private int field_75779_e = 3;
+
+ public void addTask(int par1, EntityAIBase par2EntityAIBase) {
+ this.taskEntries.add(new EntityAITaskEntry(this, par1, par2EntityAIBase));
+ }
+
+ /**
+ * removes the indicated task from the entity's AI tasks.
+ */
+ public void removeTask(EntityAIBase par1EntityAIBase) {
+ Iterator var2 = this.taskEntries.iterator();
+
+ while (var2.hasNext()) {
+ EntityAITaskEntry var3 = (EntityAITaskEntry) var2.next();
+ EntityAIBase var4 = var3.action;
+
+ if (var4 == par1EntityAIBase) {
+ if (this.executingTaskEntries.contains(var3)) {
+ var4.resetTask();
+ this.executingTaskEntries.remove(var3);
+ }
+
+ var2.remove();
+ }
+ }
+ }
+
+ public void onUpdateTasks() {
+ ArrayList var1 = new ArrayList();
+ Iterator var2;
+ EntityAITaskEntry var3;
+
+ if (this.field_75778_d++ % this.field_75779_e == 0) {
+ var2 = this.taskEntries.iterator();
+
+ while (var2.hasNext()) {
+ var3 = (EntityAITaskEntry) var2.next();
+ boolean var4 = this.executingTaskEntries.contains(var3);
+
+ if (var4) {
+ if (this.canUse(var3) && this.canContinue(var3)) {
+ continue;
+ }
+
+ var3.action.resetTask();
+ this.executingTaskEntries.remove(var3);
+ }
+
+ if (this.canUse(var3) && var3.action.shouldExecute()) {
+ var1.add(var3);
+ this.executingTaskEntries.add(var3);
+ }
+ }
+ } else {
+ var2 = this.executingTaskEntries.iterator();
+
+ while (var2.hasNext()) {
+ var3 = (EntityAITaskEntry) var2.next();
+
+ if (!var3.action.continueExecuting()) {
+ var3.action.resetTask();
+ var2.remove();
+ }
+ }
+ }
+
+ var2 = var1.iterator();
+
+ while (var2.hasNext()) {
+ var3 = (EntityAITaskEntry) var2.next();
+ var3.action.startExecuting();
+ }
+
+ var2 = this.executingTaskEntries.iterator();
+
+ while (var2.hasNext()) {
+ var3 = (EntityAITaskEntry) var2.next();
+ var3.action.updateTask();
+ }
+ }
+
+ /**
+ * Determine if a specific AI Task should continue being executed.
+ */
+ private boolean canContinue(EntityAITaskEntry par1EntityAITaskEntry) {
+ return par1EntityAITaskEntry.action.continueExecuting();
+ }
+
+ /**
+ * Determine if a specific AI Task can be executed, which means that all running
+ * higher (= lower int value) priority tasks are compatible with it or all lower
+ * priority tasks can be interrupted.
+ */
+ private boolean canUse(EntityAITaskEntry par1EntityAITaskEntry) {
+ Iterator var2 = this.taskEntries.iterator();
+
+ while (var2.hasNext()) {
+ EntityAITaskEntry var3 = (EntityAITaskEntry) var2.next();
+
+ if (var3 != par1EntityAITaskEntry) {
+ if (par1EntityAITaskEntry.priority >= var3.priority) {
+ if (this.executingTaskEntries.contains(var3)
+ && !this.areTasksCompatible(par1EntityAITaskEntry, var3)) {
+ return false;
+ }
+ } else if (this.executingTaskEntries.contains(var3) && !var3.action.isContinuous()) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns whether two EntityAITaskEntries can be executed concurrently
+ */
+ private boolean areTasksCompatible(EntityAITaskEntry par1EntityAITaskEntry,
+ EntityAITaskEntry par2EntityAITaskEntry) {
+ return (par1EntityAITaskEntry.action.getMutexBits() & par2EntityAITaskEntry.action.getMutexBits()) == 0;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAITempt.java b/sp-server/src/main/java/net/minecraft/src/EntityAITempt.java
new file mode 100644
index 0000000..8dfc924
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAITempt.java
@@ -0,0 +1,132 @@
+package net.minecraft.src;
+
+public class EntityAITempt extends EntityAIBase {
+ /** The entity using this AI that is tempted by the player. */
+ private EntityCreature temptedEntity;
+ private float field_75282_b;
+ private double field_75283_c;
+ private double field_75280_d;
+ private double field_75281_e;
+ private double field_75278_f;
+ private double field_75279_g;
+
+ /** The player that is tempting the entity that is using this AI. */
+ private EntityPlayer temptingPlayer;
+
+ /**
+ * A counter that is decremented each time the shouldExecute method is called.
+ * The shouldExecute method will always return false if delayTemptCounter is
+ * greater than 0.
+ */
+ private int delayTemptCounter = 0;
+ private boolean field_75287_j;
+
+ /**
+ * This field saves the ID of the items that can be used to breed entities with
+ * this behaviour.
+ */
+ private int breedingFood;
+
+ /**
+ * Whether the entity using this AI will be scared by the tempter's sudden
+ * movement.
+ */
+ private boolean scaredByPlayerMovement;
+ private boolean field_75286_m;
+
+ public EntityAITempt(EntityCreature par1EntityCreature, float par2, int par3, boolean par4) {
+ this.temptedEntity = par1EntityCreature;
+ this.field_75282_b = par2;
+ this.breedingFood = par3;
+ this.scaredByPlayerMovement = par4;
+ this.setMutexBits(3);
+ }
+
+ /**
+ * Returns whether the EntityAIBase should begin execution.
+ */
+ public boolean shouldExecute() {
+ if (this.delayTemptCounter > 0) {
+ --this.delayTemptCounter;
+ return false;
+ } else {
+ this.temptingPlayer = this.temptedEntity.worldObj.getClosestPlayerToEntity(this.temptedEntity, 10.0D);
+
+ if (this.temptingPlayer == null) {
+ return false;
+ } else {
+ ItemStack var1 = this.temptingPlayer.getCurrentEquippedItem();
+ return var1 == null ? false : var1.itemID == this.breedingFood;
+ }
+ }
+ }
+
+ /**
+ * Returns whether an in-progress EntityAIBase should continue executing
+ */
+ public boolean continueExecuting() {
+ if (this.scaredByPlayerMovement) {
+ if (this.temptedEntity.getDistanceSqToEntity(this.temptingPlayer) < 36.0D) {
+ if (this.temptingPlayer.getDistanceSq(this.field_75283_c, this.field_75280_d,
+ this.field_75281_e) > 0.010000000000000002D) {
+ return false;
+ }
+
+ if (Math.abs((double) this.temptingPlayer.rotationPitch - this.field_75278_f) > 5.0D
+ || Math.abs((double) this.temptingPlayer.rotationYaw - this.field_75279_g) > 5.0D) {
+ return false;
+ }
+ } else {
+ this.field_75283_c = this.temptingPlayer.posX;
+ this.field_75280_d = this.temptingPlayer.posY;
+ this.field_75281_e = this.temptingPlayer.posZ;
+ }
+
+ this.field_75278_f = (double) this.temptingPlayer.rotationPitch;
+ this.field_75279_g = (double) this.temptingPlayer.rotationYaw;
+ }
+
+ return this.shouldExecute();
+ }
+
+ /**
+ * Execute a one shot task or start executing a continuous task
+ */
+ public void startExecuting() {
+ this.field_75283_c = this.temptingPlayer.posX;
+ this.field_75280_d = this.temptingPlayer.posY;
+ this.field_75281_e = this.temptingPlayer.posZ;
+ this.field_75287_j = true;
+ this.field_75286_m = this.temptedEntity.getNavigator().getAvoidsWater();
+ this.temptedEntity.getNavigator().setAvoidsWater(false);
+ }
+
+ /**
+ * Resets the task
+ */
+ public void resetTask() {
+ this.temptingPlayer = null;
+ this.temptedEntity.getNavigator().clearPathEntity();
+ this.delayTemptCounter = 100;
+ this.field_75287_j = false;
+ this.temptedEntity.getNavigator().setAvoidsWater(this.field_75286_m);
+ }
+
+ /**
+ * Updates the task
+ */
+ public void updateTask() {
+ this.temptedEntity.getLookHelper().setLookPositionWithEntity(this.temptingPlayer, 30.0F,
+ (float) this.temptedEntity.getVerticalFaceSpeed());
+
+ if (this.temptedEntity.getDistanceSqToEntity(this.temptingPlayer) < 6.25D) {
+ this.temptedEntity.getNavigator().clearPathEntity();
+ } else {
+ this.temptedEntity.getNavigator().tryMoveToEntityLiving(this.temptingPlayer, this.field_75282_b);
+ }
+ }
+
+ public boolean func_75277_f() {
+ return this.field_75287_j;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAITradePlayer.java b/sp-server/src/main/java/net/minecraft/src/EntityAITradePlayer.java
new file mode 100644
index 0000000..79eaaf0
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAITradePlayer.java
@@ -0,0 +1,44 @@
+package net.minecraft.src;
+
+public class EntityAITradePlayer extends EntityAIBase {
+ private EntityVillager villager;
+
+ public EntityAITradePlayer(EntityVillager par1EntityVillager) {
+ this.villager = par1EntityVillager;
+ this.setMutexBits(5);
+ }
+
+ /**
+ * Returns whether the EntityAIBase should begin execution.
+ */
+ public boolean shouldExecute() {
+ if (!this.villager.isEntityAlive()) {
+ return false;
+ } else if (this.villager.isInWater()) {
+ return false;
+ } else if (!this.villager.onGround) {
+ return false;
+ } else if (this.villager.velocityChanged) {
+ return false;
+ } else {
+ EntityPlayer var1 = this.villager.getCustomer();
+ return var1 == null ? false
+ : (this.villager.getDistanceSqToEntity(var1) > 16.0D ? false
+ : var1.openContainer instanceof Container);
+ }
+ }
+
+ /**
+ * Execute a one shot task or start executing a continuous task
+ */
+ public void startExecuting() {
+ this.villager.getNavigator().clearPathEntity();
+ }
+
+ /**
+ * Resets the task
+ */
+ public void resetTask() {
+ this.villager.setCustomer((EntityPlayer) null);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAIVillagerMate.java b/sp-server/src/main/java/net/minecraft/src/EntityAIVillagerMate.java
new file mode 100644
index 0000000..eb27369
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAIVillagerMate.java
@@ -0,0 +1,108 @@
+package net.minecraft.src;
+
+public class EntityAIVillagerMate extends EntityAIBase {
+ private EntityVillager villagerObj;
+ private EntityVillager mate;
+ private World worldObj;
+ private int matingTimeout = 0;
+ Village villageObj;
+
+ public EntityAIVillagerMate(EntityVillager par1EntityVillager) {
+ this.villagerObj = par1EntityVillager;
+ this.worldObj = par1EntityVillager.worldObj;
+ this.setMutexBits(3);
+ }
+
+ /**
+ * Returns whether the EntityAIBase should begin execution.
+ */
+ public boolean shouldExecute() {
+ if (this.villagerObj.getGrowingAge() != 0) {
+ return false;
+ } else if (this.villagerObj.getRNG().nextInt(500) != 0) {
+ return false;
+ } else {
+ this.villageObj = this.worldObj.villageCollectionObj.findNearestVillage(
+ MathHelper.floor_double(this.villagerObj.posX), MathHelper.floor_double(this.villagerObj.posY),
+ MathHelper.floor_double(this.villagerObj.posZ), 0);
+
+ if (this.villageObj == null) {
+ return false;
+ } else if (!this.checkSufficientDoorsPresentForNewVillager()) {
+ return false;
+ } else {
+ Entity var1 = this.worldObj.findNearestEntityWithinAABB(EntityVillager.class,
+ this.villagerObj.boundingBox.expand(8.0D, 3.0D, 8.0D), this.villagerObj);
+
+ if (var1 == null) {
+ return false;
+ } else {
+ this.mate = (EntityVillager) var1;
+ return this.mate.getGrowingAge() == 0;
+ }
+ }
+ }
+ }
+
+ /**
+ * Execute a one shot task or start executing a continuous task
+ */
+ public void startExecuting() {
+ this.matingTimeout = 300;
+ this.villagerObj.setMating(true);
+ }
+
+ /**
+ * Resets the task
+ */
+ public void resetTask() {
+ this.villageObj = null;
+ this.mate = null;
+ this.villagerObj.setMating(false);
+ }
+
+ /**
+ * Returns whether an in-progress EntityAIBase should continue executing
+ */
+ public boolean continueExecuting() {
+ return this.matingTimeout >= 0 && this.checkSufficientDoorsPresentForNewVillager()
+ && this.villagerObj.getGrowingAge() == 0;
+ }
+
+ /**
+ * Updates the task
+ */
+ public void updateTask() {
+ --this.matingTimeout;
+ this.villagerObj.getLookHelper().setLookPositionWithEntity(this.mate, 10.0F, 30.0F);
+
+ if (this.villagerObj.getDistanceSqToEntity(this.mate) > 2.25D) {
+ this.villagerObj.getNavigator().tryMoveToEntityLiving(this.mate, 0.25F);
+ } else if (this.matingTimeout == 0 && this.mate.isMating()) {
+ this.giveBirth();
+ }
+
+ if (this.villagerObj.getRNG().nextInt(35) == 0) {
+ this.worldObj.setEntityState(this.villagerObj, (byte) 12);
+ }
+ }
+
+ private boolean checkSufficientDoorsPresentForNewVillager() {
+ if (!this.villageObj.isMatingSeason()) {
+ return false;
+ } else {
+ int var1 = (int) ((double) ((float) this.villageObj.getNumVillageDoors()) * 0.35D);
+ return this.villageObj.getNumVillagers() < var1;
+ }
+ }
+
+ private void giveBirth() {
+ EntityVillager var1 = this.villagerObj.func_90012_b(this.mate);
+ this.mate.setGrowingAge(6000);
+ this.villagerObj.setGrowingAge(6000);
+ var1.setGrowingAge(-24000);
+ var1.setLocationAndAngles(this.villagerObj.posX, this.villagerObj.posY, this.villagerObj.posZ, 0.0F, 0.0F);
+ this.worldObj.spawnEntityInWorld(var1);
+ this.worldObj.setEntityState(var1, (byte) 12);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAIWander.java b/sp-server/src/main/java/net/minecraft/src/EntityAIWander.java
new file mode 100644
index 0000000..c3f48db
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAIWander.java
@@ -0,0 +1,51 @@
+package net.minecraft.src;
+
+public class EntityAIWander extends EntityAIBase {
+ private EntityCreature entity;
+ private double xPosition;
+ private double yPosition;
+ private double zPosition;
+ private float speed;
+
+ public EntityAIWander(EntityCreature par1EntityCreature, float par2) {
+ this.entity = par1EntityCreature;
+ this.speed = par2;
+ this.setMutexBits(1);
+ }
+
+ /**
+ * Returns whether the EntityAIBase should begin execution.
+ */
+ public boolean shouldExecute() {
+ if (this.entity.getAge() >= 100) {
+ return false;
+ } else if (this.entity.getRNG().nextInt(120) != 0) {
+ return false;
+ } else {
+ Vec3 var1 = RandomPositionGenerator.findRandomTarget(this.entity, 10, 7);
+
+ if (var1 == null) {
+ return false;
+ } else {
+ this.xPosition = var1.xCoord;
+ this.yPosition = var1.yCoord;
+ this.zPosition = var1.zCoord;
+ return true;
+ }
+ }
+ }
+
+ /**
+ * Returns whether an in-progress EntityAIBase should continue executing
+ */
+ public boolean continueExecuting() {
+ return !this.entity.getNavigator().noPath();
+ }
+
+ /**
+ * Execute a one shot task or start executing a continuous task
+ */
+ public void startExecuting() {
+ this.entity.getNavigator().tryMoveToXYZ(this.xPosition, this.yPosition, this.zPosition, this.speed);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAIWatchClosest.java b/sp-server/src/main/java/net/minecraft/src/EntityAIWatchClosest.java
new file mode 100644
index 0000000..8cb045e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAIWatchClosest.java
@@ -0,0 +1,84 @@
+package net.minecraft.src;
+
+public class EntityAIWatchClosest extends EntityAIBase {
+ private EntityLiving theWatcher;
+
+ /** The closest entity which is being watched by this one. */
+ protected Entity closestEntity;
+ private float field_75333_c;
+ private int lookTime;
+ private float field_75331_e;
+ private Class watchedClass;
+
+ public EntityAIWatchClosest(EntityLiving par1EntityLiving, Class par2Class, float par3) {
+ this.theWatcher = par1EntityLiving;
+ this.watchedClass = par2Class;
+ this.field_75333_c = par3;
+ this.field_75331_e = 0.02F;
+ this.setMutexBits(2);
+ }
+
+ public EntityAIWatchClosest(EntityLiving par1EntityLiving, Class par2Class, float par3, float par4) {
+ this.theWatcher = par1EntityLiving;
+ this.watchedClass = par2Class;
+ this.field_75333_c = par3;
+ this.field_75331_e = par4;
+ this.setMutexBits(2);
+ }
+
+ /**
+ * Returns whether the EntityAIBase should begin execution.
+ */
+ public boolean shouldExecute() {
+ if (this.theWatcher.getRNG().nextFloat() >= this.field_75331_e) {
+ return false;
+ } else {
+ if (this.watchedClass == EntityPlayer.class) {
+ this.closestEntity = this.theWatcher.worldObj.getClosestPlayerToEntity(this.theWatcher,
+ (double) this.field_75333_c);
+ } else {
+ this.closestEntity = this.theWatcher.worldObj.findNearestEntityWithinAABB(this.watchedClass,
+ this.theWatcher.boundingBox.expand((double) this.field_75333_c, 3.0D,
+ (double) this.field_75333_c),
+ this.theWatcher);
+ }
+
+ return this.closestEntity != null;
+ }
+ }
+
+ /**
+ * Returns whether an in-progress EntityAIBase should continue executing
+ */
+ public boolean continueExecuting() {
+ return !this.closestEntity.isEntityAlive() ? false
+ : (this.theWatcher
+ .getDistanceSqToEntity(this.closestEntity) > (double) (this.field_75333_c * this.field_75333_c)
+ ? false
+ : this.lookTime > 0);
+ }
+
+ /**
+ * Execute a one shot task or start executing a continuous task
+ */
+ public void startExecuting() {
+ this.lookTime = 40 + this.theWatcher.getRNG().nextInt(40);
+ }
+
+ /**
+ * Resets the task
+ */
+ public void resetTask() {
+ this.closestEntity = null;
+ }
+
+ /**
+ * Updates the task
+ */
+ public void updateTask() {
+ this.theWatcher.getLookHelper().setLookPosition(this.closestEntity.posX,
+ this.closestEntity.posY + (double) this.closestEntity.getEyeHeight(), this.closestEntity.posZ, 10.0F,
+ (float) this.theWatcher.getVerticalFaceSpeed());
+ --this.lookTime;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAIWatchClosest2.java b/sp-server/src/main/java/net/minecraft/src/EntityAIWatchClosest2.java
new file mode 100644
index 0000000..8315273
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAIWatchClosest2.java
@@ -0,0 +1,8 @@
+package net.minecraft.src;
+
+public class EntityAIWatchClosest2 extends EntityAIWatchClosest {
+ public EntityAIWatchClosest2(EntityLiving par1EntityLiving, Class par2Class, float par3, float par4) {
+ super(par1EntityLiving, par2Class, par3, par4);
+ this.setMutexBits(3);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAgeable.java b/sp-server/src/main/java/net/minecraft/src/EntityAgeable.java
new file mode 100644
index 0000000..cb6ea86
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAgeable.java
@@ -0,0 +1,141 @@
+package net.minecraft.src;
+
+public abstract class EntityAgeable extends EntityCreature {
+ private float field_98056_d = -1.0F;
+ private float field_98057_e;
+
+ public EntityAgeable(World par1World) {
+ super(par1World);
+ }
+
+ public abstract EntityAgeable createChild(EntityAgeable var1);
+
+ /**
+ * Called when a player interacts with a mob. e.g. gets milk from a cow, gets
+ * into the saddle on a pig.
+ */
+ public boolean interact(EntityPlayer par1EntityPlayer) {
+ ItemStack var2 = par1EntityPlayer.inventory.getCurrentItem();
+
+ if (var2 != null && var2.itemID == Item.monsterPlacer.itemID && !this.worldObj.isRemote) {
+ Class var3 = EntityList.getClassFromID(var2.getItemDamage());
+
+ if (var3 != null && var3.isAssignableFrom(this.getClass())) {
+ EntityAgeable var4 = this.createChild(this);
+
+ if (var4 != null) {
+ var4.setGrowingAge(-24000);
+ var4.setLocationAndAngles(this.posX, this.posY, this.posZ, 0.0F, 0.0F);
+ this.worldObj.spawnEntityInWorld(var4);
+
+ if (var2.hasDisplayName()) {
+ var4.func_94058_c(var2.getDisplayName());
+ }
+
+ if (!par1EntityPlayer.capabilities.isCreativeMode) {
+ --var2.stackSize;
+
+ if (var2.stackSize <= 0) {
+ par1EntityPlayer.inventory.setInventorySlotContents(par1EntityPlayer.inventory.currentItem,
+ (ItemStack) null);
+ }
+ }
+ }
+ }
+ }
+
+ return super.interact(par1EntityPlayer);
+ }
+
+ protected void entityInit() {
+ super.entityInit();
+ this.dataWatcher.addObject(12, Integer.valueOf(0));
+ }
+
+ /**
+ * The age value may be negative or positive or zero. If it's negative, it get's
+ * incremented on each tick, if it's positive, it get's decremented each tick.
+ * Don't confuse this with EntityLiving.getAge. With a negative value the Entity
+ * is considered a child.
+ */
+ public int getGrowingAge() {
+ return this.dataWatcher.getWatchableObjectInt(12);
+ }
+
+ /**
+ * The age value may be negative or positive or zero. If it's negative, it get's
+ * incremented on each tick, if it's positive, it get's decremented each tick.
+ * With a negative value the Entity is considered a child.
+ */
+ public void setGrowingAge(int par1) {
+ this.dataWatcher.updateObject(12, Integer.valueOf(par1));
+ this.func_98054_a(this.isChild());
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ super.writeEntityToNBT(par1NBTTagCompound);
+ par1NBTTagCompound.setInteger("Age", this.getGrowingAge());
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ super.readEntityFromNBT(par1NBTTagCompound);
+ this.setGrowingAge(par1NBTTagCompound.getInteger("Age"));
+ }
+
+ /**
+ * Called frequently so the entity can update its state every tick as required.
+ * For example, zombies and skeletons use this to react to sunlight and start to
+ * burn.
+ */
+ public void onLivingUpdate() {
+ super.onLivingUpdate();
+
+ if (this.worldObj.isRemote) {
+ this.func_98054_a(this.isChild());
+ } else {
+ int var1 = this.getGrowingAge();
+
+ if (var1 < 0) {
+ ++var1;
+ this.setGrowingAge(var1);
+ } else if (var1 > 0) {
+ --var1;
+ this.setGrowingAge(var1);
+ }
+ }
+ }
+
+ /**
+ * If Animal, checks if the age timer is negative
+ */
+ public boolean isChild() {
+ return this.getGrowingAge() < 0;
+ }
+
+ public void func_98054_a(boolean par1) {
+ this.func_98055_j(par1 ? 0.5F : 1.0F);
+ }
+
+ /**
+ * Sets the width and height of the entity. Args: width, height
+ */
+ protected final void setSize(float par1, float par2) {
+ boolean var3 = this.field_98056_d > 0.0F;
+ this.field_98056_d = par1;
+ this.field_98057_e = par2;
+
+ if (!var3) {
+ this.func_98055_j(1.0F);
+ }
+ }
+
+ private void func_98055_j(float par1) {
+ super.setSize(this.field_98056_d * par1, this.field_98057_e * par1);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAmbientCreature.java b/sp-server/src/main/java/net/minecraft/src/EntityAmbientCreature.java
new file mode 100644
index 0000000..9c21b83
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAmbientCreature.java
@@ -0,0 +1,7 @@
+package net.minecraft.src;
+
+public abstract class EntityAmbientCreature extends EntityLiving implements IAnimals {
+ public EntityAmbientCreature(World par1World) {
+ super(par1World);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityAnimal.java b/sp-server/src/main/java/net/minecraft/src/EntityAnimal.java
new file mode 100644
index 0000000..bab58db
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityAnimal.java
@@ -0,0 +1,338 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+public abstract class EntityAnimal extends EntityAgeable implements IAnimals {
+ private int inLove;
+
+ /**
+ * This is representation of a counter for reproduction progress. (Note that
+ * this is different from the inLove which represent being in Love-Mode)
+ */
+ private int breeding = 0;
+
+ public EntityAnimal(World par1World) {
+ super(par1World);
+ }
+
+ /**
+ * main AI tick function, replaces updateEntityActionState
+ */
+ protected void updateAITick() {
+ if (this.getGrowingAge() != 0) {
+ this.inLove = 0;
+ }
+
+ super.updateAITick();
+ }
+
+ /**
+ * Called frequently so the entity can update its state every tick as required.
+ * For example, zombies and skeletons use this to react to sunlight and start to
+ * burn.
+ */
+ public void onLivingUpdate() {
+ super.onLivingUpdate();
+
+ if (this.getGrowingAge() != 0) {
+ this.inLove = 0;
+ }
+
+ if (this.inLove > 0) {
+ --this.inLove;
+ String var1 = "heart";
+
+ if (this.inLove % 10 == 0) {
+ double var2 = this.rand.nextGaussian() * 0.02D;
+ double var4 = this.rand.nextGaussian() * 0.02D;
+ double var6 = this.rand.nextGaussian() * 0.02D;
+ this.worldObj.spawnParticle(var1,
+ this.posX + (double) (this.rand.nextFloat() * this.width * 2.0F) - (double) this.width,
+ this.posY + 0.5D + (double) (this.rand.nextFloat() * this.height),
+ this.posZ + (double) (this.rand.nextFloat() * this.width * 2.0F) - (double) this.width, var2,
+ var4, var6);
+ }
+ } else {
+ this.breeding = 0;
+ }
+ }
+
+ /**
+ * Basic mob attack. Default to touch of death in EntityCreature. Overridden by
+ * each mob to define their attack.
+ */
+ protected void attackEntity(Entity par1Entity, float par2) {
+ if (par1Entity instanceof EntityPlayer) {
+ if (par2 < 3.0F) {
+ double var3 = par1Entity.posX - this.posX;
+ double var5 = par1Entity.posZ - this.posZ;
+ this.rotationYaw = (float) (Math.atan2(var5, var3) * 180.0D / Math.PI) - 90.0F;
+ this.hasAttacked = true;
+ }
+
+ EntityPlayer var7 = (EntityPlayer) par1Entity;
+
+ if (var7.getCurrentEquippedItem() == null || !this.isBreedingItem(var7.getCurrentEquippedItem())) {
+ this.entityToAttack = null;
+ }
+ } else if (par1Entity instanceof EntityAnimal) {
+ EntityAnimal var8 = (EntityAnimal) par1Entity;
+
+ if (this.getGrowingAge() > 0 && var8.getGrowingAge() < 0) {
+ if ((double) par2 < 2.5D) {
+ this.hasAttacked = true;
+ }
+ } else if (this.inLove > 0 && var8.inLove > 0) {
+ if (var8.entityToAttack == null) {
+ var8.entityToAttack = this;
+ }
+
+ if (var8.entityToAttack == this && (double) par2 < 3.5D) {
+ ++var8.inLove;
+ ++this.inLove;
+ ++this.breeding;
+
+ if (this.breeding % 4 == 0) {
+ this.worldObj.spawnParticle("heart",
+ this.posX + (double) (this.rand.nextFloat() * this.width * 2.0F) - (double) this.width,
+ this.posY + 0.5D + (double) (this.rand.nextFloat() * this.height),
+ this.posZ + (double) (this.rand.nextFloat() * this.width * 2.0F) - (double) this.width,
+ 0.0D, 0.0D, 0.0D);
+ }
+
+ if (this.breeding == 60) {
+ this.procreate((EntityAnimal) par1Entity);
+ }
+ } else {
+ this.breeding = 0;
+ }
+ } else {
+ this.breeding = 0;
+ this.entityToAttack = null;
+ }
+ }
+ }
+
+ /**
+ * Creates a baby animal according to the animal type of the target at the
+ * actual position and spawns 'love' particles.
+ */
+ private void procreate(EntityAnimal par1EntityAnimal) {
+ EntityAgeable var2 = this.createChild(par1EntityAnimal);
+
+ if (var2 != null) {
+ this.setGrowingAge(6000);
+ par1EntityAnimal.setGrowingAge(6000);
+ this.inLove = 0;
+ this.breeding = 0;
+ this.entityToAttack = null;
+ par1EntityAnimal.entityToAttack = null;
+ par1EntityAnimal.breeding = 0;
+ par1EntityAnimal.inLove = 0;
+ var2.setGrowingAge(-24000);
+ var2.setLocationAndAngles(this.posX, this.posY, this.posZ, this.rotationYaw, this.rotationPitch);
+
+ for (int var3 = 0; var3 < 7; ++var3) {
+ double var4 = this.rand.nextGaussian() * 0.02D;
+ double var6 = this.rand.nextGaussian() * 0.02D;
+ double var8 = this.rand.nextGaussian() * 0.02D;
+ this.worldObj.spawnParticle("heart",
+ this.posX + (double) (this.rand.nextFloat() * this.width * 2.0F) - (double) this.width,
+ this.posY + 0.5D + (double) (this.rand.nextFloat() * this.height),
+ this.posZ + (double) (this.rand.nextFloat() * this.width * 2.0F) - (double) this.width, var4,
+ var6, var8);
+ }
+
+ this.worldObj.spawnEntityInWorld(var2);
+ }
+ }
+
+ /**
+ * Called when the entity is attacked.
+ */
+ public boolean attackEntityFrom(DamageSource par1DamageSource, int par2) {
+ if (this.isEntityInvulnerable()) {
+ return false;
+ } else {
+ this.fleeingTick = 60;
+ this.entityToAttack = null;
+ this.inLove = 0;
+ return super.attackEntityFrom(par1DamageSource, par2);
+ }
+ }
+
+ /**
+ * Takes a coordinate in and returns a weight to determine how likely this
+ * creature will try to path to the block. Args: x, y, z
+ */
+ public float getBlockPathWeight(int par1, int par2, int par3) {
+ return this.worldObj.getBlockId(par1, par2 - 1, par3) == Block.grass.blockID ? 10.0F
+ : this.worldObj.getLightBrightness(par1, par2, par3) - 0.5F;
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ super.writeEntityToNBT(par1NBTTagCompound);
+ par1NBTTagCompound.setInteger("InLove", this.inLove);
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ super.readEntityFromNBT(par1NBTTagCompound);
+ this.inLove = par1NBTTagCompound.getInteger("InLove");
+ }
+
+ /**
+ * Finds the closest player within 16 blocks to attack, or null if this Entity
+ * isn't interested in attacking (Animals, Spiders at day, peaceful PigZombies).
+ */
+ protected Entity findPlayerToAttack() {
+ if (this.fleeingTick > 0) {
+ return null;
+ } else {
+ float var1 = 8.0F;
+ List var2;
+ int var3;
+ EntityAnimal var4;
+
+ if (this.inLove > 0) {
+ var2 = this.worldObj.getEntitiesWithinAABB(this.getClass(),
+ this.boundingBox.expand((double) var1, (double) var1, (double) var1));
+
+ for (var3 = 0; var3 < var2.size(); ++var3) {
+ var4 = (EntityAnimal) var2.get(var3);
+
+ if (var4 != this && var4.inLove > 0) {
+ return var4;
+ }
+ }
+ } else if (this.getGrowingAge() == 0) {
+ var2 = this.worldObj.getEntitiesWithinAABB(EntityPlayer.class,
+ this.boundingBox.expand((double) var1, (double) var1, (double) var1));
+
+ for (var3 = 0; var3 < var2.size(); ++var3) {
+ EntityPlayer var5 = (EntityPlayer) var2.get(var3);
+
+ if (var5.getCurrentEquippedItem() != null && this.isBreedingItem(var5.getCurrentEquippedItem())) {
+ return var5;
+ }
+ }
+ } else if (this.getGrowingAge() > 0) {
+ var2 = this.worldObj.getEntitiesWithinAABB(this.getClass(),
+ this.boundingBox.expand((double) var1, (double) var1, (double) var1));
+
+ for (var3 = 0; var3 < var2.size(); ++var3) {
+ var4 = (EntityAnimal) var2.get(var3);
+
+ if (var4 != this && var4.getGrowingAge() < 0) {
+ return var4;
+ }
+ }
+ }
+
+ return null;
+ }
+ }
+
+ /**
+ * Checks if the entity's current position is a valid location to spawn this
+ * entity.
+ */
+ public boolean getCanSpawnHere() {
+ int var1 = MathHelper.floor_double(this.posX);
+ int var2 = MathHelper.floor_double(this.boundingBox.minY);
+ int var3 = MathHelper.floor_double(this.posZ);
+ return this.worldObj.getBlockId(var1, var2 - 1, var3) == Block.grass.blockID
+ && this.worldObj.getFullBlockLightValue(var1, var2, var3) > 8 && super.getCanSpawnHere();
+ }
+
+ /**
+ * Get number of ticks, at least during which the living entity will be silent.
+ */
+ public int getTalkInterval() {
+ return 120;
+ }
+
+ /**
+ * Determines if an entity can be despawned, used on idle far away entities
+ */
+ protected boolean canDespawn() {
+ return false;
+ }
+
+ /**
+ * Get the experience points the entity currently has.
+ */
+ protected int getExperiencePoints(EntityPlayer par1EntityPlayer) {
+ return 1 + this.worldObj.rand.nextInt(3);
+ }
+
+ /**
+ * Checks if the parameter is an item which this animal can be fed to breed it
+ * (wheat, carrots or seeds depending on the animal type)
+ */
+ public boolean isBreedingItem(ItemStack par1ItemStack) {
+ return par1ItemStack.itemID == Item.wheat.itemID;
+ }
+
+ /**
+ * Called when a player interacts with a mob. e.g. gets milk from a cow, gets
+ * into the saddle on a pig.
+ */
+ public boolean interact(EntityPlayer par1EntityPlayer) {
+ ItemStack var2 = par1EntityPlayer.inventory.getCurrentItem();
+
+ if (var2 != null && this.isBreedingItem(var2) && this.getGrowingAge() == 0 && this.inLove <= 0) {
+ if (!par1EntityPlayer.capabilities.isCreativeMode) {
+ --var2.stackSize;
+
+ if (var2.stackSize <= 0) {
+ par1EntityPlayer.inventory.setInventorySlotContents(par1EntityPlayer.inventory.currentItem,
+ (ItemStack) null);
+ }
+ }
+
+ this.inLove = 600;
+ this.entityToAttack = null;
+
+ for (int var3 = 0; var3 < 7; ++var3) {
+ double var4 = this.rand.nextGaussian() * 0.02D;
+ double var6 = this.rand.nextGaussian() * 0.02D;
+ double var8 = this.rand.nextGaussian() * 0.02D;
+ this.worldObj.spawnParticle("heart",
+ this.posX + (double) (this.rand.nextFloat() * this.width * 2.0F) - (double) this.width,
+ this.posY + 0.5D + (double) (this.rand.nextFloat() * this.height),
+ this.posZ + (double) (this.rand.nextFloat() * this.width * 2.0F) - (double) this.width, var4,
+ var6, var8);
+ }
+
+ return true;
+ } else {
+ return super.interact(par1EntityPlayer);
+ }
+ }
+
+ /**
+ * Returns if the entity is currently in 'love mode'.
+ */
+ public boolean isInLove() {
+ return this.inLove > 0;
+ }
+
+ public void resetInLove() {
+ this.inLove = 0;
+ }
+
+ /**
+ * Returns true if the mob is currently able to mate with the specified mob.
+ */
+ public boolean canMateWith(EntityAnimal par1EntityAnimal) {
+ return par1EntityAnimal == this ? false
+ : (par1EntityAnimal.getClass() != this.getClass() ? false
+ : this.isInLove() && par1EntityAnimal.isInLove());
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityArrow.java b/sp-server/src/main/java/net/minecraft/src/EntityArrow.java
new file mode 100644
index 0000000..8ed639e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityArrow.java
@@ -0,0 +1,496 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+public class EntityArrow extends Entity implements IProjectile {
+ private int xTile = -1;
+ private int yTile = -1;
+ private int zTile = -1;
+ private int inTile = 0;
+ private int inData = 0;
+ private boolean inGround = false;
+
+ /** 1 if the player can pick up the arrow */
+ public int canBePickedUp = 0;
+
+ /** Seems to be some sort of timer for animating an arrow. */
+ public int arrowShake = 0;
+
+ /** The owner of this arrow. */
+ public Entity shootingEntity;
+ private int ticksInGround;
+ private int ticksInAir = 0;
+ private double damage = 2.0D;
+
+ /** The amount of knockback an arrow applies when it hits a mob. */
+ private int knockbackStrength;
+
+ public EntityArrow(World par1World) {
+ super(par1World);
+ this.renderDistanceWeight = 10.0D;
+ this.setSize(0.5F, 0.5F);
+ }
+
+ public EntityArrow(World par1World, double par2, double par4, double par6) {
+ super(par1World);
+ this.renderDistanceWeight = 10.0D;
+ this.setSize(0.5F, 0.5F);
+ this.setPosition(par2, par4, par6);
+ this.yOffset = 0.0F;
+ }
+
+ public EntityArrow(World par1World, EntityLiving par2EntityLiving, EntityLiving par3EntityLiving, float par4,
+ float par5) {
+ super(par1World);
+ this.renderDistanceWeight = 10.0D;
+ this.shootingEntity = par2EntityLiving;
+
+ if (par2EntityLiving instanceof EntityPlayer) {
+ this.canBePickedUp = 1;
+ }
+
+ this.posY = par2EntityLiving.posY + (double) par2EntityLiving.getEyeHeight() - 0.10000000149011612D;
+ double var6 = par3EntityLiving.posX - par2EntityLiving.posX;
+ double var8 = par3EntityLiving.boundingBox.minY + (double) (par3EntityLiving.height / 3.0F) - this.posY;
+ double var10 = par3EntityLiving.posZ - par2EntityLiving.posZ;
+ double var12 = (double) MathHelper.sqrt_double(var6 * var6 + var10 * var10);
+
+ if (var12 >= 1.0E-7D) {
+ float var14 = (float) (Math.atan2(var10, var6) * 180.0D / Math.PI) - 90.0F;
+ float var15 = (float) (-(Math.atan2(var8, var12) * 180.0D / Math.PI));
+ double var16 = var6 / var12;
+ double var18 = var10 / var12;
+ this.setLocationAndAngles(par2EntityLiving.posX + var16, this.posY, par2EntityLiving.posZ + var18, var14,
+ var15);
+ this.yOffset = 0.0F;
+ float var20 = (float) var12 * 0.2F;
+ this.setThrowableHeading(var6, var8 + (double) var20, var10, par4, par5);
+ }
+ }
+
+ public EntityArrow(World par1World, EntityLiving par2EntityLiving, float par3) {
+ super(par1World);
+ this.renderDistanceWeight = 10.0D;
+ this.shootingEntity = par2EntityLiving;
+
+ if (par2EntityLiving instanceof EntityPlayer) {
+ this.canBePickedUp = 1;
+ }
+
+ this.setSize(0.5F, 0.5F);
+ this.setLocationAndAngles(par2EntityLiving.posX,
+ par2EntityLiving.posY + (double) par2EntityLiving.getEyeHeight(), par2EntityLiving.posZ,
+ par2EntityLiving.rotationYaw, par2EntityLiving.rotationPitch);
+ this.posX -= (double) (MathHelper.cos(this.rotationYaw / 180.0F * (float) Math.PI) * 0.16F);
+ this.posY -= 0.10000000149011612D;
+ this.posZ -= (double) (MathHelper.sin(this.rotationYaw / 180.0F * (float) Math.PI) * 0.16F);
+ this.setPosition(this.posX, this.posY, this.posZ);
+ this.yOffset = 0.0F;
+ this.motionX = (double) (-MathHelper.sin(this.rotationYaw / 180.0F * (float) Math.PI)
+ * MathHelper.cos(this.rotationPitch / 180.0F * (float) Math.PI));
+ this.motionZ = (double) (MathHelper.cos(this.rotationYaw / 180.0F * (float) Math.PI)
+ * MathHelper.cos(this.rotationPitch / 180.0F * (float) Math.PI));
+ this.motionY = (double) (-MathHelper.sin(this.rotationPitch / 180.0F * (float) Math.PI));
+ this.setThrowableHeading(this.motionX, this.motionY, this.motionZ, par3 * 1.5F, 1.0F);
+ }
+
+ protected void entityInit() {
+ this.dataWatcher.addObject(16, Byte.valueOf((byte) 0));
+ }
+
+ /**
+ * Similar to setArrowHeading, it's point the throwable entity to a x, y, z
+ * direction.
+ */
+ public void setThrowableHeading(double par1, double par3, double par5, float par7, float par8) {
+ float var9 = MathHelper.sqrt_double(par1 * par1 + par3 * par3 + par5 * par5);
+ par1 /= (double) var9;
+ par3 /= (double) var9;
+ par5 /= (double) var9;
+ par1 += this.rand.nextGaussian() * (double) (this.rand.nextBoolean() ? -1 : 1) * 0.007499999832361937D
+ * (double) par8;
+ par3 += this.rand.nextGaussian() * (double) (this.rand.nextBoolean() ? -1 : 1) * 0.007499999832361937D
+ * (double) par8;
+ par5 += this.rand.nextGaussian() * (double) (this.rand.nextBoolean() ? -1 : 1) * 0.007499999832361937D
+ * (double) par8;
+ par1 *= (double) par7;
+ par3 *= (double) par7;
+ par5 *= (double) par7;
+ this.motionX = par1;
+ this.motionY = par3;
+ this.motionZ = par5;
+ float var10 = MathHelper.sqrt_double(par1 * par1 + par5 * par5);
+ this.prevRotationYaw = this.rotationYaw = (float) (Math.atan2(par1, par5) * 180.0D / Math.PI);
+ this.prevRotationPitch = this.rotationPitch = (float) (Math.atan2(par3, (double) var10) * 180.0D / Math.PI);
+ this.ticksInGround = 0;
+ }
+
+ /**
+ * Called to update the entity's position/logic.
+ */
+ public void onUpdate() {
+ super.onUpdate();
+
+ if (this.prevRotationPitch == 0.0F && this.prevRotationYaw == 0.0F) {
+ float var1 = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ);
+ this.prevRotationYaw = this.rotationYaw = (float) (Math.atan2(this.motionX, this.motionZ) * 180.0D
+ / Math.PI);
+ this.prevRotationPitch = this.rotationPitch = (float) (Math.atan2(this.motionY, (double) var1) * 180.0D
+ / Math.PI);
+ }
+
+ int var16 = this.worldObj.getBlockId(this.xTile, this.yTile, this.zTile);
+
+ if (var16 > 0) {
+ Block.blocksList[var16].setBlockBoundsBasedOnState(this.worldObj, this.xTile, this.yTile, this.zTile);
+ AxisAlignedBB var2 = Block.blocksList[var16].getCollisionBoundingBoxFromPool(this.worldObj, this.xTile,
+ this.yTile, this.zTile);
+
+ if (var2 != null && var2
+ .isVecInside(this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX, this.posY, this.posZ))) {
+ this.inGround = true;
+ }
+ }
+
+ if (this.arrowShake > 0) {
+ --this.arrowShake;
+ }
+
+ if (this.inGround) {
+ int var18 = this.worldObj.getBlockId(this.xTile, this.yTile, this.zTile);
+ int var19 = this.worldObj.getBlockMetadata(this.xTile, this.yTile, this.zTile);
+
+ if (var18 == this.inTile && var19 == this.inData) {
+ ++this.ticksInGround;
+
+ if (this.ticksInGround == 1200) {
+ this.setDead();
+ }
+ } else {
+ this.inGround = false;
+ this.motionX *= (double) (this.rand.nextFloat() * 0.2F);
+ this.motionY *= (double) (this.rand.nextFloat() * 0.2F);
+ this.motionZ *= (double) (this.rand.nextFloat() * 0.2F);
+ this.ticksInGround = 0;
+ this.ticksInAir = 0;
+ }
+ } else {
+ ++this.ticksInAir;
+ Vec3 var17 = this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX, this.posY, this.posZ);
+ Vec3 var3 = this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX + this.motionX,
+ this.posY + this.motionY, this.posZ + this.motionZ);
+ MovingObjectPosition var4 = this.worldObj.rayTraceBlocks_do_do(var17, var3, false, true);
+ var17 = this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX, this.posY, this.posZ);
+ var3 = this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX + this.motionX, this.posY + this.motionY,
+ this.posZ + this.motionZ);
+
+ if (var4 != null) {
+ var3 = this.worldObj.getWorldVec3Pool().getVecFromPool(var4.hitVec.xCoord, var4.hitVec.yCoord,
+ var4.hitVec.zCoord);
+ }
+
+ Entity var5 = null;
+ List var6 = this.worldObj.getEntitiesWithinAABBExcludingEntity(this,
+ this.boundingBox.addCoord(this.motionX, this.motionY, this.motionZ).expand(1.0D, 1.0D, 1.0D));
+ double var7 = 0.0D;
+ int var9;
+ float var11;
+
+ for (var9 = 0; var9 < var6.size(); ++var9) {
+ Entity var10 = (Entity) var6.get(var9);
+
+ if (var10.canBeCollidedWith() && (var10 != this.shootingEntity || this.ticksInAir >= 5)) {
+ var11 = 0.3F;
+ AxisAlignedBB var12 = var10.boundingBox.expand((double) var11, (double) var11, (double) var11);
+ MovingObjectPosition var13 = var12.calculateIntercept(var17, var3);
+
+ if (var13 != null) {
+ double var14 = var17.distanceTo(var13.hitVec);
+
+ if (var14 < var7 || var7 == 0.0D) {
+ var5 = var10;
+ var7 = var14;
+ }
+ }
+ }
+ }
+
+ if (var5 != null) {
+ var4 = new MovingObjectPosition(var5);
+ }
+
+ if (var4 != null && var4.entityHit != null && var4.entityHit instanceof EntityPlayer) {
+ EntityPlayer var20 = (EntityPlayer) var4.entityHit;
+
+ if (var20.capabilities.disableDamage || this.shootingEntity instanceof EntityPlayer
+ && !((EntityPlayer) this.shootingEntity).func_96122_a(var20)) {
+ var4 = null;
+ }
+ }
+
+ float var21;
+ float var27;
+
+ if (var4 != null) {
+ if (var4.entityHit != null) {
+ var21 = MathHelper.sqrt_double(
+ this.motionX * this.motionX + this.motionY * this.motionY + this.motionZ * this.motionZ);
+ int var22 = MathHelper.ceiling_double_int((double) var21 * this.damage);
+
+ if (this.getIsCritical()) {
+ var22 += this.rand.nextInt(var22 / 2 + 2);
+ }
+
+ DamageSource var23 = null;
+
+ if (this.shootingEntity == null) {
+ var23 = DamageSource.causeArrowDamage(this, this);
+ } else {
+ var23 = DamageSource.causeArrowDamage(this, this.shootingEntity);
+ }
+
+ if (this.isBurning() && !(var4.entityHit instanceof EntityEnderman)) {
+ var4.entityHit.setFire(5);
+ }
+
+ if (var4.entityHit.attackEntityFrom(var23, var22)) {
+ if (var4.entityHit instanceof EntityLiving) {
+ EntityLiving var25 = (EntityLiving) var4.entityHit;
+
+ if (!this.worldObj.isRemote) {
+ var25.setArrowCountInEntity(var25.getArrowCountInEntity() + 1);
+ }
+
+ if (this.knockbackStrength > 0) {
+ var27 = MathHelper
+ .sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ);
+
+ if (var27 > 0.0F) {
+ var4.entityHit.addVelocity(
+ this.motionX * (double) this.knockbackStrength * 0.6000000238418579D
+ / (double) var27,
+ 0.1D, this.motionZ * (double) this.knockbackStrength * 0.6000000238418579D
+ / (double) var27);
+ }
+ }
+
+ if (this.shootingEntity != null) {
+ EnchantmentThorns.func_92096_a(this.shootingEntity, var25, this.rand);
+ }
+
+ if (this.shootingEntity != null && var4.entityHit != this.shootingEntity
+ && var4.entityHit instanceof EntityPlayer
+ && this.shootingEntity instanceof EntityPlayerMP) {
+ ((EntityPlayerMP) this.shootingEntity).playerNetServerHandler
+ .sendPacket(new Packet70GameEvent(6, 0));
+ }
+ }
+
+ this.playSound("random.bowhit", 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F));
+
+ if (!(var4.entityHit instanceof EntityEnderman)) {
+ this.setDead();
+ }
+ } else {
+ this.motionX *= -0.10000000149011612D;
+ this.motionY *= -0.10000000149011612D;
+ this.motionZ *= -0.10000000149011612D;
+ this.rotationYaw += 180.0F;
+ this.prevRotationYaw += 180.0F;
+ this.ticksInAir = 0;
+ }
+ } else {
+ this.xTile = var4.blockX;
+ this.yTile = var4.blockY;
+ this.zTile = var4.blockZ;
+ this.inTile = this.worldObj.getBlockId(this.xTile, this.yTile, this.zTile);
+ this.inData = this.worldObj.getBlockMetadata(this.xTile, this.yTile, this.zTile);
+ this.motionX = (double) ((float) (var4.hitVec.xCoord - this.posX));
+ this.motionY = (double) ((float) (var4.hitVec.yCoord - this.posY));
+ this.motionZ = (double) ((float) (var4.hitVec.zCoord - this.posZ));
+ var21 = MathHelper.sqrt_double(
+ this.motionX * this.motionX + this.motionY * this.motionY + this.motionZ * this.motionZ);
+ this.posX -= this.motionX / (double) var21 * 0.05000000074505806D;
+ this.posY -= this.motionY / (double) var21 * 0.05000000074505806D;
+ this.posZ -= this.motionZ / (double) var21 * 0.05000000074505806D;
+ this.playSound("random.bowhit", 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F));
+ this.inGround = true;
+ this.arrowShake = 7;
+ this.setIsCritical(false);
+
+ if (this.inTile != 0) {
+ Block.blocksList[this.inTile].onEntityCollidedWithBlock(this.worldObj, this.xTile, this.yTile,
+ this.zTile, this);
+ }
+ }
+ }
+
+ if (this.getIsCritical()) {
+ for (var9 = 0; var9 < 4; ++var9) {
+ this.worldObj.spawnParticle("crit", this.posX + this.motionX * (double) var9 / 4.0D,
+ this.posY + this.motionY * (double) var9 / 4.0D,
+ this.posZ + this.motionZ * (double) var9 / 4.0D, -this.motionX, -this.motionY + 0.2D,
+ -this.motionZ);
+ }
+ }
+
+ this.posX += this.motionX;
+ this.posY += this.motionY;
+ this.posZ += this.motionZ;
+ var21 = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ);
+ this.rotationYaw = (float) (Math.atan2(this.motionX, this.motionZ) * 180.0D / Math.PI);
+
+ for (this.rotationPitch = (float) (Math.atan2(this.motionY, (double) var21) * 180.0D
+ / Math.PI); this.rotationPitch
+ - this.prevRotationPitch < -180.0F; this.prevRotationPitch -= 360.0F) {
+ ;
+ }
+
+ while (this.rotationPitch - this.prevRotationPitch >= 180.0F) {
+ this.prevRotationPitch += 360.0F;
+ }
+
+ while (this.rotationYaw - this.prevRotationYaw < -180.0F) {
+ this.prevRotationYaw -= 360.0F;
+ }
+
+ while (this.rotationYaw - this.prevRotationYaw >= 180.0F) {
+ this.prevRotationYaw += 360.0F;
+ }
+
+ this.rotationPitch = this.prevRotationPitch + (this.rotationPitch - this.prevRotationPitch) * 0.2F;
+ this.rotationYaw = this.prevRotationYaw + (this.rotationYaw - this.prevRotationYaw) * 0.2F;
+ float var24 = 0.99F;
+ var11 = 0.05F;
+
+ if (this.isInWater()) {
+ for (int var26 = 0; var26 < 4; ++var26) {
+ var27 = 0.25F;
+ this.worldObj.spawnParticle("bubble", this.posX - this.motionX * (double) var27,
+ this.posY - this.motionY * (double) var27, this.posZ - this.motionZ * (double) var27,
+ this.motionX, this.motionY, this.motionZ);
+ }
+
+ var24 = 0.8F;
+ }
+
+ this.motionX *= (double) var24;
+ this.motionY *= (double) var24;
+ this.motionZ *= (double) var24;
+ this.motionY -= (double) var11;
+ this.setPosition(this.posX, this.posY, this.posZ);
+ this.doBlockCollisions();
+ }
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ par1NBTTagCompound.setShort("xTile", (short) this.xTile);
+ par1NBTTagCompound.setShort("yTile", (short) this.yTile);
+ par1NBTTagCompound.setShort("zTile", (short) this.zTile);
+ par1NBTTagCompound.setByte("inTile", (byte) this.inTile);
+ par1NBTTagCompound.setByte("inData", (byte) this.inData);
+ par1NBTTagCompound.setByte("shake", (byte) this.arrowShake);
+ par1NBTTagCompound.setByte("inGround", (byte) (this.inGround ? 1 : 0));
+ par1NBTTagCompound.setByte("pickup", (byte) this.canBePickedUp);
+ par1NBTTagCompound.setDouble("damage", this.damage);
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ this.xTile = par1NBTTagCompound.getShort("xTile");
+ this.yTile = par1NBTTagCompound.getShort("yTile");
+ this.zTile = par1NBTTagCompound.getShort("zTile");
+ this.inTile = par1NBTTagCompound.getByte("inTile") & 255;
+ this.inData = par1NBTTagCompound.getByte("inData") & 255;
+ this.arrowShake = par1NBTTagCompound.getByte("shake") & 255;
+ this.inGround = par1NBTTagCompound.getByte("inGround") == 1;
+
+ if (par1NBTTagCompound.hasKey("damage")) {
+ this.damage = par1NBTTagCompound.getDouble("damage");
+ }
+
+ if (par1NBTTagCompound.hasKey("pickup")) {
+ this.canBePickedUp = par1NBTTagCompound.getByte("pickup");
+ } else if (par1NBTTagCompound.hasKey("player")) {
+ this.canBePickedUp = par1NBTTagCompound.getBoolean("player") ? 1 : 0;
+ }
+ }
+
+ /**
+ * Called by a player entity when they collide with an entity
+ */
+ public void onCollideWithPlayer(EntityPlayer par1EntityPlayer) {
+ if (!this.worldObj.isRemote && this.inGround && this.arrowShake <= 0) {
+ boolean var2 = this.canBePickedUp == 1
+ || this.canBePickedUp == 2 && par1EntityPlayer.capabilities.isCreativeMode;
+
+ if (this.canBePickedUp == 1
+ && !par1EntityPlayer.inventory.addItemStackToInventory(new ItemStack(Item.arrow, 1))) {
+ var2 = false;
+ }
+
+ if (var2) {
+ this.playSound("random.pop", 0.2F,
+ ((this.rand.nextFloat() - this.rand.nextFloat()) * 0.7F + 1.0F) * 2.0F);
+ par1EntityPlayer.onItemPickup(this, 1);
+ this.setDead();
+ }
+ }
+ }
+
+ /**
+ * returns if this entity triggers Block.onEntityWalking on the blocks they walk
+ * on. used for spiders and wolves to prevent them from trampling crops
+ */
+ protected boolean canTriggerWalking() {
+ return false;
+ }
+
+ public void setDamage(double par1) {
+ this.damage = par1;
+ }
+
+ public double getDamage() {
+ return this.damage;
+ }
+
+ /**
+ * Sets the amount of knockback the arrow applies when it hits a mob.
+ */
+ public void setKnockbackStrength(int par1) {
+ this.knockbackStrength = par1;
+ }
+
+ /**
+ * If returns false, the item will not inflict any damage against entities.
+ */
+ public boolean canAttackWithItem() {
+ return false;
+ }
+
+ /**
+ * Whether the arrow has a stream of critical hit particles flying behind it.
+ */
+ public void setIsCritical(boolean par1) {
+ byte var2 = this.dataWatcher.getWatchableObjectByte(16);
+
+ if (par1) {
+ this.dataWatcher.updateObject(16, Byte.valueOf((byte) (var2 | 1)));
+ } else {
+ this.dataWatcher.updateObject(16, Byte.valueOf((byte) (var2 & -2)));
+ }
+ }
+
+ /**
+ * Whether the arrow has a stream of critical hit particles flying behind it.
+ */
+ public boolean getIsCritical() {
+ byte var1 = this.dataWatcher.getWatchableObjectByte(16);
+ return (var1 & 1) != 0;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityBat.java b/sp-server/src/main/java/net/minecraft/src/EntityBat.java
new file mode 100644
index 0000000..0062f8f
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityBat.java
@@ -0,0 +1,253 @@
+package net.minecraft.src;
+
+import java.util.Calendar;
+
+public class EntityBat extends EntityAmbientCreature {
+ /** Coordinates of where the bat spawned. */
+ private ChunkCoordinates spawnPosition;
+
+ public EntityBat(World par1World) {
+ super(par1World);
+ this.texture = "/mob/bat.png";
+ this.setSize(0.5F, 0.9F);
+ this.setIsBatHanging(true);
+ }
+
+ protected void entityInit() {
+ super.entityInit();
+ this.dataWatcher.addObject(16, Byte.valueOf((byte) 0));
+ }
+
+ /**
+ * Returns the volume for the sounds this mob makes.
+ */
+ protected float getSoundVolume() {
+ return 0.1F;
+ }
+
+ /**
+ * Gets the pitch of living sounds in living entities.
+ */
+ protected float getSoundPitch() {
+ return super.getSoundPitch() * 0.95F;
+ }
+
+ /**
+ * Returns the sound this mob makes while it's alive.
+ */
+ protected String getLivingSound() {
+ return this.getIsBatHanging() && this.rand.nextInt(4) != 0 ? null : "mob.bat.idle";
+ }
+
+ /**
+ * Returns the sound this mob makes when it is hurt.
+ */
+ protected String getHurtSound() {
+ return "mob.bat.hurt";
+ }
+
+ /**
+ * Returns the sound this mob makes on death.
+ */
+ protected String getDeathSound() {
+ return "mob.bat.death";
+ }
+
+ /**
+ * Returns true if this entity should push and be pushed by other entities when
+ * colliding.
+ */
+ public boolean canBePushed() {
+ return false;
+ }
+
+ protected void collideWithEntity(Entity par1Entity) {
+ }
+
+ protected void func_85033_bc() {
+ }
+
+ public int getMaxHealth() {
+ return 6;
+ }
+
+ public boolean getIsBatHanging() {
+ return (this.dataWatcher.getWatchableObjectByte(16) & 1) != 0;
+ }
+
+ public void setIsBatHanging(boolean par1) {
+ byte var2 = this.dataWatcher.getWatchableObjectByte(16);
+
+ if (par1) {
+ this.dataWatcher.updateObject(16, Byte.valueOf((byte) (var2 | 1)));
+ } else {
+ this.dataWatcher.updateObject(16, Byte.valueOf((byte) (var2 & -2)));
+ }
+ }
+
+ /**
+ * Returns true if the newer Entity AI code should be run
+ */
+ protected boolean isAIEnabled() {
+ return true;
+ }
+
+ /**
+ * Called to update the entity's position/logic.
+ */
+ public void onUpdate() {
+ super.onUpdate();
+
+ if (this.getIsBatHanging()) {
+ this.motionX = this.motionY = this.motionZ = 0.0D;
+ this.posY = (double) MathHelper.floor_double(this.posY) + 1.0D - (double) this.height;
+ } else {
+ this.motionY *= 0.6000000238418579D;
+ }
+ }
+
+ protected void updateAITasks() {
+ super.updateAITasks();
+
+ if (this.getIsBatHanging()) {
+ if (!this.worldObj.isBlockNormalCube(MathHelper.floor_double(this.posX), (int) this.posY + 1,
+ MathHelper.floor_double(this.posZ))) {
+ this.setIsBatHanging(false);
+ this.worldObj.playAuxSFXAtEntity((EntityPlayer) null, 1015, (int) this.posX, (int) this.posY,
+ (int) this.posZ, 0);
+ } else {
+ if (this.rand.nextInt(200) == 0) {
+ this.rotationYawHead = (float) this.rand.nextInt(360);
+ }
+
+ if (this.worldObj.getClosestPlayerToEntity(this, 4.0D) != null) {
+ this.setIsBatHanging(false);
+ this.worldObj.playAuxSFXAtEntity((EntityPlayer) null, 1015, (int) this.posX, (int) this.posY,
+ (int) this.posZ, 0);
+ }
+ }
+ } else {
+ if (this.spawnPosition != null && (!this.worldObj.isAirBlock(this.spawnPosition.posX,
+ this.spawnPosition.posY, this.spawnPosition.posZ) || this.spawnPosition.posY < 1)) {
+ this.spawnPosition = null;
+ }
+
+ if (this.spawnPosition == null || this.rand.nextInt(30) == 0 || this.spawnPosition
+ .getDistanceSquared((int) this.posX, (int) this.posY, (int) this.posZ) < 4.0F) {
+ this.spawnPosition = new ChunkCoordinates((int) this.posX + this.rand.nextInt(7) - this.rand.nextInt(7),
+ (int) this.posY + this.rand.nextInt(6) - 2,
+ (int) this.posZ + this.rand.nextInt(7) - this.rand.nextInt(7));
+ }
+
+ double var1 = (double) this.spawnPosition.posX + 0.5D - this.posX;
+ double var3 = (double) this.spawnPosition.posY + 0.1D - this.posY;
+ double var5 = (double) this.spawnPosition.posZ + 0.5D - this.posZ;
+ this.motionX += (Math.signum(var1) * 0.5D - this.motionX) * 0.10000000149011612D;
+ this.motionY += (Math.signum(var3) * 0.699999988079071D - this.motionY) * 0.10000000149011612D;
+ this.motionZ += (Math.signum(var5) * 0.5D - this.motionZ) * 0.10000000149011612D;
+ float var7 = (float) (Math.atan2(this.motionZ, this.motionX) * 180.0D / Math.PI) - 90.0F;
+ float var8 = MathHelper.wrapAngleTo180_float(var7 - this.rotationYaw);
+ this.moveForward = 0.5F;
+ this.rotationYaw += var8;
+
+ if (this.rand.nextInt(100) == 0 && this.worldObj.isBlockNormalCube(MathHelper.floor_double(this.posX),
+ (int) this.posY + 1, MathHelper.floor_double(this.posZ))) {
+ this.setIsBatHanging(true);
+ }
+ }
+ }
+
+ /**
+ * returns if this entity triggers Block.onEntityWalking on the blocks they walk
+ * on. used for spiders and wolves to prevent them from trampling crops
+ */
+ protected boolean canTriggerWalking() {
+ return false;
+ }
+
+ /**
+ * Called when the mob is falling. Calculates and applies fall damage.
+ */
+ protected void fall(float par1) {
+ }
+
+ /**
+ * Takes in the distance the entity has fallen this tick and whether its on the
+ * ground to update the fall distance and deal fall damage if landing on the
+ * ground. Args: distanceFallenThisTick, onGround
+ */
+ protected void updateFallState(double par1, boolean par3) {
+ }
+
+ /**
+ * Return whether this entity should NOT trigger a pressure plate or a tripwire.
+ */
+ public boolean doesEntityNotTriggerPressurePlate() {
+ return true;
+ }
+
+ /**
+ * Called when the entity is attacked.
+ */
+ public boolean attackEntityFrom(DamageSource par1DamageSource, int par2) {
+ if (this.isEntityInvulnerable()) {
+ return false;
+ } else {
+ if (!this.worldObj.isRemote && this.getIsBatHanging()) {
+ this.setIsBatHanging(false);
+ }
+
+ return super.attackEntityFrom(par1DamageSource, par2);
+ }
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ super.readEntityFromNBT(par1NBTTagCompound);
+ this.dataWatcher.updateObject(16, Byte.valueOf(par1NBTTagCompound.getByte("BatFlags")));
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ super.writeEntityToNBT(par1NBTTagCompound);
+ par1NBTTagCompound.setByte("BatFlags", this.dataWatcher.getWatchableObjectByte(16));
+ }
+
+ /**
+ * Checks if the entity's current position is a valid location to spawn this
+ * entity.
+ */
+ public boolean getCanSpawnHere() {
+ int var1 = MathHelper.floor_double(this.boundingBox.minY);
+
+ if (var1 >= 63) {
+ return false;
+ } else {
+ int var2 = MathHelper.floor_double(this.posX);
+ int var3 = MathHelper.floor_double(this.posZ);
+ int var4 = this.worldObj.getBlockLightValue(var2, var1, var3);
+ byte var5 = 4;
+ Calendar var6 = this.worldObj.getCurrentDate();
+
+ if ((var6.get(2) + 1 != 10 || var6.get(5) < 20) && (var6.get(2) + 1 != 11 || var6.get(5) > 3)) {
+ if (this.rand.nextBoolean()) {
+ return false;
+ }
+ } else {
+ var5 = 7;
+ }
+
+ return var4 > this.rand.nextInt(var5) ? false : super.getCanSpawnHere();
+ }
+ }
+
+ /**
+ * Initialize this creature.
+ */
+ public void initCreature() {
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityBlaze.java b/sp-server/src/main/java/net/minecraft/src/EntityBlaze.java
new file mode 100644
index 0000000..e821e78
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityBlaze.java
@@ -0,0 +1,210 @@
+package net.minecraft.src;
+
+public class EntityBlaze extends EntityMob {
+ /** Random offset used in floating behaviour */
+ private float heightOffset = 0.5F;
+
+ /** ticks until heightOffset is randomized */
+ private int heightOffsetUpdateTime;
+ private int field_70846_g;
+
+ public EntityBlaze(World par1World) {
+ super(par1World);
+ this.texture = "/mob/fire.png";
+ this.isImmuneToFire = true;
+ this.experienceValue = 10;
+ }
+
+ public int getMaxHealth() {
+ return 20;
+ }
+
+ protected void entityInit() {
+ super.entityInit();
+ this.dataWatcher.addObject(16, Byte.valueOf((byte) 0));
+ }
+
+ /**
+ * Returns the sound this mob makes while it's alive.
+ */
+ protected String getLivingSound() {
+ return "mob.blaze.breathe";
+ }
+
+ /**
+ * Returns the sound this mob makes when it is hurt.
+ */
+ protected String getHurtSound() {
+ return "mob.blaze.hit";
+ }
+
+ /**
+ * Returns the sound this mob makes on death.
+ */
+ protected String getDeathSound() {
+ return "mob.blaze.death";
+ }
+
+ /**
+ * Gets how bright this entity is.
+ */
+ public float getBrightness(float par1) {
+ return 1.0F;
+ }
+
+ /**
+ * Called frequently so the entity can update its state every tick as required.
+ * For example, zombies and skeletons use this to react to sunlight and start to
+ * burn.
+ */
+ public void onLivingUpdate() {
+ if (!this.worldObj.isRemote) {
+ if (this.isWet()) {
+ this.attackEntityFrom(DamageSource.drown, 1);
+ }
+
+ --this.heightOffsetUpdateTime;
+
+ if (this.heightOffsetUpdateTime <= 0) {
+ this.heightOffsetUpdateTime = 100;
+ this.heightOffset = 0.5F + (float) this.rand.nextGaussian() * 3.0F;
+ }
+
+ if (this.getEntityToAttack() != null
+ && this.getEntityToAttack().posY + (double) this.getEntityToAttack().getEyeHeight() > this.posY
+ + (double) this.getEyeHeight() + (double) this.heightOffset) {
+ this.motionY += (0.30000001192092896D - this.motionY) * 0.30000001192092896D;
+ }
+ }
+
+ if (this.rand.nextInt(24) == 0) {
+ this.worldObj.playSoundEffect(this.posX + 0.5D, this.posY + 0.5D, this.posZ + 0.5D, "fire.fire",
+ 1.0F + this.rand.nextFloat(), this.rand.nextFloat() * 0.7F + 0.3F);
+ }
+
+ if (!this.onGround && this.motionY < 0.0D) {
+ this.motionY *= 0.6D;
+ }
+
+ for (int var1 = 0; var1 < 2; ++var1) {
+ this.worldObj.spawnParticle("largesmoke", this.posX + (this.rand.nextDouble() - 0.5D) * (double) this.width,
+ this.posY + this.rand.nextDouble() * (double) this.height,
+ this.posZ + (this.rand.nextDouble() - 0.5D) * (double) this.width, 0.0D, 0.0D, 0.0D);
+ }
+
+ super.onLivingUpdate();
+ }
+
+ /**
+ * Basic mob attack. Default to touch of death in EntityCreature. Overridden by
+ * each mob to define their attack.
+ */
+ protected void attackEntity(Entity par1Entity, float par2) {
+ if (this.attackTime <= 0 && par2 < 2.0F && par1Entity.boundingBox.maxY > this.boundingBox.minY
+ && par1Entity.boundingBox.minY < this.boundingBox.maxY) {
+ this.attackTime = 20;
+ this.attackEntityAsMob(par1Entity);
+ } else if (par2 < 30.0F) {
+ double var3 = par1Entity.posX - this.posX;
+ double var5 = par1Entity.boundingBox.minY + (double) (par1Entity.height / 2.0F)
+ - (this.posY + (double) (this.height / 2.0F));
+ double var7 = par1Entity.posZ - this.posZ;
+
+ if (this.attackTime == 0) {
+ ++this.field_70846_g;
+
+ if (this.field_70846_g == 1) {
+ this.attackTime = 60;
+ this.func_70844_e(true);
+ } else if (this.field_70846_g <= 4) {
+ this.attackTime = 6;
+ } else {
+ this.attackTime = 100;
+ this.field_70846_g = 0;
+ this.func_70844_e(false);
+ }
+
+ if (this.field_70846_g > 1) {
+ float var9 = MathHelper.sqrt_float(par2) * 0.5F;
+ this.worldObj.playAuxSFXAtEntity((EntityPlayer) null, 1009, (int) this.posX, (int) this.posY,
+ (int) this.posZ, 0);
+
+ for (int var10 = 0; var10 < 1; ++var10) {
+ EntitySmallFireball var11 = new EntitySmallFireball(this.worldObj, this,
+ var3 + this.rand.nextGaussian() * (double) var9, var5,
+ var7 + this.rand.nextGaussian() * (double) var9);
+ var11.posY = this.posY + (double) (this.height / 2.0F) + 0.5D;
+ this.worldObj.spawnEntityInWorld(var11);
+ }
+ }
+ }
+
+ this.rotationYaw = (float) (Math.atan2(var7, var3) * 180.0D / Math.PI) - 90.0F;
+ this.hasAttacked = true;
+ }
+ }
+
+ /**
+ * Called when the mob is falling. Calculates and applies fall damage.
+ */
+ protected void fall(float par1) {
+ }
+
+ /**
+ * Returns the item ID for the item the mob drops on death.
+ */
+ protected int getDropItemId() {
+ return Item.blazeRod.itemID;
+ }
+
+ /**
+ * Returns true if the entity is on fire. Used by render to add the fire effect
+ * on rendering.
+ */
+ public boolean isBurning() {
+ return this.func_70845_n();
+ }
+
+ /**
+ * Drop 0-2 items of this living's type
+ */
+ protected void dropFewItems(boolean par1, int par2) {
+ if (par1) {
+ int var3 = this.rand.nextInt(2 + par2);
+
+ for (int var4 = 0; var4 < var3; ++var4) {
+ this.dropItem(Item.blazeRod.itemID, 1);
+ }
+ }
+ }
+
+ public boolean func_70845_n() {
+ return (this.dataWatcher.getWatchableObjectByte(16) & 1) != 0;
+ }
+
+ public void func_70844_e(boolean par1) {
+ byte var2 = this.dataWatcher.getWatchableObjectByte(16);
+
+ if (par1) {
+ var2 = (byte) (var2 | 1);
+ } else {
+ var2 &= -2;
+ }
+
+ this.dataWatcher.updateObject(16, Byte.valueOf(var2));
+ }
+
+ /**
+ * Checks to make sure the light is not too bright where the mob is spawning
+ */
+ protected boolean isValidLightLevel() {
+ return true;
+ }
+
+ /**
+ * Returns the amount of damage a mob should deal.
+ */
+ public int getAttackStrength(Entity par1Entity) {
+ return 6;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityBoat.java b/sp-server/src/main/java/net/minecraft/src/EntityBoat.java
new file mode 100644
index 0000000..0172a1b
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityBoat.java
@@ -0,0 +1,420 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+public class EntityBoat extends Entity {
+ private boolean field_70279_a;
+ private double speedMultiplier;
+ private int boatPosRotationIncrements;
+ private double boatX;
+ private double boatY;
+ private double boatZ;
+ private double boatYaw;
+ private double boatPitch;
+
+ public EntityBoat(World par1World) {
+ super(par1World);
+ this.field_70279_a = true;
+ this.speedMultiplier = 0.07D;
+ this.preventEntitySpawning = true;
+ this.setSize(1.5F, 0.6F);
+ this.yOffset = this.height / 2.0F;
+ }
+
+ /**
+ * returns if this entity triggers Block.onEntityWalking on the blocks they walk
+ * on. used for spiders and wolves to prevent them from trampling crops
+ */
+ protected boolean canTriggerWalking() {
+ return false;
+ }
+
+ protected void entityInit() {
+ this.dataWatcher.addObject(17, Integer.valueOf(0));
+ this.dataWatcher.addObject(18, Integer.valueOf(1));
+ this.dataWatcher.addObject(19, Integer.valueOf(0));
+ }
+
+ /**
+ * Returns a boundingBox used to collide the entity with other entities and
+ * blocks. This enables the entity to be pushable on contact, like boats or
+ * minecarts.
+ */
+ public AxisAlignedBB getCollisionBox(Entity par1Entity) {
+ return par1Entity.boundingBox;
+ }
+
+ /**
+ * returns the bounding box for this entity
+ */
+ public AxisAlignedBB getBoundingBox() {
+ return this.boundingBox;
+ }
+
+ /**
+ * Returns true if this entity should push and be pushed by other entities when
+ * colliding.
+ */
+ public boolean canBePushed() {
+ return true;
+ }
+
+ public EntityBoat(World par1World, double par2, double par4, double par6) {
+ this(par1World);
+ this.setPosition(par2, par4 + (double) this.yOffset, par6);
+ this.motionX = 0.0D;
+ this.motionY = 0.0D;
+ this.motionZ = 0.0D;
+ this.prevPosX = par2;
+ this.prevPosY = par4;
+ this.prevPosZ = par6;
+ }
+
+ /**
+ * Returns the Y offset from the entity's position for any entity riding this
+ * one.
+ */
+ public double getMountedYOffset() {
+ return (double) this.height * 0.0D - 0.30000001192092896D;
+ }
+
+ /**
+ * Called when the entity is attacked.
+ */
+ public boolean attackEntityFrom(DamageSource par1DamageSource, int par2) {
+ if (this.isEntityInvulnerable()) {
+ return false;
+ } else if (!this.worldObj.isRemote && !this.isDead) {
+ this.setForwardDirection(-this.getForwardDirection());
+ this.setTimeSinceHit(10);
+ this.setDamageTaken(this.getDamageTaken() + par2 * 10);
+ this.setBeenAttacked();
+ boolean var3 = par1DamageSource.getEntity() instanceof EntityPlayer
+ && ((EntityPlayer) par1DamageSource.getEntity()).capabilities.isCreativeMode;
+
+ if (var3 || this.getDamageTaken() > 40) {
+ if (this.riddenByEntity != null) {
+ this.riddenByEntity.mountEntity(this);
+ }
+
+ if (!var3) {
+ this.dropItemWithOffset(Item.boat.itemID, 1, 0.0F);
+ }
+
+ this.setDead();
+ }
+
+ return true;
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * Returns true if other Entities should be prevented from moving through this
+ * Entity.
+ */
+ public boolean canBeCollidedWith() {
+ return !this.isDead;
+ }
+
+ /**
+ * Called to update the entity's position/logic.
+ */
+ public void onUpdate() {
+ super.onUpdate();
+
+ if (this.getTimeSinceHit() > 0) {
+ this.setTimeSinceHit(this.getTimeSinceHit() - 1);
+ }
+
+ if (this.getDamageTaken() > 0) {
+ this.setDamageTaken(this.getDamageTaken() - 1);
+ }
+
+ this.prevPosX = this.posX;
+ this.prevPosY = this.posY;
+ this.prevPosZ = this.posZ;
+ byte var1 = 5;
+ double var2 = 0.0D;
+
+ for (int var4 = 0; var4 < var1; ++var4) {
+ double var5 = this.boundingBox.minY
+ + (this.boundingBox.maxY - this.boundingBox.minY) * (double) (var4 + 0) / (double) var1 - 0.125D;
+ double var7 = this.boundingBox.minY
+ + (this.boundingBox.maxY - this.boundingBox.minY) * (double) (var4 + 1) / (double) var1 - 0.125D;
+ AxisAlignedBB var9 = AxisAlignedBB.getAABBPool().getAABB(this.boundingBox.minX, var5, this.boundingBox.minZ,
+ this.boundingBox.maxX, var7, this.boundingBox.maxZ);
+
+ if (this.worldObj.isAABBInMaterial(var9, Material.water)) {
+ var2 += 1.0D / (double) var1;
+ }
+ }
+
+ double var23 = Math.sqrt(this.motionX * this.motionX + this.motionZ * this.motionZ);
+ double var6;
+ double var8;
+
+ if (var23 > 0.26249999999999996D) {
+ var6 = Math.cos((double) this.rotationYaw * Math.PI / 180.0D);
+ var8 = Math.sin((double) this.rotationYaw * Math.PI / 180.0D);
+
+ for (int var10 = 0; (double) var10 < 1.0D + var23 * 60.0D; ++var10) {
+ double var11 = (double) (this.rand.nextFloat() * 2.0F - 1.0F);
+ double var13 = (double) (this.rand.nextInt(2) * 2 - 1) * 0.7D;
+ double var15;
+ double var17;
+
+ if (this.rand.nextBoolean()) {
+ var15 = this.posX - var6 * var11 * 0.8D + var8 * var13;
+ var17 = this.posZ - var8 * var11 * 0.8D - var6 * var13;
+ this.worldObj.spawnParticle("splash", var15, this.posY - 0.125D, var17, this.motionX, this.motionY,
+ this.motionZ);
+ } else {
+ var15 = this.posX + var6 + var8 * var11 * 0.7D;
+ var17 = this.posZ + var8 - var6 * var11 * 0.7D;
+ this.worldObj.spawnParticle("splash", var15, this.posY - 0.125D, var17, this.motionX, this.motionY,
+ this.motionZ);
+ }
+ }
+ }
+
+ double var12;
+ double var25;
+
+ if (this.worldObj.isRemote && this.field_70279_a) {
+ if (this.boatPosRotationIncrements > 0) {
+ var6 = this.posX + (this.boatX - this.posX) / (double) this.boatPosRotationIncrements;
+ var8 = this.posY + (this.boatY - this.posY) / (double) this.boatPosRotationIncrements;
+ var25 = this.posZ + (this.boatZ - this.posZ) / (double) this.boatPosRotationIncrements;
+ var12 = MathHelper.wrapAngleTo180_double(this.boatYaw - (double) this.rotationYaw);
+ this.rotationYaw = (float) ((double) this.rotationYaw
+ + var12 / (double) this.boatPosRotationIncrements);
+ this.rotationPitch = (float) ((double) this.rotationPitch
+ + (this.boatPitch - (double) this.rotationPitch) / (double) this.boatPosRotationIncrements);
+ --this.boatPosRotationIncrements;
+ this.setPosition(var6, var8, var25);
+ this.setRotation(this.rotationYaw, this.rotationPitch);
+ } else {
+ var6 = this.posX + this.motionX;
+ var8 = this.posY + this.motionY;
+ var25 = this.posZ + this.motionZ;
+ this.setPosition(var6, var8, var25);
+
+ if (this.onGround) {
+ this.motionX *= 0.5D;
+ this.motionY *= 0.5D;
+ this.motionZ *= 0.5D;
+ }
+
+ this.motionX *= 0.9900000095367432D;
+ this.motionY *= 0.949999988079071D;
+ this.motionZ *= 0.9900000095367432D;
+ }
+ } else {
+ if (var2 < 1.0D) {
+ var6 = var2 * 2.0D - 1.0D;
+ this.motionY += 0.03999999910593033D * var6;
+ } else {
+ if (this.motionY < 0.0D) {
+ this.motionY /= 2.0D;
+ }
+
+ this.motionY += 0.007000000216066837D;
+ }
+
+ if (this.riddenByEntity != null) {
+ this.motionX += this.riddenByEntity.motionX * this.speedMultiplier;
+ this.motionZ += this.riddenByEntity.motionZ * this.speedMultiplier;
+ }
+
+ var6 = Math.sqrt(this.motionX * this.motionX + this.motionZ * this.motionZ);
+
+ if (var6 > 0.35D) {
+ var8 = 0.35D / var6;
+ this.motionX *= var8;
+ this.motionZ *= var8;
+ var6 = 0.35D;
+ }
+
+ if (var6 > var23 && this.speedMultiplier < 0.35D) {
+ this.speedMultiplier += (0.35D - this.speedMultiplier) / 35.0D;
+
+ if (this.speedMultiplier > 0.35D) {
+ this.speedMultiplier = 0.35D;
+ }
+ } else {
+ this.speedMultiplier -= (this.speedMultiplier - 0.07D) / 35.0D;
+
+ if (this.speedMultiplier < 0.07D) {
+ this.speedMultiplier = 0.07D;
+ }
+ }
+
+ if (this.onGround) {
+ this.motionX *= 0.5D;
+ this.motionY *= 0.5D;
+ this.motionZ *= 0.5D;
+ }
+
+ this.moveEntity(this.motionX, this.motionY, this.motionZ);
+
+ if (this.isCollidedHorizontally && var23 > 0.2D) {
+ if (!this.worldObj.isRemote && !this.isDead) {
+ this.setDead();
+ int var24;
+
+ for (var24 = 0; var24 < 3; ++var24) {
+ this.dropItemWithOffset(Block.planks.blockID, 1, 0.0F);
+ }
+
+ for (var24 = 0; var24 < 2; ++var24) {
+ this.dropItemWithOffset(Item.stick.itemID, 1, 0.0F);
+ }
+ }
+ } else {
+ this.motionX *= 0.9900000095367432D;
+ this.motionY *= 0.949999988079071D;
+ this.motionZ *= 0.9900000095367432D;
+ }
+
+ this.rotationPitch = 0.0F;
+ var8 = (double) this.rotationYaw;
+ var25 = this.prevPosX - this.posX;
+ var12 = this.prevPosZ - this.posZ;
+
+ if (var25 * var25 + var12 * var12 > 0.001D) {
+ var8 = (double) ((float) (Math.atan2(var12, var25) * 180.0D / Math.PI));
+ }
+
+ double var14 = MathHelper.wrapAngleTo180_double(var8 - (double) this.rotationYaw);
+
+ if (var14 > 20.0D) {
+ var14 = 20.0D;
+ }
+
+ if (var14 < -20.0D) {
+ var14 = -20.0D;
+ }
+
+ this.rotationYaw = (float) ((double) this.rotationYaw + var14);
+ this.setRotation(this.rotationYaw, this.rotationPitch);
+
+ if (!this.worldObj.isRemote) {
+ List var16 = this.worldObj.getEntitiesWithinAABBExcludingEntity(this,
+ this.boundingBox.expand(0.20000000298023224D, 0.0D, 0.20000000298023224D));
+ int var26;
+
+ if (var16 != null && !var16.isEmpty()) {
+ for (var26 = 0; var26 < var16.size(); ++var26) {
+ Entity var18 = (Entity) var16.get(var26);
+
+ if (var18 != this.riddenByEntity && var18.canBePushed() && var18 instanceof EntityBoat) {
+ var18.applyEntityCollision(this);
+ }
+ }
+ }
+
+ for (var26 = 0; var26 < 4; ++var26) {
+ int var27 = MathHelper.floor_double(this.posX + ((double) (var26 % 2) - 0.5D) * 0.8D);
+ int var19 = MathHelper.floor_double(this.posZ + ((double) (var26 / 2) - 0.5D) * 0.8D);
+
+ for (int var20 = 0; var20 < 2; ++var20) {
+ int var21 = MathHelper.floor_double(this.posY) + var20;
+ int var22 = this.worldObj.getBlockId(var27, var21, var19);
+
+ if (var22 == Block.snow.blockID) {
+ this.worldObj.setBlockToAir(var27, var21, var19);
+ } else if (var22 == Block.waterlily.blockID) {
+ this.worldObj.destroyBlock(var27, var21, var19, true);
+ }
+ }
+ }
+
+ if (this.riddenByEntity != null && this.riddenByEntity.isDead) {
+ this.riddenByEntity = null;
+ }
+ }
+ }
+ }
+
+ public void updateRiderPosition() {
+ if (this.riddenByEntity != null) {
+ double var1 = Math.cos((double) this.rotationYaw * Math.PI / 180.0D) * 0.4D;
+ double var3 = Math.sin((double) this.rotationYaw * Math.PI / 180.0D) * 0.4D;
+ this.riddenByEntity.setPosition(this.posX + var1,
+ this.posY + this.getMountedYOffset() + this.riddenByEntity.getYOffset(), this.posZ + var3);
+ }
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ protected void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ protected void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ }
+
+ /**
+ * Called when a player interacts with a mob. e.g. gets milk from a cow, gets
+ * into the saddle on a pig.
+ */
+ public boolean interact(EntityPlayer par1EntityPlayer) {
+ if (this.riddenByEntity != null && this.riddenByEntity instanceof EntityPlayer
+ && this.riddenByEntity != par1EntityPlayer) {
+ return true;
+ } else {
+ if (!this.worldObj.isRemote) {
+ par1EntityPlayer.mountEntity(this);
+ }
+
+ return true;
+ }
+ }
+
+ /**
+ * Sets the damage taken from the last hit.
+ */
+ public void setDamageTaken(int par1) {
+ this.dataWatcher.updateObject(19, Integer.valueOf(par1));
+ }
+
+ /**
+ * Gets the damage taken from the last hit.
+ */
+ public int getDamageTaken() {
+ return this.dataWatcher.getWatchableObjectInt(19);
+ }
+
+ /**
+ * Sets the time to count down from since the last time entity was hit.
+ */
+ public void setTimeSinceHit(int par1) {
+ this.dataWatcher.updateObject(17, Integer.valueOf(par1));
+ }
+
+ /**
+ * Gets the time since the last hit.
+ */
+ public int getTimeSinceHit() {
+ return this.dataWatcher.getWatchableObjectInt(17);
+ }
+
+ /**
+ * Sets the forward direction of the entity.
+ */
+ public void setForwardDirection(int par1) {
+ this.dataWatcher.updateObject(18, Integer.valueOf(par1));
+ }
+
+ /**
+ * Gets the forward direction of the entity.
+ */
+ public int getForwardDirection() {
+ return this.dataWatcher.getWatchableObjectInt(18);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityBodyHelper.java b/sp-server/src/main/java/net/minecraft/src/EntityBodyHelper.java
new file mode 100644
index 0000000..cd5674d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityBodyHelper.java
@@ -0,0 +1,55 @@
+package net.minecraft.src;
+
+public class EntityBodyHelper {
+ /** Instance of EntityLiving. */
+ private EntityLiving theLiving;
+ private int field_75666_b = 0;
+ private float field_75667_c = 0.0F;
+
+ public EntityBodyHelper(EntityLiving par1EntityLiving) {
+ this.theLiving = par1EntityLiving;
+ }
+
+ public void func_75664_a() {
+ double var1 = this.theLiving.posX - this.theLiving.prevPosX;
+ double var3 = this.theLiving.posZ - this.theLiving.prevPosZ;
+
+ if (var1 * var1 + var3 * var3 > 2.500000277905201E-7D) {
+ this.theLiving.renderYawOffset = this.theLiving.rotationYaw;
+ this.theLiving.rotationYawHead = this.func_75665_a(this.theLiving.renderYawOffset,
+ this.theLiving.rotationYawHead, 75.0F);
+ this.field_75667_c = this.theLiving.rotationYawHead;
+ this.field_75666_b = 0;
+ } else {
+ float var5 = 75.0F;
+
+ if (Math.abs(this.theLiving.rotationYawHead - this.field_75667_c) > 15.0F) {
+ this.field_75666_b = 0;
+ this.field_75667_c = this.theLiving.rotationYawHead;
+ } else {
+ ++this.field_75666_b;
+
+ if (this.field_75666_b > 10) {
+ var5 = Math.max(1.0F - (float) (this.field_75666_b - 10) / 10.0F, 0.0F) * 75.0F;
+ }
+ }
+
+ this.theLiving.renderYawOffset = this.func_75665_a(this.theLiving.rotationYawHead,
+ this.theLiving.renderYawOffset, var5);
+ }
+ }
+
+ private float func_75665_a(float par1, float par2, float par3) {
+ float var4 = MathHelper.wrapAngleTo180_float(par1 - par2);
+
+ if (var4 < -par3) {
+ var4 = -par3;
+ }
+
+ if (var4 >= par3) {
+ var4 = par3;
+ }
+
+ return par1 - var4;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityCaveSpider.java b/sp-server/src/main/java/net/minecraft/src/EntityCaveSpider.java
new file mode 100644
index 0000000..bc81c07
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityCaveSpider.java
@@ -0,0 +1,43 @@
+package net.minecraft.src;
+
+public class EntityCaveSpider extends EntitySpider {
+ public EntityCaveSpider(World par1World) {
+ super(par1World);
+ this.texture = "/mob/cavespider.png";
+ this.setSize(0.7F, 0.5F);
+ }
+
+ public int getMaxHealth() {
+ return 12;
+ }
+
+ public boolean attackEntityAsMob(Entity par1Entity) {
+ if (super.attackEntityAsMob(par1Entity)) {
+ if (par1Entity instanceof EntityLiving) {
+ byte var2 = 0;
+
+ if (this.worldObj.difficultySetting > 1) {
+ if (this.worldObj.difficultySetting == 2) {
+ var2 = 7;
+ } else if (this.worldObj.difficultySetting == 3) {
+ var2 = 15;
+ }
+ }
+
+ if (var2 > 0) {
+ ((EntityLiving) par1Entity).addPotionEffect(new PotionEffect(Potion.poison.id, var2 * 20, 0));
+ }
+ }
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Initialize this creature.
+ */
+ public void initCreature() {
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityChicken.java b/sp-server/src/main/java/net/minecraft/src/EntityChicken.java
new file mode 100644
index 0000000..e5f04a3
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityChicken.java
@@ -0,0 +1,156 @@
+package net.minecraft.src;
+
+public class EntityChicken extends EntityAnimal {
+ public boolean field_70885_d = false;
+ public float field_70886_e = 0.0F;
+ public float destPos = 0.0F;
+ public float field_70884_g;
+ public float field_70888_h;
+ public float field_70889_i = 1.0F;
+
+ /** The time until the next egg is spawned. */
+ public int timeUntilNextEgg;
+
+ public EntityChicken(World par1World) {
+ super(par1World);
+ this.texture = "/mob/chicken.png";
+ this.setSize(0.3F, 0.7F);
+ this.timeUntilNextEgg = this.rand.nextInt(6000) + 6000;
+ float var2 = 0.25F;
+ this.tasks.addTask(0, new EntityAISwimming(this));
+ this.tasks.addTask(1, new EntityAIPanic(this, 0.38F));
+ this.tasks.addTask(2, new EntityAIMate(this, var2));
+ this.tasks.addTask(3, new EntityAITempt(this, 0.25F, Item.seeds.itemID, false));
+ this.tasks.addTask(4, new EntityAIFollowParent(this, 0.28F));
+ this.tasks.addTask(5, new EntityAIWander(this, var2));
+ this.tasks.addTask(6, new EntityAIWatchClosest(this, EntityPlayer.class, 6.0F));
+ this.tasks.addTask(7, new EntityAILookIdle(this));
+ }
+
+ /**
+ * Returns true if the newer Entity AI code should be run
+ */
+ public boolean isAIEnabled() {
+ return true;
+ }
+
+ public int getMaxHealth() {
+ return 4;
+ }
+
+ /**
+ * Called frequently so the entity can update its state every tick as required.
+ * For example, zombies and skeletons use this to react to sunlight and start to
+ * burn.
+ */
+ public void onLivingUpdate() {
+ super.onLivingUpdate();
+ this.field_70888_h = this.field_70886_e;
+ this.field_70884_g = this.destPos;
+ this.destPos = (float) ((double) this.destPos + (double) (this.onGround ? -1 : 4) * 0.3D);
+
+ if (this.destPos < 0.0F) {
+ this.destPos = 0.0F;
+ }
+
+ if (this.destPos > 1.0F) {
+ this.destPos = 1.0F;
+ }
+
+ if (!this.onGround && this.field_70889_i < 1.0F) {
+ this.field_70889_i = 1.0F;
+ }
+
+ this.field_70889_i = (float) ((double) this.field_70889_i * 0.9D);
+
+ if (!this.onGround && this.motionY < 0.0D) {
+ this.motionY *= 0.6D;
+ }
+
+ this.field_70886_e += this.field_70889_i * 2.0F;
+
+ if (!this.isChild() && !this.worldObj.isRemote && --this.timeUntilNextEgg <= 0) {
+ this.playSound("mob.chicken.plop", 1.0F, (this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F + 1.0F);
+ this.dropItem(Item.egg.itemID, 1);
+ this.timeUntilNextEgg = this.rand.nextInt(6000) + 6000;
+ }
+ }
+
+ /**
+ * Called when the mob is falling. Calculates and applies fall damage.
+ */
+ protected void fall(float par1) {
+ }
+
+ /**
+ * Returns the sound this mob makes while it's alive.
+ */
+ protected String getLivingSound() {
+ return "mob.chicken.say";
+ }
+
+ /**
+ * Returns the sound this mob makes when it is hurt.
+ */
+ protected String getHurtSound() {
+ return "mob.chicken.hurt";
+ }
+
+ /**
+ * Returns the sound this mob makes on death.
+ */
+ protected String getDeathSound() {
+ return "mob.chicken.hurt";
+ }
+
+ /**
+ * Plays step sound at given x, y, z for the entity
+ */
+ protected void playStepSound(int par1, int par2, int par3, int par4) {
+ this.playSound("mob.chicken.step", 0.15F, 1.0F);
+ }
+
+ /**
+ * Returns the item ID for the item the mob drops on death.
+ */
+ protected int getDropItemId() {
+ return Item.feather.itemID;
+ }
+
+ /**
+ * Drop 0-2 items of this living's type
+ */
+ protected void dropFewItems(boolean par1, int par2) {
+ int var3 = this.rand.nextInt(3) + this.rand.nextInt(1 + par2);
+
+ for (int var4 = 0; var4 < var3; ++var4) {
+ this.dropItem(Item.feather.itemID, 1);
+ }
+
+ if (this.isBurning()) {
+ this.dropItem(Item.chickenCooked.itemID, 1);
+ } else {
+ this.dropItem(Item.chickenRaw.itemID, 1);
+ }
+ }
+
+ /**
+ * This function is used when two same-species animals in 'love mode' breed to
+ * generate the new baby animal.
+ */
+ public EntityChicken spawnBabyAnimal(EntityAgeable par1EntityAgeable) {
+ return new EntityChicken(this.worldObj);
+ }
+
+ /**
+ * Checks if the parameter is an item which this animal can be fed to breed it
+ * (wheat, carrots or seeds depending on the animal type)
+ */
+ public boolean isBreedingItem(ItemStack par1ItemStack) {
+ return par1ItemStack != null && par1ItemStack.getItem() instanceof ItemSeeds;
+ }
+
+ public EntityAgeable createChild(EntityAgeable par1EntityAgeable) {
+ return this.spawnBabyAnimal(par1EntityAgeable);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityCow.java b/sp-server/src/main/java/net/minecraft/src/EntityCow.java
new file mode 100644
index 0000000..08a9973
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityCow.java
@@ -0,0 +1,126 @@
+package net.minecraft.src;
+
+public class EntityCow extends EntityAnimal {
+ public EntityCow(World par1World) {
+ super(par1World);
+ this.texture = "/mob/cow.png";
+ this.setSize(0.9F, 1.3F);
+ this.getNavigator().setAvoidsWater(true);
+ this.tasks.addTask(0, new EntityAISwimming(this));
+ this.tasks.addTask(1, new EntityAIPanic(this, 0.38F));
+ this.tasks.addTask(2, new EntityAIMate(this, 0.2F));
+ this.tasks.addTask(3, new EntityAITempt(this, 0.25F, Item.wheat.itemID, false));
+ this.tasks.addTask(4, new EntityAIFollowParent(this, 0.25F));
+ this.tasks.addTask(5, new EntityAIWander(this, 0.2F));
+ this.tasks.addTask(6, new EntityAIWatchClosest(this, EntityPlayer.class, 6.0F));
+ this.tasks.addTask(7, new EntityAILookIdle(this));
+ }
+
+ /**
+ * Returns true if the newer Entity AI code should be run
+ */
+ public boolean isAIEnabled() {
+ return true;
+ }
+
+ public int getMaxHealth() {
+ return 10;
+ }
+
+ /**
+ * Returns the sound this mob makes while it's alive.
+ */
+ protected String getLivingSound() {
+ return "mob.cow.say";
+ }
+
+ /**
+ * Returns the sound this mob makes when it is hurt.
+ */
+ protected String getHurtSound() {
+ return "mob.cow.hurt";
+ }
+
+ /**
+ * Returns the sound this mob makes on death.
+ */
+ protected String getDeathSound() {
+ return "mob.cow.hurt";
+ }
+
+ /**
+ * Plays step sound at given x, y, z for the entity
+ */
+ protected void playStepSound(int par1, int par2, int par3, int par4) {
+ this.playSound("mob.cow.step", 0.15F, 1.0F);
+ }
+
+ /**
+ * Returns the volume for the sounds this mob makes.
+ */
+ protected float getSoundVolume() {
+ return 0.4F;
+ }
+
+ /**
+ * Returns the item ID for the item the mob drops on death.
+ */
+ protected int getDropItemId() {
+ return Item.leather.itemID;
+ }
+
+ /**
+ * Drop 0-2 items of this living's type
+ */
+ protected void dropFewItems(boolean par1, int par2) {
+ int var3 = this.rand.nextInt(3) + this.rand.nextInt(1 + par2);
+ int var4;
+
+ for (var4 = 0; var4 < var3; ++var4) {
+ this.dropItem(Item.leather.itemID, 1);
+ }
+
+ var3 = this.rand.nextInt(3) + 1 + this.rand.nextInt(1 + par2);
+
+ for (var4 = 0; var4 < var3; ++var4) {
+ if (this.isBurning()) {
+ this.dropItem(Item.beefCooked.itemID, 1);
+ } else {
+ this.dropItem(Item.beefRaw.itemID, 1);
+ }
+ }
+ }
+
+ /**
+ * Called when a player interacts with a mob. e.g. gets milk from a cow, gets
+ * into the saddle on a pig.
+ */
+ public boolean interact(EntityPlayer par1EntityPlayer) {
+ ItemStack var2 = par1EntityPlayer.inventory.getCurrentItem();
+
+ if (var2 != null && var2.itemID == Item.bucketEmpty.itemID) {
+ if (--var2.stackSize <= 0) {
+ par1EntityPlayer.inventory.setInventorySlotContents(par1EntityPlayer.inventory.currentItem,
+ new ItemStack(Item.bucketMilk));
+ } else if (!par1EntityPlayer.inventory.addItemStackToInventory(new ItemStack(Item.bucketMilk))) {
+ par1EntityPlayer.dropPlayerItem(new ItemStack(Item.bucketMilk.itemID, 1, 0));
+ }
+
+ return true;
+ } else {
+ return super.interact(par1EntityPlayer);
+ }
+ }
+
+ /**
+ * This function is used when two same-species animals in 'love mode' breed to
+ * generate the new baby animal.
+ */
+ public EntityCow spawnBabyAnimal(EntityAgeable par1EntityAgeable) {
+ return new EntityCow(this.worldObj);
+ }
+
+ public EntityAgeable createChild(EntityAgeable par1EntityAgeable) {
+ return this.spawnBabyAnimal(par1EntityAgeable);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityCreature.java b/sp-server/src/main/java/net/minecraft/src/EntityCreature.java
new file mode 100644
index 0000000..4928694
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityCreature.java
@@ -0,0 +1,242 @@
+package net.minecraft.src;
+
+public abstract class EntityCreature extends EntityLiving {
+ private PathEntity pathToEntity;
+
+ /** The Entity this EntityCreature is set to attack. */
+ protected Entity entityToAttack;
+
+ /**
+ * returns true if a creature has attacked recently only used for creepers and
+ * skeletons
+ */
+ protected boolean hasAttacked = false;
+
+ /** Used to make a creature speed up and wander away when hit. */
+ protected int fleeingTick = 0;
+
+ public EntityCreature(World par1World) {
+ super(par1World);
+ }
+
+ /**
+ * Disables a mob's ability to move on its own while true.
+ */
+ protected boolean isMovementCeased() {
+ return false;
+ }
+
+ protected void updateEntityActionState() {
+ if (this.fleeingTick > 0) {
+ --this.fleeingTick;
+ }
+
+ this.hasAttacked = this.isMovementCeased();
+ float var1 = 16.0F;
+
+ if (this.entityToAttack == null) {
+ this.entityToAttack = this.findPlayerToAttack();
+
+ if (this.entityToAttack != null) {
+ this.pathToEntity = this.worldObj.getPathEntityToEntity(this, this.entityToAttack, var1, true, false,
+ false, true);
+ }
+ } else if (this.entityToAttack.isEntityAlive()) {
+ float var2 = this.entityToAttack.getDistanceToEntity(this);
+
+ if (this.canEntityBeSeen(this.entityToAttack)) {
+ this.attackEntity(this.entityToAttack, var2);
+ }
+ } else {
+ this.entityToAttack = null;
+ }
+
+ if (!this.hasAttacked && this.entityToAttack != null
+ && (this.pathToEntity == null || this.rand.nextInt(20) == 0)) {
+ this.pathToEntity = this.worldObj.getPathEntityToEntity(this, this.entityToAttack, var1, true, false, false,
+ true);
+ } else if (!this.hasAttacked && (this.pathToEntity == null && this.rand.nextInt(180) == 0
+ || this.rand.nextInt(120) == 0 || this.fleeingTick > 0) && this.entityAge < 100) {
+ this.updateWanderPath();
+ }
+
+ int var21 = MathHelper.floor_double(this.boundingBox.minY + 0.5D);
+ boolean var3 = this.isInWater();
+ boolean var4 = this.handleLavaMovement();
+ this.rotationPitch = 0.0F;
+
+ if (this.pathToEntity != null && this.rand.nextInt(100) != 0) {
+ Vec3 var5 = this.pathToEntity.getPosition(this);
+ double var6 = (double) (this.width * 2.0F);
+
+ while (var5 != null && var5.squareDistanceTo(this.posX, var5.yCoord, this.posZ) < var6 * var6) {
+ this.pathToEntity.incrementPathIndex();
+
+ if (this.pathToEntity.isFinished()) {
+ var5 = null;
+ this.pathToEntity = null;
+ } else {
+ var5 = this.pathToEntity.getPosition(this);
+ }
+ }
+
+ this.isJumping = false;
+
+ if (var5 != null) {
+ double var8 = var5.xCoord - this.posX;
+ double var10 = var5.zCoord - this.posZ;
+ double var12 = var5.yCoord - (double) var21;
+ float var14 = (float) (Math.atan2(var10, var8) * 180.0D / Math.PI) - 90.0F;
+ float var15 = MathHelper.wrapAngleTo180_float(var14 - this.rotationYaw);
+ this.moveForward = this.moveSpeed;
+
+ if (var15 > 30.0F) {
+ var15 = 30.0F;
+ }
+
+ if (var15 < -30.0F) {
+ var15 = -30.0F;
+ }
+
+ this.rotationYaw += var15;
+
+ if (this.hasAttacked && this.entityToAttack != null) {
+ double var16 = this.entityToAttack.posX - this.posX;
+ double var18 = this.entityToAttack.posZ - this.posZ;
+ float var20 = this.rotationYaw;
+ this.rotationYaw = (float) (Math.atan2(var18, var16) * 180.0D / Math.PI) - 90.0F;
+ var15 = (var20 - this.rotationYaw + 90.0F) * (float) Math.PI / 180.0F;
+ this.moveStrafing = -MathHelper.sin(var15) * this.moveForward * 1.0F;
+ this.moveForward = MathHelper.cos(var15) * this.moveForward * 1.0F;
+ }
+
+ if (var12 > 0.0D) {
+ this.isJumping = true;
+ }
+ }
+
+ if (this.entityToAttack != null) {
+ this.faceEntity(this.entityToAttack, 30.0F, 30.0F);
+ }
+
+ if (this.isCollidedHorizontally && !this.hasPath()) {
+ this.isJumping = true;
+ }
+
+ if (this.rand.nextFloat() < 0.8F && (var3 || var4)) {
+ this.isJumping = true;
+ }
+ } else {
+ super.updateEntityActionState();
+ this.pathToEntity = null;
+ }
+ }
+
+ /**
+ * Time remaining during which the Animal is sped up and flees.
+ */
+ protected void updateWanderPath() {
+ boolean var1 = false;
+ int var2 = -1;
+ int var3 = -1;
+ int var4 = -1;
+ float var5 = -99999.0F;
+
+ for (int var6 = 0; var6 < 10; ++var6) {
+ int var7 = MathHelper.floor_double(this.posX + (double) this.rand.nextInt(13) - 6.0D);
+ int var8 = MathHelper.floor_double(this.posY + (double) this.rand.nextInt(7) - 3.0D);
+ int var9 = MathHelper.floor_double(this.posZ + (double) this.rand.nextInt(13) - 6.0D);
+ float var10 = this.getBlockPathWeight(var7, var8, var9);
+
+ if (var10 > var5) {
+ var5 = var10;
+ var2 = var7;
+ var3 = var8;
+ var4 = var9;
+ var1 = true;
+ }
+ }
+
+ if (var1) {
+ this.pathToEntity = this.worldObj.getEntityPathToXYZ(this, var2, var3, var4, 10.0F, true, false, false,
+ true);
+ }
+ }
+
+ /**
+ * Basic mob attack. Default to touch of death in EntityCreature. Overridden by
+ * each mob to define their attack.
+ */
+ protected void attackEntity(Entity par1Entity, float par2) {
+ }
+
+ /**
+ * Takes a coordinate in and returns a weight to determine how likely this
+ * creature will try to path to the block. Args: x, y, z
+ */
+ public float getBlockPathWeight(int par1, int par2, int par3) {
+ return 0.0F;
+ }
+
+ /**
+ * Finds the closest player within 16 blocks to attack, or null if this Entity
+ * isn't interested in attacking (Animals, Spiders at day, peaceful PigZombies).
+ */
+ protected Entity findPlayerToAttack() {
+ return null;
+ }
+
+ /**
+ * Checks if the entity's current position is a valid location to spawn this
+ * entity.
+ */
+ public boolean getCanSpawnHere() {
+ int var1 = MathHelper.floor_double(this.posX);
+ int var2 = MathHelper.floor_double(this.boundingBox.minY);
+ int var3 = MathHelper.floor_double(this.posZ);
+ return super.getCanSpawnHere() && this.getBlockPathWeight(var1, var2, var3) >= 0.0F;
+ }
+
+ /**
+ * if the entity got a PathEntity it returns true, else false
+ */
+ public boolean hasPath() {
+ return this.pathToEntity != null;
+ }
+
+ /**
+ * sets the pathToEntity
+ */
+ public void setPathToEntity(PathEntity par1PathEntity) {
+ this.pathToEntity = par1PathEntity;
+ }
+
+ /**
+ * returns the target Entity
+ */
+ public Entity getEntityToAttack() {
+ return this.entityToAttack;
+ }
+
+ /**
+ * Sets the entity which is to be attacked.
+ */
+ public void setTarget(Entity par1Entity) {
+ this.entityToAttack = par1Entity;
+ }
+
+ /**
+ * This method returns a value to be applied directly to entity speed, this
+ * factor is less than 1 when a slowdown potion effect is applied, more than 1
+ * when a haste potion effect is applied and 2 for fleeing entities.
+ */
+ public float getSpeedModifier() {
+ float var1 = super.getSpeedModifier();
+
+ if (this.fleeingTick > 0 && !this.isAIEnabled()) {
+ var1 *= 2.0F;
+ }
+
+ return var1;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityCreeper.java b/sp-server/src/main/java/net/minecraft/src/EntityCreeper.java
new file mode 100644
index 0000000..e5a58b9
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityCreeper.java
@@ -0,0 +1,201 @@
+package net.minecraft.src;
+
+public class EntityCreeper extends EntityMob {
+ /**
+ * Time when this creeper was last in an active state (Messed up code here,
+ * probably causes creeper animation to go weird)
+ */
+ private int lastActiveTime;
+
+ /**
+ * The amount of time since the creeper was close enough to the player to ignite
+ */
+ private int timeSinceIgnited;
+ private int fuseTime = 30;
+
+ /** Explosion radius for this creeper. */
+ private int explosionRadius = 3;
+
+ public EntityCreeper(World par1World) {
+ super(par1World);
+ this.texture = "/mob/creeper.png";
+ this.tasks.addTask(1, new EntityAISwimming(this));
+ this.tasks.addTask(2, new EntityAICreeperSwell(this));
+ this.tasks.addTask(3, new EntityAIAvoidEntity(this, EntityOcelot.class, 6.0F, 0.25F, 0.3F));
+ this.tasks.addTask(4, new EntityAIAttackOnCollide(this, 0.25F, false));
+ this.tasks.addTask(5, new EntityAIWander(this, 0.2F));
+ this.tasks.addTask(6, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F));
+ this.tasks.addTask(6, new EntityAILookIdle(this));
+ this.targetTasks.addTask(1, new EntityAINearestAttackableTarget(this, EntityPlayer.class, 16.0F, 0, true));
+ this.targetTasks.addTask(2, new EntityAIHurtByTarget(this, false));
+ }
+
+ /**
+ * Returns true if the newer Entity AI code should be run
+ */
+ public boolean isAIEnabled() {
+ return true;
+ }
+
+ public int func_82143_as() {
+ return this.getAttackTarget() == null ? 3 : 3 + (this.health - 1);
+ }
+
+ /**
+ * Called when the mob is falling. Calculates and applies fall damage.
+ */
+ protected void fall(float par1) {
+ super.fall(par1);
+ this.timeSinceIgnited = (int) ((float) this.timeSinceIgnited + par1 * 1.5F);
+
+ if (this.timeSinceIgnited > this.fuseTime - 5) {
+ this.timeSinceIgnited = this.fuseTime - 5;
+ }
+ }
+
+ public int getMaxHealth() {
+ return 20;
+ }
+
+ protected void entityInit() {
+ super.entityInit();
+ this.dataWatcher.addObject(16, Byte.valueOf((byte) -1));
+ this.dataWatcher.addObject(17, Byte.valueOf((byte) 0));
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ super.writeEntityToNBT(par1NBTTagCompound);
+
+ if (this.dataWatcher.getWatchableObjectByte(17) == 1) {
+ par1NBTTagCompound.setBoolean("powered", true);
+ }
+
+ par1NBTTagCompound.setShort("Fuse", (short) this.fuseTime);
+ par1NBTTagCompound.setByte("ExplosionRadius", (byte) this.explosionRadius);
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ super.readEntityFromNBT(par1NBTTagCompound);
+ this.dataWatcher.updateObject(17, Byte.valueOf((byte) (par1NBTTagCompound.getBoolean("powered") ? 1 : 0)));
+
+ if (par1NBTTagCompound.hasKey("Fuse")) {
+ this.fuseTime = par1NBTTagCompound.getShort("Fuse");
+ }
+
+ if (par1NBTTagCompound.hasKey("ExplosionRadius")) {
+ this.explosionRadius = par1NBTTagCompound.getByte("ExplosionRadius");
+ }
+ }
+
+ /**
+ * Called to update the entity's position/logic.
+ */
+ public void onUpdate() {
+ if (this.isEntityAlive()) {
+ this.lastActiveTime = this.timeSinceIgnited;
+ int var1 = this.getCreeperState();
+
+ if (var1 > 0 && this.timeSinceIgnited == 0) {
+ this.playSound("random.fuse", 1.0F, 0.5F);
+ }
+
+ this.timeSinceIgnited += var1;
+
+ if (this.timeSinceIgnited < 0) {
+ this.timeSinceIgnited = 0;
+ }
+
+ if (this.timeSinceIgnited >= this.fuseTime) {
+ this.timeSinceIgnited = this.fuseTime;
+
+ if (!this.worldObj.isRemote) {
+ boolean var2 = this.worldObj.getGameRules().getGameRuleBooleanValue("mobGriefing");
+
+ if (this.getPowered()) {
+ this.worldObj.createExplosion(this, this.posX, this.posY, this.posZ,
+ (float) (this.explosionRadius * 2), var2);
+ } else {
+ this.worldObj.createExplosion(this, this.posX, this.posY, this.posZ,
+ (float) this.explosionRadius, var2);
+ }
+
+ this.setDead();
+ }
+ }
+ }
+
+ super.onUpdate();
+ }
+
+ /**
+ * Returns the sound this mob makes when it is hurt.
+ */
+ protected String getHurtSound() {
+ return "mob.creeper.say";
+ }
+
+ /**
+ * Returns the sound this mob makes on death.
+ */
+ protected String getDeathSound() {
+ return "mob.creeper.death";
+ }
+
+ /**
+ * Called when the mob's health reaches 0.
+ */
+ public void onDeath(DamageSource par1DamageSource) {
+ super.onDeath(par1DamageSource);
+
+ if (par1DamageSource.getEntity() instanceof EntitySkeleton) {
+ int var2 = Item.record13.itemID + this.rand.nextInt(Item.recordWait.itemID - Item.record13.itemID + 1);
+ this.dropItem(var2, 1);
+ }
+ }
+
+ public boolean attackEntityAsMob(Entity par1Entity) {
+ return true;
+ }
+
+ /**
+ * Returns true if the creeper is powered by a lightning bolt.
+ */
+ public boolean getPowered() {
+ return this.dataWatcher.getWatchableObjectByte(17) == 1;
+ }
+
+ /**
+ * Returns the item ID for the item the mob drops on death.
+ */
+ protected int getDropItemId() {
+ return Item.gunpowder.itemID;
+ }
+
+ /**
+ * Returns the current state of creeper, -1 is idle, 1 is 'in fuse'
+ */
+ public int getCreeperState() {
+ return this.dataWatcher.getWatchableObjectByte(16);
+ }
+
+ /**
+ * Sets the state of creeper, -1 to idle and 1 to be 'in fuse'
+ */
+ public void setCreeperState(int par1) {
+ this.dataWatcher.updateObject(16, Byte.valueOf((byte) par1));
+ }
+
+ /**
+ * Called when a lightning bolt hits the entity.
+ */
+ public void onStruckByLightning(EntityLightningBolt par1EntityLightningBolt) {
+ super.onStruckByLightning(par1EntityLightningBolt);
+ this.dataWatcher.updateObject(17, Byte.valueOf((byte) 1));
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityDamageSource.java b/sp-server/src/main/java/net/minecraft/src/EntityDamageSource.java
new file mode 100644
index 0000000..91f6a30
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityDamageSource.java
@@ -0,0 +1,41 @@
+package net.minecraft.src;
+
+public class EntityDamageSource extends DamageSource {
+ protected Entity damageSourceEntity;
+
+ public EntityDamageSource(String par1Str, Entity par2Entity) {
+ super(par1Str);
+ this.damageSourceEntity = par2Entity;
+ }
+
+ public Entity getEntity() {
+ return this.damageSourceEntity;
+ }
+
+ /**
+ * Returns the message to be displayed on player death.
+ */
+ public String getDeathMessage(EntityLiving par1EntityLiving) {
+ ItemStack var2 = this.damageSourceEntity instanceof EntityLiving
+ ? ((EntityLiving) this.damageSourceEntity).getHeldItem()
+ : null;
+ String var3 = "death.attack." + this.damageType;
+ String var4 = var3 + ".item";
+ return var2 != null && var2.hasDisplayName() && StatCollector.func_94522_b(var4)
+ ? StatCollector.translateToLocalFormatted(var4,
+ new Object[] { par1EntityLiving.getTranslatedEntityName(),
+ this.damageSourceEntity.getTranslatedEntityName(), var2.getDisplayName() })
+ : StatCollector.translateToLocalFormatted(var3,
+ new Object[] { par1EntityLiving.getTranslatedEntityName(),
+ this.damageSourceEntity.getTranslatedEntityName() });
+ }
+
+ /**
+ * Return whether this damage source will have its damage amount scaled based on
+ * the current difficulty.
+ */
+ public boolean isDifficultyScaled() {
+ return this.damageSourceEntity != null && this.damageSourceEntity instanceof EntityLiving
+ && !(this.damageSourceEntity instanceof EntityPlayer);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityDamageSourceIndirect.java b/sp-server/src/main/java/net/minecraft/src/EntityDamageSourceIndirect.java
new file mode 100644
index 0000000..8a57f4b
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityDamageSourceIndirect.java
@@ -0,0 +1,36 @@
+package net.minecraft.src;
+
+public class EntityDamageSourceIndirect extends EntityDamageSource {
+ private Entity indirectEntity;
+
+ public EntityDamageSourceIndirect(String par1Str, Entity par2Entity, Entity par3Entity) {
+ super(par1Str, par2Entity);
+ this.indirectEntity = par3Entity;
+ }
+
+ public Entity getSourceOfDamage() {
+ return this.damageSourceEntity;
+ }
+
+ public Entity getEntity() {
+ return this.indirectEntity;
+ }
+
+ /**
+ * Returns the message to be displayed on player death.
+ */
+ public String getDeathMessage(EntityLiving par1EntityLiving) {
+ String var2 = this.indirectEntity == null ? this.damageSourceEntity.getTranslatedEntityName()
+ : this.indirectEntity.getTranslatedEntityName();
+ ItemStack var3 = this.indirectEntity instanceof EntityLiving
+ ? ((EntityLiving) this.indirectEntity).getHeldItem()
+ : null;
+ String var4 = "death.attack." + this.damageType;
+ String var5 = var4 + ".item";
+ return var3 != null && var3.hasDisplayName() && StatCollector.func_94522_b(var5)
+ ? StatCollector.translateToLocalFormatted(var5,
+ new Object[] { par1EntityLiving.getTranslatedEntityName(), var2, var3.getDisplayName() })
+ : StatCollector.translateToLocalFormatted(var4,
+ new Object[] { par1EntityLiving.getTranslatedEntityName(), var2 });
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityDragon.java b/sp-server/src/main/java/net/minecraft/src/EntityDragon.java
new file mode 100644
index 0000000..9e1d28e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityDragon.java
@@ -0,0 +1,696 @@
+package net.minecraft.src;
+
+import java.util.Iterator;
+import java.util.List;
+
+public class EntityDragon extends EntityLiving implements IEntityMultiPart {
+ public double targetX;
+ public double targetY;
+ public double targetZ;
+
+ /**
+ * Ring buffer array for the last 64 Y-positions and yaw rotations. Used to
+ * calculate offsets for the animations.
+ */
+ public double[][] ringBuffer = new double[64][3];
+
+ /**
+ * Index into the ring buffer. Incremented once per tick and restarts at 0 once
+ * it reaches the end of the buffer.
+ */
+ public int ringBufferIndex = -1;
+
+ /** An array containing all body parts of this dragon */
+ public EntityDragonPart[] dragonPartArray;
+
+ /** The head bounding box of a dragon */
+ public EntityDragonPart dragonPartHead;
+
+ /** The body bounding box of a dragon */
+ public EntityDragonPart dragonPartBody;
+ public EntityDragonPart dragonPartTail1;
+ public EntityDragonPart dragonPartTail2;
+ public EntityDragonPart dragonPartTail3;
+ public EntityDragonPart dragonPartWing1;
+ public EntityDragonPart dragonPartWing2;
+
+ /** Animation time at previous tick. */
+ public float prevAnimTime = 0.0F;
+
+ /**
+ * Animation time, used to control the speed of the animation cycles (wings
+ * flapping, jaw opening, etc.)
+ */
+ public float animTime = 0.0F;
+
+ /** Force selecting a new flight target at next tick if set to true. */
+ public boolean forceNewTarget = false;
+
+ /**
+ * Activated if the dragon is flying though obsidian, white stone or bedrock.
+ * Slows movement and animation speed.
+ */
+ public boolean slowed = false;
+ private Entity target;
+ public int deathTicks = 0;
+
+ /** The current endercrystal that is healing this dragon */
+ public EntityEnderCrystal healingEnderCrystal = null;
+
+ public EntityDragon(World par1World) {
+ super(par1World);
+ this.dragonPartArray = new EntityDragonPart[] {
+ this.dragonPartHead = new EntityDragonPart(this, "head", 6.0F, 6.0F),
+ this.dragonPartBody = new EntityDragonPart(this, "body", 8.0F, 8.0F),
+ this.dragonPartTail1 = new EntityDragonPart(this, "tail", 4.0F, 4.0F),
+ this.dragonPartTail2 = new EntityDragonPart(this, "tail", 4.0F, 4.0F),
+ this.dragonPartTail3 = new EntityDragonPart(this, "tail", 4.0F, 4.0F),
+ this.dragonPartWing1 = new EntityDragonPart(this, "wing", 4.0F, 4.0F),
+ this.dragonPartWing2 = new EntityDragonPart(this, "wing", 4.0F, 4.0F) };
+ this.setEntityHealth(this.getMaxHealth());
+ this.texture = "/mob/enderdragon/ender.png";
+ this.setSize(16.0F, 8.0F);
+ this.noClip = true;
+ this.isImmuneToFire = true;
+ this.targetY = 100.0D;
+ this.ignoreFrustumCheck = true;
+ }
+
+ public int getMaxHealth() {
+ return 200;
+ }
+
+ protected void entityInit() {
+ super.entityInit();
+ this.dataWatcher.addObject(16, Integer.valueOf(this.getMaxHealth()));
+ }
+
+ /**
+ * Returns a double[3] array with movement offsets, used to calculate trailing
+ * tail/neck positions. [0] = yaw offset, [1] = y offset, [2] = unused, always
+ * 0. Parameters: buffer index offset, partial ticks.
+ */
+ public double[] getMovementOffsets(int par1, float par2) {
+ if (this.health <= 0) {
+ par2 = 0.0F;
+ }
+
+ par2 = 1.0F - par2;
+ int var3 = this.ringBufferIndex - par1 * 1 & 63;
+ int var4 = this.ringBufferIndex - par1 * 1 - 1 & 63;
+ double[] var5 = new double[3];
+ double var6 = this.ringBuffer[var3][0];
+ double var8 = MathHelper.wrapAngleTo180_double(this.ringBuffer[var4][0] - var6);
+ var5[0] = var6 + var8 * (double) par2;
+ var6 = this.ringBuffer[var3][1];
+ var8 = this.ringBuffer[var4][1] - var6;
+ var5[1] = var6 + var8 * (double) par2;
+ var5[2] = this.ringBuffer[var3][2] + (this.ringBuffer[var4][2] - this.ringBuffer[var3][2]) * (double) par2;
+ return var5;
+ }
+
+ /**
+ * Called frequently so the entity can update its state every tick as required.
+ * For example, zombies and skeletons use this to react to sunlight and start to
+ * burn.
+ */
+ public void onLivingUpdate() {
+ float var1;
+ float var2;
+
+ if (!this.worldObj.isRemote) {
+ this.dataWatcher.updateObject(16, Integer.valueOf(this.health));
+ } else {
+ var1 = MathHelper.cos(this.animTime * (float) Math.PI * 2.0F);
+ var2 = MathHelper.cos(this.prevAnimTime * (float) Math.PI * 2.0F);
+
+ if (var2 <= -0.3F && var1 >= -0.3F) {
+ this.worldObj.playSound(this.posX, this.posY, this.posZ, "mob.enderdragon.wings", 5.0F,
+ 0.8F + this.rand.nextFloat() * 0.3F, false);
+ }
+ }
+
+ this.prevAnimTime = this.animTime;
+ float var3;
+
+ if (this.health <= 0) {
+ var1 = (this.rand.nextFloat() - 0.5F) * 8.0F;
+ var2 = (this.rand.nextFloat() - 0.5F) * 4.0F;
+ var3 = (this.rand.nextFloat() - 0.5F) * 8.0F;
+ this.worldObj.spawnParticle("largeexplode", this.posX + (double) var1, this.posY + 2.0D + (double) var2,
+ this.posZ + (double) var3, 0.0D, 0.0D, 0.0D);
+ } else {
+ this.updateDragonEnderCrystal();
+ var1 = 0.2F / (MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ) * 10.0F
+ + 1.0F);
+ var1 *= (float) Math.pow(2.0D, this.motionY);
+
+ if (this.slowed) {
+ this.animTime += var1 * 0.5F;
+ } else {
+ this.animTime += var1;
+ }
+
+ this.rotationYaw = MathHelper.wrapAngleTo180_float(this.rotationYaw);
+
+ if (this.ringBufferIndex < 0) {
+ for (int var25 = 0; var25 < this.ringBuffer.length; ++var25) {
+ this.ringBuffer[var25][0] = (double) this.rotationYaw;
+ this.ringBuffer[var25][1] = this.posY;
+ }
+ }
+
+ if (++this.ringBufferIndex == this.ringBuffer.length) {
+ this.ringBufferIndex = 0;
+ }
+
+ this.ringBuffer[this.ringBufferIndex][0] = (double) this.rotationYaw;
+ this.ringBuffer[this.ringBufferIndex][1] = this.posY;
+ double var4;
+ double var6;
+ double var8;
+ double var26;
+ float var31;
+
+ if (this.worldObj.isRemote) {
+ if (this.newPosRotationIncrements > 0) {
+ var26 = this.posX + (this.newPosX - this.posX) / (double) this.newPosRotationIncrements;
+ var4 = this.posY + (this.newPosY - this.posY) / (double) this.newPosRotationIncrements;
+ var6 = this.posZ + (this.newPosZ - this.posZ) / (double) this.newPosRotationIncrements;
+ var8 = MathHelper.wrapAngleTo180_double(this.newRotationYaw - (double) this.rotationYaw);
+ this.rotationYaw = (float) ((double) this.rotationYaw
+ + var8 / (double) this.newPosRotationIncrements);
+ this.rotationPitch = (float) ((double) this.rotationPitch
+ + (this.newRotationPitch - (double) this.rotationPitch)
+ / (double) this.newPosRotationIncrements);
+ --this.newPosRotationIncrements;
+ this.setPosition(var26, var4, var6);
+ this.setRotation(this.rotationYaw, this.rotationPitch);
+ }
+ } else {
+ var26 = this.targetX - this.posX;
+ var4 = this.targetY - this.posY;
+ var6 = this.targetZ - this.posZ;
+ var8 = var26 * var26 + var4 * var4 + var6 * var6;
+
+ if (this.target != null) {
+ this.targetX = this.target.posX;
+ this.targetZ = this.target.posZ;
+ double var10 = this.targetX - this.posX;
+ double var12 = this.targetZ - this.posZ;
+ double var14 = Math.sqrt(var10 * var10 + var12 * var12);
+ double var16 = 0.4000000059604645D + var14 / 80.0D - 1.0D;
+
+ if (var16 > 10.0D) {
+ var16 = 10.0D;
+ }
+
+ this.targetY = this.target.boundingBox.minY + var16;
+ } else {
+ this.targetX += this.rand.nextGaussian() * 2.0D;
+ this.targetZ += this.rand.nextGaussian() * 2.0D;
+ }
+
+ if (this.forceNewTarget || var8 < 100.0D || var8 > 22500.0D || this.isCollidedHorizontally
+ || this.isCollidedVertically) {
+ this.setNewTarget();
+ }
+
+ var4 /= (double) MathHelper.sqrt_double(var26 * var26 + var6 * var6);
+ var31 = 0.6F;
+
+ if (var4 < (double) (-var31)) {
+ var4 = (double) (-var31);
+ }
+
+ if (var4 > (double) var31) {
+ var4 = (double) var31;
+ }
+
+ this.motionY += var4 * 0.10000000149011612D;
+ this.rotationYaw = MathHelper.wrapAngleTo180_float(this.rotationYaw);
+ double var11 = 180.0D - Math.atan2(var26, var6) * 180.0D / Math.PI;
+ double var13 = MathHelper.wrapAngleTo180_double(var11 - (double) this.rotationYaw);
+
+ if (var13 > 50.0D) {
+ var13 = 50.0D;
+ }
+
+ if (var13 < -50.0D) {
+ var13 = -50.0D;
+ }
+
+ Vec3 var15 = this.worldObj.getWorldVec3Pool()
+ .getVecFromPool(this.targetX - this.posX, this.targetY - this.posY, this.targetZ - this.posZ)
+ .normalize();
+ Vec3 var39 = this.worldObj.getWorldVec3Pool()
+ .getVecFromPool((double) MathHelper.sin(this.rotationYaw * (float) Math.PI / 180.0F),
+ this.motionY, (double) (-MathHelper.cos(this.rotationYaw * (float) Math.PI / 180.0F)))
+ .normalize();
+ float var17 = (float) (var39.dotProduct(var15) + 0.5D) / 1.5F;
+
+ if (var17 < 0.0F) {
+ var17 = 0.0F;
+ }
+
+ this.randomYawVelocity *= 0.8F;
+ float var18 = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ) * 1.0F
+ + 1.0F;
+ double var19 = Math.sqrt(this.motionX * this.motionX + this.motionZ * this.motionZ) * 1.0D + 1.0D;
+
+ if (var19 > 40.0D) {
+ var19 = 40.0D;
+ }
+
+ this.randomYawVelocity = (float) ((double) this.randomYawVelocity
+ + var13 * (0.699999988079071D / var19 / (double) var18));
+ this.rotationYaw += this.randomYawVelocity * 0.1F;
+ float var21 = (float) (2.0D / (var19 + 1.0D));
+ float var22 = 0.06F;
+ this.moveFlying(0.0F, -1.0F, var22 * (var17 * var21 + (1.0F - var21)));
+
+ if (this.slowed) {
+ this.moveEntity(this.motionX * 0.800000011920929D, this.motionY * 0.800000011920929D,
+ this.motionZ * 0.800000011920929D);
+ } else {
+ this.moveEntity(this.motionX, this.motionY, this.motionZ);
+ }
+
+ Vec3 var23 = this.worldObj.getWorldVec3Pool().getVecFromPool(this.motionX, this.motionY, this.motionZ)
+ .normalize();
+ float var24 = (float) (var23.dotProduct(var39) + 1.0D) / 2.0F;
+ var24 = 0.8F + 0.15F * var24;
+ this.motionX *= (double) var24;
+ this.motionZ *= (double) var24;
+ this.motionY *= 0.9100000262260437D;
+ }
+
+ this.renderYawOffset = this.rotationYaw;
+ this.dragonPartHead.width = this.dragonPartHead.height = 3.0F;
+ this.dragonPartTail1.width = this.dragonPartTail1.height = 2.0F;
+ this.dragonPartTail2.width = this.dragonPartTail2.height = 2.0F;
+ this.dragonPartTail3.width = this.dragonPartTail3.height = 2.0F;
+ this.dragonPartBody.height = 3.0F;
+ this.dragonPartBody.width = 5.0F;
+ this.dragonPartWing1.height = 2.0F;
+ this.dragonPartWing1.width = 4.0F;
+ this.dragonPartWing2.height = 3.0F;
+ this.dragonPartWing2.width = 4.0F;
+ var2 = (float) (this.getMovementOffsets(5, 1.0F)[1] - this.getMovementOffsets(10, 1.0F)[1]) * 10.0F / 180.0F
+ * (float) Math.PI;
+ var3 = MathHelper.cos(var2);
+ float var27 = -MathHelper.sin(var2);
+ float var5 = this.rotationYaw * (float) Math.PI / 180.0F;
+ float var28 = MathHelper.sin(var5);
+ float var7 = MathHelper.cos(var5);
+ this.dragonPartBody.onUpdate();
+ this.dragonPartBody.setLocationAndAngles(this.posX + (double) (var28 * 0.5F), this.posY,
+ this.posZ - (double) (var7 * 0.5F), 0.0F, 0.0F);
+ this.dragonPartWing1.onUpdate();
+ this.dragonPartWing1.setLocationAndAngles(this.posX + (double) (var7 * 4.5F), this.posY + 2.0D,
+ this.posZ + (double) (var28 * 4.5F), 0.0F, 0.0F);
+ this.dragonPartWing2.onUpdate();
+ this.dragonPartWing2.setLocationAndAngles(this.posX - (double) (var7 * 4.5F), this.posY + 2.0D,
+ this.posZ - (double) (var28 * 4.5F), 0.0F, 0.0F);
+
+ if (!this.worldObj.isRemote && this.hurtTime == 0) {
+ this.collideWithEntities(this.worldObj.getEntitiesWithinAABBExcludingEntity(this,
+ this.dragonPartWing1.boundingBox.expand(4.0D, 2.0D, 4.0D).offset(0.0D, -2.0D, 0.0D)));
+ this.collideWithEntities(this.worldObj.getEntitiesWithinAABBExcludingEntity(this,
+ this.dragonPartWing2.boundingBox.expand(4.0D, 2.0D, 4.0D).offset(0.0D, -2.0D, 0.0D)));
+ this.attackEntitiesInList(this.worldObj.getEntitiesWithinAABBExcludingEntity(this,
+ this.dragonPartHead.boundingBox.expand(1.0D, 1.0D, 1.0D)));
+ }
+
+ double[] var29 = this.getMovementOffsets(5, 1.0F);
+ double[] var9 = this.getMovementOffsets(0, 1.0F);
+ var31 = MathHelper.sin(this.rotationYaw * (float) Math.PI / 180.0F - this.randomYawVelocity * 0.01F);
+ float var33 = MathHelper.cos(this.rotationYaw * (float) Math.PI / 180.0F - this.randomYawVelocity * 0.01F);
+ this.dragonPartHead.onUpdate();
+ this.dragonPartHead.setLocationAndAngles(this.posX + (double) (var31 * 5.5F * var3),
+ this.posY + (var9[1] - var29[1]) * 1.0D + (double) (var27 * 5.5F),
+ this.posZ - (double) (var33 * 5.5F * var3), 0.0F, 0.0F);
+
+ for (int var30 = 0; var30 < 3; ++var30) {
+ EntityDragonPart var32 = null;
+
+ if (var30 == 0) {
+ var32 = this.dragonPartTail1;
+ }
+
+ if (var30 == 1) {
+ var32 = this.dragonPartTail2;
+ }
+
+ if (var30 == 2) {
+ var32 = this.dragonPartTail3;
+ }
+
+ double[] var34 = this.getMovementOffsets(12 + var30 * 2, 1.0F);
+ float var35 = this.rotationYaw * (float) Math.PI / 180.0F
+ + this.simplifyAngle(var34[0] - var29[0]) * (float) Math.PI / 180.0F * 1.0F;
+ float var37 = MathHelper.sin(var35);
+ float var36 = MathHelper.cos(var35);
+ float var38 = 1.5F;
+ float var40 = (float) (var30 + 1) * 2.0F;
+ var32.onUpdate();
+ var32.setLocationAndAngles(this.posX - (double) ((var28 * var38 + var37 * var40) * var3),
+ this.posY + (var34[1] - var29[1]) * 1.0D - (double) ((var40 + var38) * var27) + 1.5D,
+ this.posZ + (double) ((var7 * var38 + var36 * var40) * var3), 0.0F, 0.0F);
+ }
+
+ if (!this.worldObj.isRemote) {
+ this.slowed = this.destroyBlocksInAABB(this.dragonPartHead.boundingBox)
+ | this.destroyBlocksInAABB(this.dragonPartBody.boundingBox);
+ }
+ }
+ }
+
+ /**
+ * Updates the state of the enderdragon's current endercrystal.
+ */
+ private void updateDragonEnderCrystal() {
+ if (this.healingEnderCrystal != null) {
+ if (this.healingEnderCrystal.isDead) {
+ if (!this.worldObj.isRemote) {
+ this.attackEntityFromPart(this.dragonPartHead, DamageSource.setExplosionSource((Explosion) null),
+ 10);
+ }
+
+ this.healingEnderCrystal = null;
+ } else if (this.ticksExisted % 10 == 0 && this.getHealth() < this.getMaxHealth()) {
+ this.setEntityHealth(this.getHealth() + 1);
+ }
+ }
+
+ if (this.rand.nextInt(10) == 0) {
+ float var1 = 32.0F;
+ List var2 = this.worldObj.getEntitiesWithinAABB(EntityEnderCrystal.class,
+ this.boundingBox.expand((double) var1, (double) var1, (double) var1));
+ EntityEnderCrystal var3 = null;
+ double var4 = Double.MAX_VALUE;
+ Iterator var6 = var2.iterator();
+
+ while (var6.hasNext()) {
+ EntityEnderCrystal var7 = (EntityEnderCrystal) var6.next();
+ double var8 = var7.getDistanceSqToEntity(this);
+
+ if (var8 < var4) {
+ var4 = var8;
+ var3 = var7;
+ }
+ }
+
+ this.healingEnderCrystal = var3;
+ }
+ }
+
+ /**
+ * Pushes all entities inside the list away from the enderdragon.
+ */
+ private void collideWithEntities(List par1List) {
+ double var2 = (this.dragonPartBody.boundingBox.minX + this.dragonPartBody.boundingBox.maxX) / 2.0D;
+ double var4 = (this.dragonPartBody.boundingBox.minZ + this.dragonPartBody.boundingBox.maxZ) / 2.0D;
+ Iterator var6 = par1List.iterator();
+
+ while (var6.hasNext()) {
+ Entity var7 = (Entity) var6.next();
+
+ if (var7 instanceof EntityLiving) {
+ double var8 = var7.posX - var2;
+ double var10 = var7.posZ - var4;
+ double var12 = var8 * var8 + var10 * var10;
+ var7.addVelocity(var8 / var12 * 4.0D, 0.20000000298023224D, var10 / var12 * 4.0D);
+ }
+ }
+ }
+
+ /**
+ * Attacks all entities inside this list, dealing 5 hearts of damage.
+ */
+ private void attackEntitiesInList(List par1List) {
+ for (int var2 = 0; var2 < par1List.size(); ++var2) {
+ Entity var3 = (Entity) par1List.get(var2);
+
+ if (var3 instanceof EntityLiving) {
+ var3.attackEntityFrom(DamageSource.causeMobDamage(this), 10);
+ }
+ }
+ }
+
+ /**
+ * Sets a new target for the flight AI. It can be a random coordinate or a
+ * nearby player.
+ */
+ private void setNewTarget() {
+ this.forceNewTarget = false;
+
+ if (this.rand.nextInt(2) == 0 && !this.worldObj.playerEntities.isEmpty()) {
+ this.target = (Entity) this.worldObj.playerEntities
+ .get(this.rand.nextInt(this.worldObj.playerEntities.size()));
+ } else {
+ boolean var1 = false;
+
+ do {
+ this.targetX = 0.0D;
+ this.targetY = (double) (70.0F + this.rand.nextFloat() * 50.0F);
+ this.targetZ = 0.0D;
+ this.targetX += (double) (this.rand.nextFloat() * 120.0F - 60.0F);
+ this.targetZ += (double) (this.rand.nextFloat() * 120.0F - 60.0F);
+ double var2 = this.posX - this.targetX;
+ double var4 = this.posY - this.targetY;
+ double var6 = this.posZ - this.targetZ;
+ var1 = var2 * var2 + var4 * var4 + var6 * var6 > 100.0D;
+ } while (!var1);
+
+ this.target = null;
+ }
+ }
+
+ /**
+ * Simplifies the value of a number by adding/subtracting 180 to the point that
+ * the number is between -180 and 180.
+ */
+ private float simplifyAngle(double par1) {
+ return (float) MathHelper.wrapAngleTo180_double(par1);
+ }
+
+ /**
+ * Destroys all blocks that aren't associated with 'The End' inside the given
+ * bounding box.
+ */
+ private boolean destroyBlocksInAABB(AxisAlignedBB par1AxisAlignedBB) {
+ int var2 = MathHelper.floor_double(par1AxisAlignedBB.minX);
+ int var3 = MathHelper.floor_double(par1AxisAlignedBB.minY);
+ int var4 = MathHelper.floor_double(par1AxisAlignedBB.minZ);
+ int var5 = MathHelper.floor_double(par1AxisAlignedBB.maxX);
+ int var6 = MathHelper.floor_double(par1AxisAlignedBB.maxY);
+ int var7 = MathHelper.floor_double(par1AxisAlignedBB.maxZ);
+ boolean var8 = false;
+ boolean var9 = false;
+
+ for (int var10 = var2; var10 <= var5; ++var10) {
+ for (int var11 = var3; var11 <= var6; ++var11) {
+ for (int var12 = var4; var12 <= var7; ++var12) {
+ int var13 = this.worldObj.getBlockId(var10, var11, var12);
+
+ if (var13 != 0) {
+ if (var13 != Block.obsidian.blockID && var13 != Block.whiteStone.blockID
+ && var13 != Block.bedrock.blockID
+ && this.worldObj.getGameRules().getGameRuleBooleanValue("mobGriefing")) {
+ var9 = this.worldObj.setBlockToAir(var10, var11, var12) || var9;
+ } else {
+ var8 = true;
+ }
+ }
+ }
+ }
+ }
+
+ if (var9) {
+ double var16 = par1AxisAlignedBB.minX
+ + (par1AxisAlignedBB.maxX - par1AxisAlignedBB.minX) * (double) this.rand.nextFloat();
+ double var17 = par1AxisAlignedBB.minY
+ + (par1AxisAlignedBB.maxY - par1AxisAlignedBB.minY) * (double) this.rand.nextFloat();
+ double var14 = par1AxisAlignedBB.minZ
+ + (par1AxisAlignedBB.maxZ - par1AxisAlignedBB.minZ) * (double) this.rand.nextFloat();
+ this.worldObj.spawnParticle("largeexplode", var16, var17, var14, 0.0D, 0.0D, 0.0D);
+ }
+
+ return var8;
+ }
+
+ public boolean attackEntityFromPart(EntityDragonPart par1EntityDragonPart, DamageSource par2DamageSource,
+ int par3) {
+ if (par1EntityDragonPart != this.dragonPartHead) {
+ par3 = par3 / 4 + 1;
+ }
+
+ float var4 = this.rotationYaw * (float) Math.PI / 180.0F;
+ float var5 = MathHelper.sin(var4);
+ float var6 = MathHelper.cos(var4);
+ this.targetX = this.posX + (double) (var5 * 5.0F) + (double) ((this.rand.nextFloat() - 0.5F) * 2.0F);
+ this.targetY = this.posY + (double) (this.rand.nextFloat() * 3.0F) + 1.0D;
+ this.targetZ = this.posZ - (double) (var6 * 5.0F) + (double) ((this.rand.nextFloat() - 0.5F) * 2.0F);
+ this.target = null;
+
+ if (par2DamageSource.getEntity() instanceof EntityPlayer || par2DamageSource.isExplosion()) {
+ this.func_82195_e(par2DamageSource, par3);
+ }
+
+ return true;
+ }
+
+ /**
+ * Called when the entity is attacked.
+ */
+ public boolean attackEntityFrom(DamageSource par1DamageSource, int par2) {
+ return false;
+ }
+
+ protected boolean func_82195_e(DamageSource par1DamageSource, int par2) {
+ return super.attackEntityFrom(par1DamageSource, par2);
+ }
+
+ /**
+ * handles entity death timer, experience orb and particle creation
+ */
+ protected void onDeathUpdate() {
+ ++this.deathTicks;
+
+ if (this.deathTicks >= 180 && this.deathTicks <= 200) {
+ float var1 = (this.rand.nextFloat() - 0.5F) * 8.0F;
+ float var2 = (this.rand.nextFloat() - 0.5F) * 4.0F;
+ float var3 = (this.rand.nextFloat() - 0.5F) * 8.0F;
+ this.worldObj.spawnParticle("hugeexplosion", this.posX + (double) var1, this.posY + 2.0D + (double) var2,
+ this.posZ + (double) var3, 0.0D, 0.0D, 0.0D);
+ }
+
+ int var4;
+ int var5;
+
+ if (!this.worldObj.isRemote) {
+ if (this.deathTicks > 150 && this.deathTicks % 5 == 0) {
+ var4 = 1000;
+
+ while (var4 > 0) {
+ var5 = EntityXPOrb.getXPSplit(var4);
+ var4 -= var5;
+ this.worldObj
+ .spawnEntityInWorld(new EntityXPOrb(this.worldObj, this.posX, this.posY, this.posZ, var5));
+ }
+ }
+
+ if (this.deathTicks == 1) {
+ this.worldObj.func_82739_e(1018, (int) this.posX, (int) this.posY, (int) this.posZ, 0);
+ }
+ }
+
+ this.moveEntity(0.0D, 0.10000000149011612D, 0.0D);
+ this.renderYawOffset = this.rotationYaw += 20.0F;
+
+ if (this.deathTicks == 200 && !this.worldObj.isRemote) {
+ var4 = 2000;
+
+ while (var4 > 0) {
+ var5 = EntityXPOrb.getXPSplit(var4);
+ var4 -= var5;
+ this.worldObj.spawnEntityInWorld(new EntityXPOrb(this.worldObj, this.posX, this.posY, this.posZ, var5));
+ }
+
+ this.createEnderPortal(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posZ));
+ this.setDead();
+ }
+ }
+
+ /**
+ * Creates the ender portal leading back to the normal world after defeating the
+ * enderdragon.
+ */
+ private void createEnderPortal(int par1, int par2) {
+ byte var3 = 64;
+ BlockEndPortal.bossDefeated = true;
+ byte var4 = 4;
+
+ for (int var5 = var3 - 1; var5 <= var3 + 32; ++var5) {
+ for (int var6 = par1 - var4; var6 <= par1 + var4; ++var6) {
+ for (int var7 = par2 - var4; var7 <= par2 + var4; ++var7) {
+ double var8 = (double) (var6 - par1);
+ double var10 = (double) (var7 - par2);
+ double var12 = var8 * var8 + var10 * var10;
+
+ if (var12 <= ((double) var4 - 0.5D) * ((double) var4 - 0.5D)) {
+ if (var5 < var3) {
+ if (var12 <= ((double) (var4 - 1) - 0.5D) * ((double) (var4 - 1) - 0.5D)) {
+ this.worldObj.setBlock(var6, var5, var7, Block.bedrock.blockID);
+ }
+ } else if (var5 > var3) {
+ this.worldObj.setBlock(var6, var5, var7, 0);
+ } else if (var12 > ((double) (var4 - 1) - 0.5D) * ((double) (var4 - 1) - 0.5D)) {
+ this.worldObj.setBlock(var6, var5, var7, Block.bedrock.blockID);
+ } else {
+ this.worldObj.setBlock(var6, var5, var7, Block.endPortal.blockID);
+ }
+ }
+ }
+ }
+ }
+
+ this.worldObj.setBlock(par1, var3 + 0, par2, Block.bedrock.blockID);
+ this.worldObj.setBlock(par1, var3 + 1, par2, Block.bedrock.blockID);
+ this.worldObj.setBlock(par1, var3 + 2, par2, Block.bedrock.blockID);
+ this.worldObj.setBlock(par1 - 1, var3 + 2, par2, Block.torchWood.blockID);
+ this.worldObj.setBlock(par1 + 1, var3 + 2, par2, Block.torchWood.blockID);
+ this.worldObj.setBlock(par1, var3 + 2, par2 - 1, Block.torchWood.blockID);
+ this.worldObj.setBlock(par1, var3 + 2, par2 + 1, Block.torchWood.blockID);
+ this.worldObj.setBlock(par1, var3 + 3, par2, Block.bedrock.blockID);
+ this.worldObj.setBlock(par1, var3 + 4, par2, Block.dragonEgg.blockID);
+ BlockEndPortal.bossDefeated = false;
+ }
+
+ /**
+ * Makes the entity despawn if requirements are reached
+ */
+ protected void despawnEntity() {
+ }
+
+ /**
+ * Return the Entity parts making up this Entity (currently only for dragons)
+ */
+ public Entity[] getParts() {
+ return this.dragonPartArray;
+ }
+
+ /**
+ * Returns true if other Entities should be prevented from moving through this
+ * Entity.
+ */
+ public boolean canBeCollidedWith() {
+ return false;
+ }
+
+ public World func_82194_d() {
+ return this.worldObj;
+ }
+
+ /**
+ * Returns the sound this mob makes while it's alive.
+ */
+ protected String getLivingSound() {
+ return "mob.enderdragon.growl";
+ }
+
+ /**
+ * Returns the sound this mob makes when it is hurt.
+ */
+ protected String getHurtSound() {
+ return "mob.enderdragon.hit";
+ }
+
+ /**
+ * Returns the volume for the sounds this mob makes.
+ */
+ protected float getSoundVolume() {
+ return 5.0F;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityDragonPart.java b/sp-server/src/main/java/net/minecraft/src/EntityDragonPart.java
new file mode 100644
index 0000000..ad6b552
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityDragonPart.java
@@ -0,0 +1,54 @@
+package net.minecraft.src;
+
+public class EntityDragonPart extends Entity {
+ /** The dragon entity this dragon part belongs to */
+ public final IEntityMultiPart entityDragonObj;
+
+ /** The name of the Dragon Part */
+ public final String name;
+
+ public EntityDragonPart(IEntityMultiPart par1, String par2, float par3, float par4) {
+ super(par1.func_82194_d());
+ this.setSize(par3, par4);
+ this.entityDragonObj = par1;
+ this.name = par2;
+ }
+
+ protected void entityInit() {
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ protected void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ protected void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ }
+
+ /**
+ * Returns true if other Entities should be prevented from moving through this
+ * Entity.
+ */
+ public boolean canBeCollidedWith() {
+ return true;
+ }
+
+ /**
+ * Called when the entity is attacked.
+ */
+ public boolean attackEntityFrom(DamageSource par1DamageSource, int par2) {
+ return this.isEntityInvulnerable() ? false
+ : this.entityDragonObj.attackEntityFromPart(this, par1DamageSource, par2);
+ }
+
+ /**
+ * Returns true if Entity argument is equal to this Entity
+ */
+ public boolean isEntityEqual(Entity par1Entity) {
+ return this == par1Entity || this.entityDragonObj == par1Entity;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityEgg.java b/sp-server/src/main/java/net/minecraft/src/EntityEgg.java
new file mode 100644
index 0000000..19a564f
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityEgg.java
@@ -0,0 +1,48 @@
+package net.minecraft.src;
+
+public class EntityEgg extends EntityThrowable {
+ public EntityEgg(World par1World) {
+ super(par1World);
+ }
+
+ public EntityEgg(World par1World, EntityLiving par2EntityLiving) {
+ super(par1World, par2EntityLiving);
+ }
+
+ public EntityEgg(World par1World, double par2, double par4, double par6) {
+ super(par1World, par2, par4, par6);
+ }
+
+ /**
+ * Called when this EntityThrowable hits a block or entity.
+ */
+ protected void onImpact(MovingObjectPosition par1MovingObjectPosition) {
+ if (par1MovingObjectPosition.entityHit != null) {
+ par1MovingObjectPosition.entityHit.attackEntityFrom(DamageSource.causeThrownDamage(this, this.getThrower()),
+ 0);
+ }
+
+ if (!this.worldObj.isRemote && this.rand.nextInt(8) == 0) {
+ byte var2 = 1;
+
+ if (this.rand.nextInt(32) == 0) {
+ var2 = 4;
+ }
+
+ for (int var3 = 0; var3 < var2; ++var3) {
+ EntityChicken var4 = new EntityChicken(this.worldObj);
+ var4.setGrowingAge(-24000);
+ var4.setLocationAndAngles(this.posX, this.posY, this.posZ, this.rotationYaw, 0.0F);
+ this.worldObj.spawnEntityInWorld(var4);
+ }
+ }
+
+ for (int var5 = 0; var5 < 8; ++var5) {
+ this.worldObj.spawnParticle("snowballpoof", this.posX, this.posY, this.posZ, 0.0D, 0.0D, 0.0D);
+ }
+
+ if (!this.worldObj.isRemote) {
+ this.setDead();
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityEggInfo.java b/sp-server/src/main/java/net/minecraft/src/EntityEggInfo.java
new file mode 100644
index 0000000..51417a3
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityEggInfo.java
@@ -0,0 +1,18 @@
+package net.minecraft.src;
+
+public class EntityEggInfo {
+ /** The entityID of the spawned mob */
+ public int spawnedID;
+
+ /** Base color of the egg */
+ public int primaryColor;
+
+ /** Color of the egg spots */
+ public int secondaryColor;
+
+ public EntityEggInfo(int par1, int par2, int par3) {
+ this.spawnedID = par1;
+ this.primaryColor = par2;
+ this.secondaryColor = par3;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityEnderCrystal.java b/sp-server/src/main/java/net/minecraft/src/EntityEnderCrystal.java
new file mode 100644
index 0000000..1d1080e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityEnderCrystal.java
@@ -0,0 +1,89 @@
+package net.minecraft.src;
+
+public class EntityEnderCrystal extends Entity {
+ /** Used to create the rotation animation when rendering the crystal. */
+ public int innerRotation = 0;
+ public int health;
+
+ public EntityEnderCrystal(World par1World) {
+ super(par1World);
+ this.preventEntitySpawning = true;
+ this.setSize(2.0F, 2.0F);
+ this.yOffset = this.height / 2.0F;
+ this.health = 5;
+ this.innerRotation = this.rand.nextInt(100000);
+ }
+
+ /**
+ * returns if this entity triggers Block.onEntityWalking on the blocks they walk
+ * on. used for spiders and wolves to prevent them from trampling crops
+ */
+ protected boolean canTriggerWalking() {
+ return false;
+ }
+
+ protected void entityInit() {
+ this.dataWatcher.addObject(8, Integer.valueOf(this.health));
+ }
+
+ /**
+ * Called to update the entity's position/logic.
+ */
+ public void onUpdate() {
+ this.prevPosX = this.posX;
+ this.prevPosY = this.posY;
+ this.prevPosZ = this.posZ;
+ ++this.innerRotation;
+ this.dataWatcher.updateObject(8, Integer.valueOf(this.health));
+ int var1 = MathHelper.floor_double(this.posX);
+ int var2 = MathHelper.floor_double(this.posY);
+ int var3 = MathHelper.floor_double(this.posZ);
+
+ if (this.worldObj.getBlockId(var1, var2, var3) != Block.fire.blockID) {
+ this.worldObj.setBlock(var1, var2, var3, Block.fire.blockID);
+ }
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ protected void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ protected void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ }
+
+ /**
+ * Returns true if other Entities should be prevented from moving through this
+ * Entity.
+ */
+ public boolean canBeCollidedWith() {
+ return true;
+ }
+
+ /**
+ * Called when the entity is attacked.
+ */
+ public boolean attackEntityFrom(DamageSource par1DamageSource, int par2) {
+ if (this.isEntityInvulnerable()) {
+ return false;
+ } else {
+ if (!this.isDead && !this.worldObj.isRemote) {
+ this.health = 0;
+
+ if (this.health <= 0) {
+ this.setDead();
+
+ if (!this.worldObj.isRemote) {
+ this.worldObj.createExplosion((Entity) null, this.posX, this.posY, this.posZ, 6.0F, true);
+ }
+ }
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityEnderEye.java b/sp-server/src/main/java/net/minecraft/src/EntityEnderEye.java
new file mode 100644
index 0000000..2ab756b
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityEnderEye.java
@@ -0,0 +1,171 @@
+package net.minecraft.src;
+
+public class EntityEnderEye extends Entity {
+ public int field_70226_a = 0;
+
+ /** 'x' location the eye should float towards. */
+ private double targetX;
+
+ /** 'y' location the eye should float towards. */
+ private double targetY;
+
+ /** 'z' location the eye should float towards. */
+ private double targetZ;
+ private int despawnTimer;
+ private boolean shatterOrDrop;
+
+ public EntityEnderEye(World par1World) {
+ super(par1World);
+ this.setSize(0.25F, 0.25F);
+ }
+
+ protected void entityInit() {
+ }
+
+ public EntityEnderEye(World par1World, double par2, double par4, double par6) {
+ super(par1World);
+ this.despawnTimer = 0;
+ this.setSize(0.25F, 0.25F);
+ this.setPosition(par2, par4, par6);
+ this.yOffset = 0.0F;
+ }
+
+ /**
+ * The location the eye should float/move towards. Currently used for moving
+ * towards the nearest stronghold. Args: strongholdX, strongholdY, strongholdZ
+ */
+ public void moveTowards(double par1, int par3, double par4) {
+ double var6 = par1 - this.posX;
+ double var8 = par4 - this.posZ;
+ float var10 = MathHelper.sqrt_double(var6 * var6 + var8 * var8);
+
+ if (var10 > 12.0F) {
+ this.targetX = this.posX + var6 / (double) var10 * 12.0D;
+ this.targetZ = this.posZ + var8 / (double) var10 * 12.0D;
+ this.targetY = this.posY + 8.0D;
+ } else {
+ this.targetX = par1;
+ this.targetY = (double) par3;
+ this.targetZ = par4;
+ }
+
+ this.despawnTimer = 0;
+ this.shatterOrDrop = this.rand.nextInt(5) > 0;
+ }
+
+ /**
+ * Called to update the entity's position/logic.
+ */
+ public void onUpdate() {
+ this.lastTickPosX = this.posX;
+ this.lastTickPosY = this.posY;
+ this.lastTickPosZ = this.posZ;
+ super.onUpdate();
+ this.posX += this.motionX;
+ this.posY += this.motionY;
+ this.posZ += this.motionZ;
+ float var1 = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ);
+ this.rotationYaw = (float) (Math.atan2(this.motionX, this.motionZ) * 180.0D / Math.PI);
+
+ for (this.rotationPitch = (float) (Math.atan2(this.motionY, (double) var1) * 180.0D
+ / Math.PI); this.rotationPitch - this.prevRotationPitch < -180.0F; this.prevRotationPitch -= 360.0F) {
+ ;
+ }
+
+ while (this.rotationPitch - this.prevRotationPitch >= 180.0F) {
+ this.prevRotationPitch += 360.0F;
+ }
+
+ while (this.rotationYaw - this.prevRotationYaw < -180.0F) {
+ this.prevRotationYaw -= 360.0F;
+ }
+
+ while (this.rotationYaw - this.prevRotationYaw >= 180.0F) {
+ this.prevRotationYaw += 360.0F;
+ }
+
+ this.rotationPitch = this.prevRotationPitch + (this.rotationPitch - this.prevRotationPitch) * 0.2F;
+ this.rotationYaw = this.prevRotationYaw + (this.rotationYaw - this.prevRotationYaw) * 0.2F;
+
+ if (!this.worldObj.isRemote) {
+ double var2 = this.targetX - this.posX;
+ double var4 = this.targetZ - this.posZ;
+ float var6 = (float) Math.sqrt(var2 * var2 + var4 * var4);
+ float var7 = (float) Math.atan2(var4, var2);
+ double var8 = (double) var1 + (double) (var6 - var1) * 0.0025D;
+
+ if (var6 < 1.0F) {
+ var8 *= 0.8D;
+ this.motionY *= 0.8D;
+ }
+
+ this.motionX = Math.cos((double) var7) * var8;
+ this.motionZ = Math.sin((double) var7) * var8;
+
+ if (this.posY < this.targetY) {
+ this.motionY += (1.0D - this.motionY) * 0.014999999664723873D;
+ } else {
+ this.motionY += (-1.0D - this.motionY) * 0.014999999664723873D;
+ }
+ }
+
+ float var10 = 0.25F;
+
+ if (this.isInWater()) {
+ for (int var3 = 0; var3 < 4; ++var3) {
+ this.worldObj.spawnParticle("bubble", this.posX - this.motionX * (double) var10,
+ this.posY - this.motionY * (double) var10, this.posZ - this.motionZ * (double) var10,
+ this.motionX, this.motionY, this.motionZ);
+ }
+ } else {
+ this.worldObj.spawnParticle("portal",
+ this.posX - this.motionX * (double) var10 + this.rand.nextDouble() * 0.6D - 0.3D,
+ this.posY - this.motionY * (double) var10 - 0.5D,
+ this.posZ - this.motionZ * (double) var10 + this.rand.nextDouble() * 0.6D - 0.3D, this.motionX,
+ this.motionY, this.motionZ);
+ }
+
+ if (!this.worldObj.isRemote) {
+ this.setPosition(this.posX, this.posY, this.posZ);
+ ++this.despawnTimer;
+
+ if (this.despawnTimer > 80 && !this.worldObj.isRemote) {
+ this.setDead();
+
+ if (this.shatterOrDrop) {
+ this.worldObj.spawnEntityInWorld(new EntityItem(this.worldObj, this.posX, this.posY, this.posZ,
+ new ItemStack(Item.eyeOfEnder)));
+ } else {
+ this.worldObj.playAuxSFX(2003, (int) Math.round(this.posX), (int) Math.round(this.posY),
+ (int) Math.round(this.posZ), 0);
+ }
+ }
+ }
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ }
+
+ /**
+ * Gets how bright this entity is.
+ */
+ public float getBrightness(float par1) {
+ return 1.0F;
+ }
+
+ /**
+ * If returns false, the item will not inflict any damage against entities.
+ */
+ public boolean canAttackWithItem() {
+ return false;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityEnderPearl.java b/sp-server/src/main/java/net/minecraft/src/EntityEnderPearl.java
new file mode 100644
index 0000000..faaaed2
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityEnderPearl.java
@@ -0,0 +1,40 @@
+package net.minecraft.src;
+
+public class EntityEnderPearl extends EntityThrowable {
+ public EntityEnderPearl(World par1World) {
+ super(par1World);
+ }
+
+ public EntityEnderPearl(World par1World, EntityLiving par2EntityLiving) {
+ super(par1World, par2EntityLiving);
+ }
+
+ /**
+ * Called when this EntityThrowable hits a block or entity.
+ */
+ protected void onImpact(MovingObjectPosition par1MovingObjectPosition) {
+ if (par1MovingObjectPosition.entityHit != null) {
+ par1MovingObjectPosition.entityHit.attackEntityFrom(DamageSource.causeThrownDamage(this, this.getThrower()),
+ 0);
+ }
+
+ for (int var2 = 0; var2 < 32; ++var2) {
+ this.worldObj.spawnParticle("portal", this.posX, this.posY + this.rand.nextDouble() * 2.0D, this.posZ,
+ this.rand.nextGaussian(), 0.0D, this.rand.nextGaussian());
+ }
+
+ if (!this.worldObj.isRemote) {
+ if (this.getThrower() != null && this.getThrower() instanceof EntityPlayerMP) {
+ EntityPlayerMP var3 = (EntityPlayerMP) this.getThrower();
+
+ if (!var3.playerNetServerHandler.connectionClosed && var3.worldObj == this.worldObj) {
+ this.getThrower().setPositionAndUpdate(this.posX, this.posY, this.posZ);
+ this.getThrower().fallDistance = 0.0F;
+ this.getThrower().attackEntityFrom(DamageSource.fall, 5);
+ }
+ }
+
+ this.setDead();
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityEnderman.java b/sp-server/src/main/java/net/minecraft/src/EntityEnderman.java
new file mode 100644
index 0000000..c78d98c
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityEnderman.java
@@ -0,0 +1,432 @@
+package net.minecraft.src;
+
+public class EntityEnderman extends EntityMob {
+ private static boolean[] carriableBlocks = new boolean[256];
+
+ /**
+ * Counter to delay the teleportation of an enderman towards the currently
+ * attacked target
+ */
+ private int teleportDelay = 0;
+ private int field_70826_g = 0;
+ private boolean field_104003_g;
+
+ public EntityEnderman(World par1World) {
+ super(par1World);
+ this.texture = "/mob/enderman.png";
+ this.moveSpeed = 0.2F;
+ this.setSize(0.6F, 2.9F);
+ this.stepHeight = 1.0F;
+ }
+
+ public int getMaxHealth() {
+ return 40;
+ }
+
+ protected void entityInit() {
+ super.entityInit();
+ this.dataWatcher.addObject(16, Byte.valueOf((byte) 0));
+ this.dataWatcher.addObject(17, Byte.valueOf((byte) 0));
+ this.dataWatcher.addObject(18, Byte.valueOf((byte) 0));
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ super.writeEntityToNBT(par1NBTTagCompound);
+ par1NBTTagCompound.setShort("carried", (short) this.getCarried());
+ par1NBTTagCompound.setShort("carriedData", (short) this.getCarryingData());
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ super.readEntityFromNBT(par1NBTTagCompound);
+ this.setCarried(par1NBTTagCompound.getShort("carried"));
+ this.setCarryingData(par1NBTTagCompound.getShort("carriedData"));
+ }
+
+ /**
+ * Finds the closest player within 16 blocks to attack, or null if this Entity
+ * isn't interested in attacking (Animals, Spiders at day, peaceful PigZombies).
+ */
+ protected Entity findPlayerToAttack() {
+ EntityPlayer var1 = this.worldObj.getClosestVulnerablePlayerToEntity(this, 64.0D);
+
+ if (var1 != null) {
+ if (this.shouldAttackPlayer(var1)) {
+ this.field_104003_g = true;
+
+ if (this.field_70826_g == 0) {
+ this.worldObj.playSoundAtEntity(var1, "mob.endermen.stare", 1.0F, 1.0F);
+ }
+
+ if (this.field_70826_g++ == 5) {
+ this.field_70826_g = 0;
+ this.setScreaming(true);
+ return var1;
+ }
+ } else {
+ this.field_70826_g = 0;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Checks to see if this enderman should be attacking this player
+ */
+ private boolean shouldAttackPlayer(EntityPlayer par1EntityPlayer) {
+ ItemStack var2 = par1EntityPlayer.inventory.armorInventory[3];
+
+ if (var2 != null && var2.itemID == Block.pumpkin.blockID) {
+ return false;
+ } else {
+ Vec3 var3 = par1EntityPlayer.getLook(1.0F).normalize();
+ Vec3 var4 = this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX - par1EntityPlayer.posX,
+ this.boundingBox.minY + (double) (this.height / 2.0F)
+ - (par1EntityPlayer.posY + (double) par1EntityPlayer.getEyeHeight()),
+ this.posZ - par1EntityPlayer.posZ);
+ double var5 = var4.lengthVector();
+ var4 = var4.normalize();
+ double var7 = var3.dotProduct(var4);
+ return var7 > 1.0D - 0.025D / var5 ? par1EntityPlayer.canEntityBeSeen(this) : false;
+ }
+ }
+
+ /**
+ * Called frequently so the entity can update its state every tick as required.
+ * For example, zombies and skeletons use this to react to sunlight and start to
+ * burn.
+ */
+ public void onLivingUpdate() {
+ if (this.isWet()) {
+ this.attackEntityFrom(DamageSource.drown, 1);
+ }
+
+ this.moveSpeed = this.entityToAttack != null ? 6.5F : 0.3F;
+ int var1;
+
+ if (!this.worldObj.isRemote && this.worldObj.getGameRules().getGameRuleBooleanValue("mobGriefing")) {
+ int var2;
+ int var3;
+ int var4;
+
+ if (this.getCarried() == 0) {
+ if (this.rand.nextInt(20) == 0) {
+ var1 = MathHelper.floor_double(this.posX - 2.0D + this.rand.nextDouble() * 4.0D);
+ var2 = MathHelper.floor_double(this.posY + this.rand.nextDouble() * 3.0D);
+ var3 = MathHelper.floor_double(this.posZ - 2.0D + this.rand.nextDouble() * 4.0D);
+ var4 = this.worldObj.getBlockId(var1, var2, var3);
+
+ if (carriableBlocks[var4]) {
+ this.setCarried(this.worldObj.getBlockId(var1, var2, var3));
+ this.setCarryingData(this.worldObj.getBlockMetadata(var1, var2, var3));
+ this.worldObj.setBlock(var1, var2, var3, 0);
+ }
+ }
+ } else if (this.rand.nextInt(2000) == 0) {
+ var1 = MathHelper.floor_double(this.posX - 1.0D + this.rand.nextDouble() * 2.0D);
+ var2 = MathHelper.floor_double(this.posY + this.rand.nextDouble() * 2.0D);
+ var3 = MathHelper.floor_double(this.posZ - 1.0D + this.rand.nextDouble() * 2.0D);
+ var4 = this.worldObj.getBlockId(var1, var2, var3);
+ int var5 = this.worldObj.getBlockId(var1, var2 - 1, var3);
+
+ if (var4 == 0 && var5 > 0 && Block.blocksList[var5].renderAsNormalBlock()) {
+ this.worldObj.setBlock(var1, var2, var3, this.getCarried(), this.getCarryingData(), 3);
+ this.setCarried(0);
+ }
+ }
+ }
+
+ for (var1 = 0; var1 < 2; ++var1) {
+ this.worldObj.spawnParticle("portal", this.posX + (this.rand.nextDouble() - 0.5D) * (double) this.width,
+ this.posY + this.rand.nextDouble() * (double) this.height - 0.25D,
+ this.posZ + (this.rand.nextDouble() - 0.5D) * (double) this.width,
+ (this.rand.nextDouble() - 0.5D) * 2.0D, -this.rand.nextDouble(),
+ (this.rand.nextDouble() - 0.5D) * 2.0D);
+ }
+
+ if (this.worldObj.isDaytime() && !this.worldObj.isRemote) {
+ float var6 = this.getBrightness(1.0F);
+
+ if (var6 > 0.5F
+ && this.worldObj.canBlockSeeTheSky(MathHelper.floor_double(this.posX),
+ MathHelper.floor_double(this.posY), MathHelper.floor_double(this.posZ))
+ && this.rand.nextFloat() * 30.0F < (var6 - 0.4F) * 2.0F) {
+ this.entityToAttack = null;
+ this.setScreaming(false);
+ this.field_104003_g = false;
+ this.teleportRandomly();
+ }
+ }
+
+ if (this.isWet() || this.isBurning()) {
+ this.entityToAttack = null;
+ this.setScreaming(false);
+ this.field_104003_g = false;
+ this.teleportRandomly();
+ }
+
+ if (this.isScreaming() && !this.field_104003_g && this.rand.nextInt(100) == 0) {
+ this.setScreaming(false);
+ }
+
+ this.isJumping = false;
+
+ if (this.entityToAttack != null) {
+ this.faceEntity(this.entityToAttack, 100.0F, 100.0F);
+ }
+
+ if (!this.worldObj.isRemote && this.isEntityAlive()) {
+ if (this.entityToAttack != null) {
+ if (this.entityToAttack instanceof EntityPlayer
+ && this.shouldAttackPlayer((EntityPlayer) this.entityToAttack)) {
+ this.moveStrafing = this.moveForward = 0.0F;
+ this.moveSpeed = 0.0F;
+
+ if (this.entityToAttack.getDistanceSqToEntity(this) < 16.0D) {
+ this.teleportRandomly();
+ }
+
+ this.teleportDelay = 0;
+ } else if (this.entityToAttack.getDistanceSqToEntity(this) > 256.0D && this.teleportDelay++ >= 30
+ && this.teleportToEntity(this.entityToAttack)) {
+ this.teleportDelay = 0;
+ }
+ } else {
+ this.setScreaming(false);
+ this.teleportDelay = 0;
+ }
+ }
+
+ super.onLivingUpdate();
+ }
+
+ /**
+ * Teleport the enderman to a random nearby position
+ */
+ protected boolean teleportRandomly() {
+ double var1 = this.posX + (this.rand.nextDouble() - 0.5D) * 64.0D;
+ double var3 = this.posY + (double) (this.rand.nextInt(64) - 32);
+ double var5 = this.posZ + (this.rand.nextDouble() - 0.5D) * 64.0D;
+ return this.teleportTo(var1, var3, var5);
+ }
+
+ /**
+ * Teleport the enderman to another entity
+ */
+ protected boolean teleportToEntity(Entity par1Entity) {
+ Vec3 var2 = this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX - par1Entity.posX, this.boundingBox.minY
+ + (double) (this.height / 2.0F) - par1Entity.posY + (double) par1Entity.getEyeHeight(),
+ this.posZ - par1Entity.posZ);
+ var2 = var2.normalize();
+ double var3 = 16.0D;
+ double var5 = this.posX + (this.rand.nextDouble() - 0.5D) * 8.0D - var2.xCoord * var3;
+ double var7 = this.posY + (double) (this.rand.nextInt(16) - 8) - var2.yCoord * var3;
+ double var9 = this.posZ + (this.rand.nextDouble() - 0.5D) * 8.0D - var2.zCoord * var3;
+ return this.teleportTo(var5, var7, var9);
+ }
+
+ /**
+ * Teleport the enderman
+ */
+ protected boolean teleportTo(double par1, double par3, double par5) {
+ double var7 = this.posX;
+ double var9 = this.posY;
+ double var11 = this.posZ;
+ this.posX = par1;
+ this.posY = par3;
+ this.posZ = par5;
+ boolean var13 = false;
+ int var14 = MathHelper.floor_double(this.posX);
+ int var15 = MathHelper.floor_double(this.posY);
+ int var16 = MathHelper.floor_double(this.posZ);
+ int var18;
+
+ if (this.worldObj.blockExists(var14, var15, var16)) {
+ boolean var17 = false;
+
+ while (!var17 && var15 > 0) {
+ var18 = this.worldObj.getBlockId(var14, var15 - 1, var16);
+
+ if (var18 != 0 && Block.blocksList[var18].blockMaterial.blocksMovement()) {
+ var17 = true;
+ } else {
+ --this.posY;
+ --var15;
+ }
+ }
+
+ if (var17) {
+ this.setPosition(this.posX, this.posY, this.posZ);
+
+ if (this.worldObj.getCollidingBoundingBoxes(this, this.boundingBox).isEmpty()
+ && !this.worldObj.isAnyLiquid(this.boundingBox)) {
+ var13 = true;
+ }
+ }
+ }
+
+ if (!var13) {
+ this.setPosition(var7, var9, var11);
+ return false;
+ } else {
+ short var30 = 128;
+
+ for (var18 = 0; var18 < var30; ++var18) {
+ double var19 = (double) var18 / ((double) var30 - 1.0D);
+ float var21 = (this.rand.nextFloat() - 0.5F) * 0.2F;
+ float var22 = (this.rand.nextFloat() - 0.5F) * 0.2F;
+ float var23 = (this.rand.nextFloat() - 0.5F) * 0.2F;
+ double var24 = var7 + (this.posX - var7) * var19
+ + (this.rand.nextDouble() - 0.5D) * (double) this.width * 2.0D;
+ double var26 = var9 + (this.posY - var9) * var19 + this.rand.nextDouble() * (double) this.height;
+ double var28 = var11 + (this.posZ - var11) * var19
+ + (this.rand.nextDouble() - 0.5D) * (double) this.width * 2.0D;
+ this.worldObj.spawnParticle("portal", var24, var26, var28, (double) var21, (double) var22,
+ (double) var23);
+ }
+
+ this.worldObj.playSoundEffect(var7, var9, var11, "mob.endermen.portal", 1.0F, 1.0F);
+ this.playSound("mob.endermen.portal", 1.0F, 1.0F);
+ return true;
+ }
+ }
+
+ /**
+ * Returns the sound this mob makes while it's alive.
+ */
+ protected String getLivingSound() {
+ return this.isScreaming() ? "mob.endermen.scream" : "mob.endermen.idle";
+ }
+
+ /**
+ * Returns the sound this mob makes when it is hurt.
+ */
+ protected String getHurtSound() {
+ return "mob.endermen.hit";
+ }
+
+ /**
+ * Returns the sound this mob makes on death.
+ */
+ protected String getDeathSound() {
+ return "mob.endermen.death";
+ }
+
+ /**
+ * Returns the item ID for the item the mob drops on death.
+ */
+ protected int getDropItemId() {
+ return Item.enderPearl.itemID;
+ }
+
+ /**
+ * Drop 0-2 items of this living's type
+ */
+ protected void dropFewItems(boolean par1, int par2) {
+ int var3 = this.getDropItemId();
+
+ if (var3 > 0) {
+ int var4 = this.rand.nextInt(2 + par2);
+
+ for (int var5 = 0; var5 < var4; ++var5) {
+ this.dropItem(var3, 1);
+ }
+ }
+ }
+
+ /**
+ * Set the id of the block an enderman carries
+ */
+ public void setCarried(int par1) {
+ this.dataWatcher.updateObject(16, Byte.valueOf((byte) (par1 & 255)));
+ }
+
+ /**
+ * Get the id of the block an enderman carries
+ */
+ public int getCarried() {
+ return this.dataWatcher.getWatchableObjectByte(16);
+ }
+
+ /**
+ * Set the metadata of the block an enderman carries
+ */
+ public void setCarryingData(int par1) {
+ this.dataWatcher.updateObject(17, Byte.valueOf((byte) (par1 & 255)));
+ }
+
+ /**
+ * Get the metadata of the block an enderman carries
+ */
+ public int getCarryingData() {
+ return this.dataWatcher.getWatchableObjectByte(17);
+ }
+
+ /**
+ * Called when the entity is attacked.
+ */
+ public boolean attackEntityFrom(DamageSource par1DamageSource, int par2) {
+ if (this.isEntityInvulnerable()) {
+ return false;
+ } else {
+ this.setScreaming(true);
+
+ if (par1DamageSource instanceof EntityDamageSource
+ && par1DamageSource.getEntity() instanceof EntityPlayer) {
+ this.field_104003_g = true;
+ }
+
+ if (par1DamageSource instanceof EntityDamageSourceIndirect) {
+ this.field_104003_g = false;
+
+ for (int var3 = 0; var3 < 64; ++var3) {
+ if (this.teleportRandomly()) {
+ return true;
+ }
+ }
+
+ return false;
+ } else {
+ return super.attackEntityFrom(par1DamageSource, par2);
+ }
+ }
+ }
+
+ public boolean isScreaming() {
+ return this.dataWatcher.getWatchableObjectByte(18) > 0;
+ }
+
+ public void setScreaming(boolean par1) {
+ this.dataWatcher.updateObject(18, Byte.valueOf((byte) (par1 ? 1 : 0)));
+ }
+
+ /**
+ * Returns the amount of damage a mob should deal.
+ */
+ public int getAttackStrength(Entity par1Entity) {
+ return 7;
+ }
+
+ static {
+ carriableBlocks[Block.grass.blockID] = true;
+ carriableBlocks[Block.dirt.blockID] = true;
+ carriableBlocks[Block.sand.blockID] = true;
+ carriableBlocks[Block.gravel.blockID] = true;
+ carriableBlocks[Block.plantYellow.blockID] = true;
+ carriableBlocks[Block.plantRed.blockID] = true;
+ carriableBlocks[Block.mushroomBrown.blockID] = true;
+ carriableBlocks[Block.mushroomRed.blockID] = true;
+ carriableBlocks[Block.tnt.blockID] = true;
+ carriableBlocks[Block.cactus.blockID] = true;
+ carriableBlocks[Block.blockClay.blockID] = true;
+ carriableBlocks[Block.pumpkin.blockID] = true;
+ carriableBlocks[Block.melon.blockID] = true;
+ carriableBlocks[Block.mycelium.blockID] = true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityExpBottle.java b/sp-server/src/main/java/net/minecraft/src/EntityExpBottle.java
new file mode 100644
index 0000000..255e103
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityExpBottle.java
@@ -0,0 +1,49 @@
+package net.minecraft.src;
+
+public class EntityExpBottle extends EntityThrowable {
+ public EntityExpBottle(World par1World) {
+ super(par1World);
+ }
+
+ public EntityExpBottle(World par1World, EntityLiving par2EntityLiving) {
+ super(par1World, par2EntityLiving);
+ }
+
+ public EntityExpBottle(World par1World, double par2, double par4, double par6) {
+ super(par1World, par2, par4, par6);
+ }
+
+ /**
+ * Gets the amount of gravity to apply to the thrown entity with each tick.
+ */
+ protected float getGravityVelocity() {
+ return 0.07F;
+ }
+
+ protected float func_70182_d() {
+ return 0.7F;
+ }
+
+ protected float func_70183_g() {
+ return -20.0F;
+ }
+
+ /**
+ * Called when this EntityThrowable hits a block or entity.
+ */
+ protected void onImpact(MovingObjectPosition par1MovingObjectPosition) {
+ if (!this.worldObj.isRemote) {
+ this.worldObj.playAuxSFX(2002, (int) Math.round(this.posX), (int) Math.round(this.posY),
+ (int) Math.round(this.posZ), 0);
+ int var2 = 3 + this.worldObj.rand.nextInt(5) + this.worldObj.rand.nextInt(5);
+
+ while (var2 > 0) {
+ int var3 = EntityXPOrb.getXPSplit(var2);
+ var2 -= var3;
+ this.worldObj.spawnEntityInWorld(new EntityXPOrb(this.worldObj, this.posX, this.posY, this.posZ, var3));
+ }
+
+ this.setDead();
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityFallingSand.java b/sp-server/src/main/java/net/minecraft/src/EntityFallingSand.java
new file mode 100644
index 0000000..d1a76b9
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityFallingSand.java
@@ -0,0 +1,260 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+public class EntityFallingSand extends Entity {
+ public int blockID;
+ public int metadata;
+
+ /** How long the block has been falling for. */
+ public int fallTime;
+ public boolean shouldDropItem;
+ private boolean isBreakingAnvil;
+ private boolean isAnvil;
+
+ /** Maximum amount of damage dealt to entities hit by falling block */
+ private int fallHurtMax;
+
+ /** Actual damage dealt to entities hit by falling block */
+ private float fallHurtAmount;
+ public NBTTagCompound fallingBlockTileEntityData;
+
+ public EntityFallingSand(World par1World) {
+ super(par1World);
+ this.fallTime = 0;
+ this.shouldDropItem = true;
+ this.isBreakingAnvil = false;
+ this.isAnvil = false;
+ this.fallHurtMax = 40;
+ this.fallHurtAmount = 2.0F;
+ this.fallingBlockTileEntityData = null;
+ }
+
+ public EntityFallingSand(World par1World, double par2, double par4, double par6, int par8) {
+ this(par1World, par2, par4, par6, par8, 0);
+ }
+
+ public EntityFallingSand(World par1World, double par2, double par4, double par6, int par8, int par9) {
+ super(par1World);
+ this.fallTime = 0;
+ this.shouldDropItem = true;
+ this.isBreakingAnvil = false;
+ this.isAnvil = false;
+ this.fallHurtMax = 40;
+ this.fallHurtAmount = 2.0F;
+ this.fallingBlockTileEntityData = null;
+ this.blockID = par8;
+ this.metadata = par9;
+ this.preventEntitySpawning = true;
+ this.setSize(0.98F, 0.98F);
+ this.yOffset = this.height / 2.0F;
+ this.setPosition(par2, par4, par6);
+ this.motionX = 0.0D;
+ this.motionY = 0.0D;
+ this.motionZ = 0.0D;
+ this.prevPosX = par2;
+ this.prevPosY = par4;
+ this.prevPosZ = par6;
+ }
+
+ /**
+ * returns if this entity triggers Block.onEntityWalking on the blocks they walk
+ * on. used for spiders and wolves to prevent them from trampling crops
+ */
+ protected boolean canTriggerWalking() {
+ return false;
+ }
+
+ protected void entityInit() {
+ }
+
+ /**
+ * Returns true if other Entities should be prevented from moving through this
+ * Entity.
+ */
+ public boolean canBeCollidedWith() {
+ return !this.isDead;
+ }
+
+ /**
+ * Called to update the entity's position/logic.
+ */
+ public void onUpdate() {
+ if (this.blockID == 0) {
+ this.setDead();
+ } else {
+ this.prevPosX = this.posX;
+ this.prevPosY = this.posY;
+ this.prevPosZ = this.posZ;
+ ++this.fallTime;
+ this.motionY -= 0.03999999910593033D;
+ this.moveEntity(this.motionX, this.motionY, this.motionZ);
+ this.motionX *= 0.9800000190734863D;
+ this.motionY *= 0.9800000190734863D;
+ this.motionZ *= 0.9800000190734863D;
+
+ if (!this.worldObj.isRemote) {
+ int var1 = MathHelper.floor_double(this.posX);
+ int var2 = MathHelper.floor_double(this.posY);
+ int var3 = MathHelper.floor_double(this.posZ);
+
+ if (this.fallTime == 1) {
+ if (this.worldObj.getBlockId(var1, var2, var3) != this.blockID) {
+ this.setDead();
+ return;
+ }
+
+ this.worldObj.setBlockToAir(var1, var2, var3);
+ }
+
+ if (this.onGround) {
+ this.motionX *= 0.699999988079071D;
+ this.motionZ *= 0.699999988079071D;
+ this.motionY *= -0.5D;
+
+ if (this.worldObj.getBlockId(var1, var2, var3) != Block.pistonMoving.blockID) {
+ this.setDead();
+
+ if (!this.isBreakingAnvil
+ && this.worldObj.canPlaceEntityOnSide(this.blockID, var1, var2, var3, true, 1,
+ (Entity) null, (ItemStack) null)
+ && !BlockSand.canFallBelow(this.worldObj, var1, var2 - 1, var3)
+ && this.worldObj.setBlock(var1, var2, var3, this.blockID, this.metadata, 3)) {
+ if (Block.blocksList[this.blockID] instanceof BlockSand) {
+ ((BlockSand) Block.blocksList[this.blockID]).onFinishFalling(this.worldObj, var1, var2,
+ var3, this.metadata);
+ }
+
+ if (this.fallingBlockTileEntityData != null
+ && Block.blocksList[this.blockID] instanceof ITileEntityProvider) {
+ TileEntity var4 = this.worldObj.getBlockTileEntity(var1, var2, var3);
+
+ if (var4 != null) {
+ NBTTagCompound var5 = new NBTTagCompound();
+ var4.writeToNBT(var5);
+ Iterator var6 = this.fallingBlockTileEntityData.getTags().iterator();
+
+ while (var6.hasNext()) {
+ NBTBase var7 = (NBTBase) var6.next();
+
+ if (!var7.getName().equals("x") && !var7.getName().equals("y")
+ && !var7.getName().equals("z")) {
+ var5.setTag(var7.getName(), var7.copy());
+ }
+ }
+
+ var4.readFromNBT(var5);
+ var4.onInventoryChanged();
+ }
+ }
+ } else if (this.shouldDropItem && !this.isBreakingAnvil) {
+ this.entityDropItem(new ItemStack(this.blockID, 1,
+ Block.blocksList[this.blockID].damageDropped(this.metadata)), 0.0F);
+ }
+ }
+ } else if (this.fallTime > 100 && !this.worldObj.isRemote && (var2 < 1 || var2 > 256)
+ || this.fallTime > 600) {
+ if (this.shouldDropItem) {
+ this.entityDropItem(new ItemStack(this.blockID, 1,
+ Block.blocksList[this.blockID].damageDropped(this.metadata)), 0.0F);
+ }
+
+ this.setDead();
+ }
+ }
+ }
+ }
+
+ /**
+ * Called when the mob is falling. Calculates and applies fall damage.
+ */
+ protected void fall(float par1) {
+ if (this.isAnvil) {
+ int var2 = MathHelper.ceiling_float_int(par1 - 1.0F);
+
+ if (var2 > 0) {
+ ArrayList var3 = new ArrayList(
+ this.worldObj.getEntitiesWithinAABBExcludingEntity(this, this.boundingBox));
+ DamageSource var4 = this.blockID == Block.anvil.blockID ? DamageSource.anvil
+ : DamageSource.fallingBlock;
+ Iterator var5 = var3.iterator();
+
+ while (var5.hasNext()) {
+ Entity var6 = (Entity) var5.next();
+ var6.attackEntityFrom(var4,
+ Math.min(MathHelper.floor_float((float) var2 * this.fallHurtAmount), this.fallHurtMax));
+ }
+
+ if (this.blockID == Block.anvil.blockID
+ && (double) this.rand.nextFloat() < 0.05000000074505806D + (double) var2 * 0.05D) {
+ int var7 = this.metadata >> 2;
+ int var8 = this.metadata & 3;
+ ++var7;
+
+ if (var7 > 2) {
+ this.isBreakingAnvil = true;
+ } else {
+ this.metadata = var8 | var7 << 2;
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ protected void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ par1NBTTagCompound.setByte("Tile", (byte) this.blockID);
+ par1NBTTagCompound.setInteger("TileID", this.blockID);
+ par1NBTTagCompound.setByte("Data", (byte) this.metadata);
+ par1NBTTagCompound.setByte("Time", (byte) this.fallTime);
+ par1NBTTagCompound.setBoolean("DropItem", this.shouldDropItem);
+ par1NBTTagCompound.setBoolean("HurtEntities", this.isAnvil);
+ par1NBTTagCompound.setFloat("FallHurtAmount", this.fallHurtAmount);
+ par1NBTTagCompound.setInteger("FallHurtMax", this.fallHurtMax);
+
+ if (this.fallingBlockTileEntityData != null) {
+ par1NBTTagCompound.setCompoundTag("TileEntityData", this.fallingBlockTileEntityData);
+ }
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ protected void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ if (par1NBTTagCompound.hasKey("TileID")) {
+ this.blockID = par1NBTTagCompound.getInteger("TileID");
+ } else {
+ this.blockID = par1NBTTagCompound.getByte("Tile") & 255;
+ }
+
+ this.metadata = par1NBTTagCompound.getByte("Data") & 255;
+ this.fallTime = par1NBTTagCompound.getByte("Time") & 255;
+
+ if (par1NBTTagCompound.hasKey("HurtEntities")) {
+ this.isAnvil = par1NBTTagCompound.getBoolean("HurtEntities");
+ this.fallHurtAmount = par1NBTTagCompound.getFloat("FallHurtAmount");
+ this.fallHurtMax = par1NBTTagCompound.getInteger("FallHurtMax");
+ } else if (this.blockID == Block.anvil.blockID) {
+ this.isAnvil = true;
+ }
+
+ if (par1NBTTagCompound.hasKey("DropItem")) {
+ this.shouldDropItem = par1NBTTagCompound.getBoolean("DropItem");
+ }
+
+ if (par1NBTTagCompound.hasKey("TileEntityData")) {
+ this.fallingBlockTileEntityData = par1NBTTagCompound.getCompoundTag("TileEntityData");
+ }
+
+ if (this.blockID == 0) {
+ this.blockID = Block.sand.blockID;
+ }
+ }
+
+ public void setIsAnvil(boolean par1) {
+ this.isAnvil = par1;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityFireball.java b/sp-server/src/main/java/net/minecraft/src/EntityFireball.java
new file mode 100644
index 0000000..7e698c3
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityFireball.java
@@ -0,0 +1,280 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+public abstract class EntityFireball extends Entity {
+ private int xTile = -1;
+ private int yTile = -1;
+ private int zTile = -1;
+ private int inTile = 0;
+ private boolean inGround = false;
+ public EntityLiving shootingEntity;
+ private int ticksAlive;
+ private int ticksInAir = 0;
+ public double accelerationX;
+ public double accelerationY;
+ public double accelerationZ;
+
+ public EntityFireball(World par1World) {
+ super(par1World);
+ this.setSize(1.0F, 1.0F);
+ }
+
+ protected void entityInit() {
+ }
+
+ public EntityFireball(World par1World, double par2, double par4, double par6, double par8, double par10,
+ double par12) {
+ super(par1World);
+ this.setSize(1.0F, 1.0F);
+ this.setLocationAndAngles(par2, par4, par6, this.rotationYaw, this.rotationPitch);
+ this.setPosition(par2, par4, par6);
+ double var14 = (double) MathHelper.sqrt_double(par8 * par8 + par10 * par10 + par12 * par12);
+ this.accelerationX = par8 / var14 * 0.1D;
+ this.accelerationY = par10 / var14 * 0.1D;
+ this.accelerationZ = par12 / var14 * 0.1D;
+ }
+
+ public EntityFireball(World par1World, EntityLiving par2EntityLiving, double par3, double par5, double par7) {
+ super(par1World);
+ this.shootingEntity = par2EntityLiving;
+ this.setSize(1.0F, 1.0F);
+ this.setLocationAndAngles(par2EntityLiving.posX, par2EntityLiving.posY, par2EntityLiving.posZ,
+ par2EntityLiving.rotationYaw, par2EntityLiving.rotationPitch);
+ this.setPosition(this.posX, this.posY, this.posZ);
+ this.yOffset = 0.0F;
+ this.motionX = this.motionY = this.motionZ = 0.0D;
+ par3 += this.rand.nextGaussian() * 0.4D;
+ par5 += this.rand.nextGaussian() * 0.4D;
+ par7 += this.rand.nextGaussian() * 0.4D;
+ double var9 = (double) MathHelper.sqrt_double(par3 * par3 + par5 * par5 + par7 * par7);
+ this.accelerationX = par3 / var9 * 0.1D;
+ this.accelerationY = par5 / var9 * 0.1D;
+ this.accelerationZ = par7 / var9 * 0.1D;
+ }
+
+ /**
+ * Called to update the entity's position/logic.
+ */
+ public void onUpdate() {
+ if (!this.worldObj.isRemote && (this.shootingEntity != null && this.shootingEntity.isDead
+ || !this.worldObj.blockExists((int) this.posX, (int) this.posY, (int) this.posZ))) {
+ this.setDead();
+ } else {
+ super.onUpdate();
+ this.setFire(1);
+
+ if (this.inGround) {
+ int var1 = this.worldObj.getBlockId(this.xTile, this.yTile, this.zTile);
+
+ if (var1 == this.inTile) {
+ ++this.ticksAlive;
+
+ if (this.ticksAlive == 600) {
+ this.setDead();
+ }
+
+ return;
+ }
+
+ this.inGround = false;
+ this.motionX *= (double) (this.rand.nextFloat() * 0.2F);
+ this.motionY *= (double) (this.rand.nextFloat() * 0.2F);
+ this.motionZ *= (double) (this.rand.nextFloat() * 0.2F);
+ this.ticksAlive = 0;
+ this.ticksInAir = 0;
+ } else {
+ ++this.ticksInAir;
+ }
+
+ Vec3 var15 = this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX, this.posY, this.posZ);
+ Vec3 var2 = this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX + this.motionX,
+ this.posY + this.motionY, this.posZ + this.motionZ);
+ MovingObjectPosition var3 = this.worldObj.rayTraceBlocks(var15, var2);
+ var15 = this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX, this.posY, this.posZ);
+ var2 = this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX + this.motionX, this.posY + this.motionY,
+ this.posZ + this.motionZ);
+
+ if (var3 != null) {
+ var2 = this.worldObj.getWorldVec3Pool().getVecFromPool(var3.hitVec.xCoord, var3.hitVec.yCoord,
+ var3.hitVec.zCoord);
+ }
+
+ Entity var4 = null;
+ List var5 = this.worldObj.getEntitiesWithinAABBExcludingEntity(this,
+ this.boundingBox.addCoord(this.motionX, this.motionY, this.motionZ).expand(1.0D, 1.0D, 1.0D));
+ double var6 = 0.0D;
+
+ for (int var8 = 0; var8 < var5.size(); ++var8) {
+ Entity var9 = (Entity) var5.get(var8);
+
+ if (var9.canBeCollidedWith() && (!var9.isEntityEqual(this.shootingEntity) || this.ticksInAir >= 25)) {
+ float var10 = 0.3F;
+ AxisAlignedBB var11 = var9.boundingBox.expand((double) var10, (double) var10, (double) var10);
+ MovingObjectPosition var12 = var11.calculateIntercept(var15, var2);
+
+ if (var12 != null) {
+ double var13 = var15.distanceTo(var12.hitVec);
+
+ if (var13 < var6 || var6 == 0.0D) {
+ var4 = var9;
+ var6 = var13;
+ }
+ }
+ }
+ }
+
+ if (var4 != null) {
+ var3 = new MovingObjectPosition(var4);
+ }
+
+ if (var3 != null) {
+ this.onImpact(var3);
+ }
+
+ this.posX += this.motionX;
+ this.posY += this.motionY;
+ this.posZ += this.motionZ;
+ float var16 = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ);
+ this.rotationYaw = (float) (Math.atan2(this.motionZ, this.motionX) * 180.0D / Math.PI) + 90.0F;
+
+ for (this.rotationPitch = (float) (Math.atan2((double) var16, this.motionY) * 180.0D / Math.PI)
+ - 90.0F; this.rotationPitch - this.prevRotationPitch < -180.0F; this.prevRotationPitch -= 360.0F) {
+ ;
+ }
+
+ while (this.rotationPitch - this.prevRotationPitch >= 180.0F) {
+ this.prevRotationPitch += 360.0F;
+ }
+
+ while (this.rotationYaw - this.prevRotationYaw < -180.0F) {
+ this.prevRotationYaw -= 360.0F;
+ }
+
+ while (this.rotationYaw - this.prevRotationYaw >= 180.0F) {
+ this.prevRotationYaw += 360.0F;
+ }
+
+ this.rotationPitch = this.prevRotationPitch + (this.rotationPitch - this.prevRotationPitch) * 0.2F;
+ this.rotationYaw = this.prevRotationYaw + (this.rotationYaw - this.prevRotationYaw) * 0.2F;
+ float var17 = this.getMotionFactor();
+
+ if (this.isInWater()) {
+ for (int var18 = 0; var18 < 4; ++var18) {
+ float var19 = 0.25F;
+ this.worldObj.spawnParticle("bubble", this.posX - this.motionX * (double) var19,
+ this.posY - this.motionY * (double) var19, this.posZ - this.motionZ * (double) var19,
+ this.motionX, this.motionY, this.motionZ);
+ }
+
+ var17 = 0.8F;
+ }
+
+ this.motionX += this.accelerationX;
+ this.motionY += this.accelerationY;
+ this.motionZ += this.accelerationZ;
+ this.motionX *= (double) var17;
+ this.motionY *= (double) var17;
+ this.motionZ *= (double) var17;
+ this.worldObj.spawnParticle("smoke", this.posX, this.posY + 0.5D, this.posZ, 0.0D, 0.0D, 0.0D);
+ this.setPosition(this.posX, this.posY, this.posZ);
+ }
+ }
+
+ /**
+ * Return the motion factor for this projectile. The factor is multiplied by the
+ * original motion.
+ */
+ protected float getMotionFactor() {
+ return 0.95F;
+ }
+
+ /**
+ * Called when this EntityFireball hits a block or entity.
+ */
+ protected abstract void onImpact(MovingObjectPosition var1);
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ par1NBTTagCompound.setShort("xTile", (short) this.xTile);
+ par1NBTTagCompound.setShort("yTile", (short) this.yTile);
+ par1NBTTagCompound.setShort("zTile", (short) this.zTile);
+ par1NBTTagCompound.setByte("inTile", (byte) this.inTile);
+ par1NBTTagCompound.setByte("inGround", (byte) (this.inGround ? 1 : 0));
+ par1NBTTagCompound.setTag("direction",
+ this.newDoubleNBTList(new double[] { this.motionX, this.motionY, this.motionZ }));
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ this.xTile = par1NBTTagCompound.getShort("xTile");
+ this.yTile = par1NBTTagCompound.getShort("yTile");
+ this.zTile = par1NBTTagCompound.getShort("zTile");
+ this.inTile = par1NBTTagCompound.getByte("inTile") & 255;
+ this.inGround = par1NBTTagCompound.getByte("inGround") == 1;
+
+ if (par1NBTTagCompound.hasKey("direction")) {
+ NBTTagList var2 = par1NBTTagCompound.getTagList("direction");
+ this.motionX = ((NBTTagDouble) var2.tagAt(0)).data;
+ this.motionY = ((NBTTagDouble) var2.tagAt(1)).data;
+ this.motionZ = ((NBTTagDouble) var2.tagAt(2)).data;
+ } else {
+ this.setDead();
+ }
+ }
+
+ /**
+ * Returns true if other Entities should be prevented from moving through this
+ * Entity.
+ */
+ public boolean canBeCollidedWith() {
+ return true;
+ }
+
+ public float getCollisionBorderSize() {
+ return 1.0F;
+ }
+
+ /**
+ * Called when the entity is attacked.
+ */
+ public boolean attackEntityFrom(DamageSource par1DamageSource, int par2) {
+ if (this.isEntityInvulnerable()) {
+ return false;
+ } else {
+ this.setBeenAttacked();
+
+ if (par1DamageSource.getEntity() != null) {
+ Vec3 var3 = par1DamageSource.getEntity().getLookVec();
+
+ if (var3 != null) {
+ this.motionX = var3.xCoord;
+ this.motionY = var3.yCoord;
+ this.motionZ = var3.zCoord;
+ this.accelerationX = this.motionX * 0.1D;
+ this.accelerationY = this.motionY * 0.1D;
+ this.accelerationZ = this.motionZ * 0.1D;
+ }
+
+ if (par1DamageSource.getEntity() instanceof EntityLiving) {
+ this.shootingEntity = (EntityLiving) par1DamageSource.getEntity();
+ }
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+
+ /**
+ * Gets how bright this entity is.
+ */
+ public float getBrightness(float par1) {
+ return 1.0F;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityFireworkRocket.java b/sp-server/src/main/java/net/minecraft/src/EntityFireworkRocket.java
new file mode 100644
index 0000000..f102cd8
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityFireworkRocket.java
@@ -0,0 +1,143 @@
+package net.minecraft.src;
+
+public class EntityFireworkRocket extends Entity {
+ /** The age of the firework in ticks. */
+ private int fireworkAge;
+
+ /**
+ * The lifetime of the firework in ticks. When the age reaches the lifetime the
+ * firework explodes.
+ */
+ private int lifetime;
+
+ public EntityFireworkRocket(World par1World) {
+ super(par1World);
+ this.setSize(0.25F, 0.25F);
+ }
+
+ protected void entityInit() {
+ this.dataWatcher.addObjectByDataType(8, 5);
+ }
+
+ public EntityFireworkRocket(World par1World, double par2, double par4, double par6, ItemStack par8ItemStack) {
+ super(par1World);
+ this.fireworkAge = 0;
+ this.setSize(0.25F, 0.25F);
+ this.setPosition(par2, par4, par6);
+ this.yOffset = 0.0F;
+ int var9 = 1;
+
+ if (par8ItemStack != null && par8ItemStack.hasTagCompound()) {
+ this.dataWatcher.updateObject(8, par8ItemStack);
+ NBTTagCompound var10 = par8ItemStack.getTagCompound();
+ NBTTagCompound var11 = var10.getCompoundTag("Fireworks");
+
+ if (var11 != null) {
+ var9 += var11.getByte("Flight");
+ }
+ }
+
+ this.motionX = this.rand.nextGaussian() * 0.001D;
+ this.motionZ = this.rand.nextGaussian() * 0.001D;
+ this.motionY = 0.05D;
+ this.lifetime = 10 * var9 + this.rand.nextInt(6) + this.rand.nextInt(7);
+ }
+
+ /**
+ * Called to update the entity's position/logic.
+ */
+ public void onUpdate() {
+ this.lastTickPosX = this.posX;
+ this.lastTickPosY = this.posY;
+ this.lastTickPosZ = this.posZ;
+ super.onUpdate();
+ this.motionX *= 1.15D;
+ this.motionZ *= 1.15D;
+ this.motionY += 0.04D;
+ this.moveEntity(this.motionX, this.motionY, this.motionZ);
+ float var1 = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ);
+ this.rotationYaw = (float) (Math.atan2(this.motionX, this.motionZ) * 180.0D / Math.PI);
+
+ for (this.rotationPitch = (float) (Math.atan2(this.motionY, (double) var1) * 180.0D
+ / Math.PI); this.rotationPitch - this.prevRotationPitch < -180.0F; this.prevRotationPitch -= 360.0F) {
+ ;
+ }
+
+ while (this.rotationPitch - this.prevRotationPitch >= 180.0F) {
+ this.prevRotationPitch += 360.0F;
+ }
+
+ while (this.rotationYaw - this.prevRotationYaw < -180.0F) {
+ this.prevRotationYaw -= 360.0F;
+ }
+
+ while (this.rotationYaw - this.prevRotationYaw >= 180.0F) {
+ this.prevRotationYaw += 360.0F;
+ }
+
+ this.rotationPitch = this.prevRotationPitch + (this.rotationPitch - this.prevRotationPitch) * 0.2F;
+ this.rotationYaw = this.prevRotationYaw + (this.rotationYaw - this.prevRotationYaw) * 0.2F;
+
+ if (this.fireworkAge == 0) {
+ this.worldObj.playSoundAtEntity(this, "fireworks.launch", 3.0F, 1.0F);
+ }
+
+ ++this.fireworkAge;
+
+ if (this.worldObj.isRemote && this.fireworkAge % 2 < 2) {
+ this.worldObj.spawnParticle("fireworksSpark", this.posX, this.posY - 0.3D, this.posZ,
+ this.rand.nextGaussian() * 0.05D, -this.motionY * 0.5D, this.rand.nextGaussian() * 0.05D);
+ }
+
+ if (!this.worldObj.isRemote && this.fireworkAge > this.lifetime) {
+ this.worldObj.setEntityState(this, (byte) 17);
+ this.setDead();
+ }
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ par1NBTTagCompound.setInteger("Life", this.fireworkAge);
+ par1NBTTagCompound.setInteger("LifeTime", this.lifetime);
+ ItemStack var2 = this.dataWatcher.getWatchableObjectItemStack(8);
+
+ if (var2 != null) {
+ NBTTagCompound var3 = new NBTTagCompound();
+ var2.writeToNBT(var3);
+ par1NBTTagCompound.setCompoundTag("FireworksItem", var3);
+ }
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ this.fireworkAge = par1NBTTagCompound.getInteger("Life");
+ this.lifetime = par1NBTTagCompound.getInteger("LifeTime");
+ NBTTagCompound var2 = par1NBTTagCompound.getCompoundTag("FireworksItem");
+
+ if (var2 != null) {
+ ItemStack var3 = ItemStack.loadItemStackFromNBT(var2);
+
+ if (var3 != null) {
+ this.dataWatcher.updateObject(8, var3);
+ }
+ }
+ }
+
+ /**
+ * Gets how bright this entity is.
+ */
+ public float getBrightness(float par1) {
+ return super.getBrightness(par1);
+ }
+
+ /**
+ * If returns false, the item will not inflict any damage against entities.
+ */
+ public boolean canAttackWithItem() {
+ return false;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityFishHook.java b/sp-server/src/main/java/net/minecraft/src/EntityFishHook.java
new file mode 100644
index 0000000..435608b
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityFishHook.java
@@ -0,0 +1,392 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+public class EntityFishHook extends Entity {
+ /** The tile this entity is on, X position */
+ private int xTile = -1;
+
+ /** The tile this entity is on, Y position */
+ private int yTile = -1;
+
+ /** The tile this entity is on, Z position */
+ private int zTile = -1;
+ private int inTile = 0;
+ private boolean inGround = false;
+ public int shake = 0;
+ public EntityPlayer angler;
+ private int ticksInGround;
+ private int ticksInAir = 0;
+
+ /** the number of ticks remaining until this fish can no longer be caught */
+ private int ticksCatchable = 0;
+
+ /** the bobber that the fish hit */
+ public Entity bobber = null;
+ private int fishPosRotationIncrements;
+ private double fishX;
+ private double fishY;
+ private double fishZ;
+ private double fishYaw;
+ private double fishPitch;
+
+ public EntityFishHook(World par1World) {
+ super(par1World);
+ this.setSize(0.25F, 0.25F);
+ this.ignoreFrustumCheck = true;
+ }
+
+ public EntityFishHook(World par1World, EntityPlayer par2EntityPlayer) {
+ super(par1World);
+ this.ignoreFrustumCheck = true;
+ this.angler = par2EntityPlayer;
+ this.angler.fishEntity = this;
+ this.setSize(0.25F, 0.25F);
+ this.setLocationAndAngles(par2EntityPlayer.posX,
+ par2EntityPlayer.posY + 1.62D - (double) par2EntityPlayer.yOffset, par2EntityPlayer.posZ,
+ par2EntityPlayer.rotationYaw, par2EntityPlayer.rotationPitch);
+ this.posX -= (double) (MathHelper.cos(this.rotationYaw / 180.0F * (float) Math.PI) * 0.16F);
+ this.posY -= 0.10000000149011612D;
+ this.posZ -= (double) (MathHelper.sin(this.rotationYaw / 180.0F * (float) Math.PI) * 0.16F);
+ this.setPosition(this.posX, this.posY, this.posZ);
+ this.yOffset = 0.0F;
+ float var3 = 0.4F;
+ this.motionX = (double) (-MathHelper.sin(this.rotationYaw / 180.0F * (float) Math.PI)
+ * MathHelper.cos(this.rotationPitch / 180.0F * (float) Math.PI) * var3);
+ this.motionZ = (double) (MathHelper.cos(this.rotationYaw / 180.0F * (float) Math.PI)
+ * MathHelper.cos(this.rotationPitch / 180.0F * (float) Math.PI) * var3);
+ this.motionY = (double) (-MathHelper.sin(this.rotationPitch / 180.0F * (float) Math.PI) * var3);
+ this.calculateVelocity(this.motionX, this.motionY, this.motionZ, 1.5F, 1.0F);
+ }
+
+ protected void entityInit() {
+ }
+
+ public void calculateVelocity(double par1, double par3, double par5, float par7, float par8) {
+ float var9 = MathHelper.sqrt_double(par1 * par1 + par3 * par3 + par5 * par5);
+ par1 /= (double) var9;
+ par3 /= (double) var9;
+ par5 /= (double) var9;
+ par1 += this.rand.nextGaussian() * 0.007499999832361937D * (double) par8;
+ par3 += this.rand.nextGaussian() * 0.007499999832361937D * (double) par8;
+ par5 += this.rand.nextGaussian() * 0.007499999832361937D * (double) par8;
+ par1 *= (double) par7;
+ par3 *= (double) par7;
+ par5 *= (double) par7;
+ this.motionX = par1;
+ this.motionY = par3;
+ this.motionZ = par5;
+ float var10 = MathHelper.sqrt_double(par1 * par1 + par5 * par5);
+ this.prevRotationYaw = this.rotationYaw = (float) (Math.atan2(par1, par5) * 180.0D / Math.PI);
+ this.prevRotationPitch = this.rotationPitch = (float) (Math.atan2(par3, (double) var10) * 180.0D / Math.PI);
+ this.ticksInGround = 0;
+ }
+
+ /**
+ * Called to update the entity's position/logic.
+ */
+ public void onUpdate() {
+ super.onUpdate();
+
+ if (this.fishPosRotationIncrements > 0) {
+ double var21 = this.posX + (this.fishX - this.posX) / (double) this.fishPosRotationIncrements;
+ double var22 = this.posY + (this.fishY - this.posY) / (double) this.fishPosRotationIncrements;
+ double var23 = this.posZ + (this.fishZ - this.posZ) / (double) this.fishPosRotationIncrements;
+ double var7 = MathHelper.wrapAngleTo180_double(this.fishYaw - (double) this.rotationYaw);
+ this.rotationYaw = (float) ((double) this.rotationYaw + var7 / (double) this.fishPosRotationIncrements);
+ this.rotationPitch = (float) ((double) this.rotationPitch
+ + (this.fishPitch - (double) this.rotationPitch) / (double) this.fishPosRotationIncrements);
+ --this.fishPosRotationIncrements;
+ this.setPosition(var21, var22, var23);
+ this.setRotation(this.rotationYaw, this.rotationPitch);
+ } else {
+ if (!this.worldObj.isRemote) {
+ ItemStack var1 = this.angler.getCurrentEquippedItem();
+
+ if (this.angler.isDead || !this.angler.isEntityAlive() || var1 == null
+ || var1.getItem() != Item.fishingRod || this.getDistanceSqToEntity(this.angler) > 1024.0D) {
+ this.setDead();
+ this.angler.fishEntity = null;
+ return;
+ }
+
+ if (this.bobber != null) {
+ if (!this.bobber.isDead) {
+ this.posX = this.bobber.posX;
+ this.posY = this.bobber.boundingBox.minY + (double) this.bobber.height * 0.8D;
+ this.posZ = this.bobber.posZ;
+ return;
+ }
+
+ this.bobber = null;
+ }
+ }
+
+ if (this.shake > 0) {
+ --this.shake;
+ }
+
+ if (this.inGround) {
+ int var19 = this.worldObj.getBlockId(this.xTile, this.yTile, this.zTile);
+
+ if (var19 == this.inTile) {
+ ++this.ticksInGround;
+
+ if (this.ticksInGround == 1200) {
+ this.setDead();
+ }
+
+ return;
+ }
+
+ this.inGround = false;
+ this.motionX *= (double) (this.rand.nextFloat() * 0.2F);
+ this.motionY *= (double) (this.rand.nextFloat() * 0.2F);
+ this.motionZ *= (double) (this.rand.nextFloat() * 0.2F);
+ this.ticksInGround = 0;
+ this.ticksInAir = 0;
+ } else {
+ ++this.ticksInAir;
+ }
+
+ Vec3 var20 = this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX, this.posY, this.posZ);
+ Vec3 var2 = this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX + this.motionX,
+ this.posY + this.motionY, this.posZ + this.motionZ);
+ MovingObjectPosition var3 = this.worldObj.rayTraceBlocks(var20, var2);
+ var20 = this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX, this.posY, this.posZ);
+ var2 = this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX + this.motionX, this.posY + this.motionY,
+ this.posZ + this.motionZ);
+
+ if (var3 != null) {
+ var2 = this.worldObj.getWorldVec3Pool().getVecFromPool(var3.hitVec.xCoord, var3.hitVec.yCoord,
+ var3.hitVec.zCoord);
+ }
+
+ Entity var4 = null;
+ List var5 = this.worldObj.getEntitiesWithinAABBExcludingEntity(this,
+ this.boundingBox.addCoord(this.motionX, this.motionY, this.motionZ).expand(1.0D, 1.0D, 1.0D));
+ double var6 = 0.0D;
+ double var13;
+
+ for (int var8 = 0; var8 < var5.size(); ++var8) {
+ Entity var9 = (Entity) var5.get(var8);
+
+ if (var9.canBeCollidedWith() && (var9 != this.angler || this.ticksInAir >= 5)) {
+ float var10 = 0.3F;
+ AxisAlignedBB var11 = var9.boundingBox.expand((double) var10, (double) var10, (double) var10);
+ MovingObjectPosition var12 = var11.calculateIntercept(var20, var2);
+
+ if (var12 != null) {
+ var13 = var20.distanceTo(var12.hitVec);
+
+ if (var13 < var6 || var6 == 0.0D) {
+ var4 = var9;
+ var6 = var13;
+ }
+ }
+ }
+ }
+
+ if (var4 != null) {
+ var3 = new MovingObjectPosition(var4);
+ }
+
+ if (var3 != null) {
+ if (var3.entityHit != null) {
+ if (var3.entityHit.attackEntityFrom(DamageSource.causeThrownDamage(this, this.angler), 0)) {
+ this.bobber = var3.entityHit;
+ }
+ } else {
+ this.inGround = true;
+ }
+ }
+
+ if (!this.inGround) {
+ this.moveEntity(this.motionX, this.motionY, this.motionZ);
+ float var24 = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ);
+ this.rotationYaw = (float) (Math.atan2(this.motionX, this.motionZ) * 180.0D / Math.PI);
+
+ for (this.rotationPitch = (float) (Math.atan2(this.motionY, (double) var24) * 180.0D
+ / Math.PI); this.rotationPitch
+ - this.prevRotationPitch < -180.0F; this.prevRotationPitch -= 360.0F) {
+ ;
+ }
+
+ while (this.rotationPitch - this.prevRotationPitch >= 180.0F) {
+ this.prevRotationPitch += 360.0F;
+ }
+
+ while (this.rotationYaw - this.prevRotationYaw < -180.0F) {
+ this.prevRotationYaw -= 360.0F;
+ }
+
+ while (this.rotationYaw - this.prevRotationYaw >= 180.0F) {
+ this.prevRotationYaw += 360.0F;
+ }
+
+ this.rotationPitch = this.prevRotationPitch + (this.rotationPitch - this.prevRotationPitch) * 0.2F;
+ this.rotationYaw = this.prevRotationYaw + (this.rotationYaw - this.prevRotationYaw) * 0.2F;
+ float var25 = 0.92F;
+
+ if (this.onGround || this.isCollidedHorizontally) {
+ var25 = 0.5F;
+ }
+
+ byte var26 = 5;
+ double var27 = 0.0D;
+
+ for (int var28 = 0; var28 < var26; ++var28) {
+ double var14 = this.boundingBox.minY
+ + (this.boundingBox.maxY - this.boundingBox.minY) * (double) (var28 + 0) / (double) var26
+ - 0.125D + 0.125D;
+ double var16 = this.boundingBox.minY
+ + (this.boundingBox.maxY - this.boundingBox.minY) * (double) (var28 + 1) / (double) var26
+ - 0.125D + 0.125D;
+ AxisAlignedBB var18 = AxisAlignedBB.getAABBPool().getAABB(this.boundingBox.minX, var14,
+ this.boundingBox.minZ, this.boundingBox.maxX, var16, this.boundingBox.maxZ);
+
+ if (this.worldObj.isAABBInMaterial(var18, Material.water)) {
+ var27 += 1.0D / (double) var26;
+ }
+ }
+
+ if (var27 > 0.0D) {
+ if (this.ticksCatchable > 0) {
+ --this.ticksCatchable;
+ } else {
+ short var29 = 500;
+
+ if (this.worldObj.canLightningStrikeAt(MathHelper.floor_double(this.posX),
+ MathHelper.floor_double(this.posY) + 1, MathHelper.floor_double(this.posZ))) {
+ var29 = 300;
+ }
+
+ if (this.rand.nextInt(var29) == 0) {
+ this.ticksCatchable = this.rand.nextInt(30) + 10;
+ this.motionY -= 0.20000000298023224D;
+ this.playSound("random.splash", 0.25F,
+ 1.0F + (this.rand.nextFloat() - this.rand.nextFloat()) * 0.4F);
+ float var30 = (float) MathHelper.floor_double(this.boundingBox.minY);
+ int var15;
+ float var17;
+ float var31;
+
+ for (var15 = 0; (float) var15 < 1.0F + this.width * 20.0F; ++var15) {
+ var31 = (this.rand.nextFloat() * 2.0F - 1.0F) * this.width;
+ var17 = (this.rand.nextFloat() * 2.0F - 1.0F) * this.width;
+ this.worldObj.spawnParticle("bubble", this.posX + (double) var31,
+ (double) (var30 + 1.0F), this.posZ + (double) var17, this.motionX,
+ this.motionY - (double) (this.rand.nextFloat() * 0.2F), this.motionZ);
+ }
+
+ for (var15 = 0; (float) var15 < 1.0F + this.width * 20.0F; ++var15) {
+ var31 = (this.rand.nextFloat() * 2.0F - 1.0F) * this.width;
+ var17 = (this.rand.nextFloat() * 2.0F - 1.0F) * this.width;
+ this.worldObj.spawnParticle("splash", this.posX + (double) var31,
+ (double) (var30 + 1.0F), this.posZ + (double) var17, this.motionX, this.motionY,
+ this.motionZ);
+ }
+ }
+ }
+ }
+
+ if (this.ticksCatchable > 0) {
+ this.motionY -= (double) (this.rand.nextFloat() * this.rand.nextFloat() * this.rand.nextFloat())
+ * 0.2D;
+ }
+
+ var13 = var27 * 2.0D - 1.0D;
+ this.motionY += 0.03999999910593033D * var13;
+
+ if (var27 > 0.0D) {
+ var25 = (float) ((double) var25 * 0.9D);
+ this.motionY *= 0.8D;
+ }
+
+ this.motionX *= (double) var25;
+ this.motionY *= (double) var25;
+ this.motionZ *= (double) var25;
+ this.setPosition(this.posX, this.posY, this.posZ);
+ }
+ }
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ par1NBTTagCompound.setShort("xTile", (short) this.xTile);
+ par1NBTTagCompound.setShort("yTile", (short) this.yTile);
+ par1NBTTagCompound.setShort("zTile", (short) this.zTile);
+ par1NBTTagCompound.setByte("inTile", (byte) this.inTile);
+ par1NBTTagCompound.setByte("shake", (byte) this.shake);
+ par1NBTTagCompound.setByte("inGround", (byte) (this.inGround ? 1 : 0));
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ this.xTile = par1NBTTagCompound.getShort("xTile");
+ this.yTile = par1NBTTagCompound.getShort("yTile");
+ this.zTile = par1NBTTagCompound.getShort("zTile");
+ this.inTile = par1NBTTagCompound.getByte("inTile") & 255;
+ this.shake = par1NBTTagCompound.getByte("shake") & 255;
+ this.inGround = par1NBTTagCompound.getByte("inGround") == 1;
+ }
+
+ public int catchFish() {
+ if (this.worldObj.isRemote) {
+ return 0;
+ } else {
+ byte var1 = 0;
+
+ if (this.bobber != null) {
+ double var2 = this.angler.posX - this.posX;
+ double var4 = this.angler.posY - this.posY;
+ double var6 = this.angler.posZ - this.posZ;
+ double var8 = (double) MathHelper.sqrt_double(var2 * var2 + var4 * var4 + var6 * var6);
+ double var10 = 0.1D;
+ this.bobber.motionX += var2 * var10;
+ this.bobber.motionY += var4 * var10 + (double) MathHelper.sqrt_double(var8) * 0.08D;
+ this.bobber.motionZ += var6 * var10;
+ var1 = 3;
+ } else if (this.ticksCatchable > 0) {
+ EntityItem var13 = new EntityItem(this.worldObj, this.posX, this.posY, this.posZ,
+ new ItemStack(Item.fishRaw));
+ double var3 = this.angler.posX - this.posX;
+ double var5 = this.angler.posY - this.posY;
+ double var7 = this.angler.posZ - this.posZ;
+ double var9 = (double) MathHelper.sqrt_double(var3 * var3 + var5 * var5 + var7 * var7);
+ double var11 = 0.1D;
+ var13.motionX = var3 * var11;
+ var13.motionY = var5 * var11 + (double) MathHelper.sqrt_double(var9) * 0.08D;
+ var13.motionZ = var7 * var11;
+ this.worldObj.spawnEntityInWorld(var13);
+ this.angler.addStat(StatList.fishCaughtStat, 1);
+ this.angler.worldObj.spawnEntityInWorld(new EntityXPOrb(this.angler.worldObj, this.angler.posX,
+ this.angler.posY + 0.5D, this.angler.posZ + 0.5D, this.rand.nextInt(6) + 1));
+ var1 = 1;
+ }
+
+ if (this.inGround) {
+ var1 = 2;
+ }
+
+ this.setDead();
+ this.angler.fishEntity = null;
+ return var1;
+ }
+ }
+
+ /**
+ * Will get destroyed next tick.
+ */
+ public void setDead() {
+ super.setDead();
+
+ if (this.angler != null) {
+ this.angler.fishEntity = null;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityFlying.java b/sp-server/src/main/java/net/minecraft/src/EntityFlying.java
new file mode 100644
index 0000000..a5a7ab6
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityFlying.java
@@ -0,0 +1,90 @@
+package net.minecraft.src;
+
+public abstract class EntityFlying extends EntityLiving {
+ public EntityFlying(World par1World) {
+ super(par1World);
+ }
+
+ /**
+ * Called when the mob is falling. Calculates and applies fall damage.
+ */
+ protected void fall(float par1) {
+ }
+
+ /**
+ * Takes in the distance the entity has fallen this tick and whether its on the
+ * ground to update the fall distance and deal fall damage if landing on the
+ * ground. Args: distanceFallenThisTick, onGround
+ */
+ protected void updateFallState(double par1, boolean par3) {
+ }
+
+ /**
+ * Moves the entity based on the specified heading. Args: strafe, forward
+ */
+ public void moveEntityWithHeading(float par1, float par2) {
+ if (this.isInWater()) {
+ this.moveFlying(par1, par2, 0.02F);
+ this.moveEntity(this.motionX, this.motionY, this.motionZ);
+ this.motionX *= 0.800000011920929D;
+ this.motionY *= 0.800000011920929D;
+ this.motionZ *= 0.800000011920929D;
+ } else if (this.handleLavaMovement()) {
+ this.moveFlying(par1, par2, 0.02F);
+ this.moveEntity(this.motionX, this.motionY, this.motionZ);
+ this.motionX *= 0.5D;
+ this.motionY *= 0.5D;
+ this.motionZ *= 0.5D;
+ } else {
+ float var3 = 0.91F;
+
+ if (this.onGround) {
+ var3 = 0.54600006F;
+ int var4 = this.worldObj.getBlockId(MathHelper.floor_double(this.posX),
+ MathHelper.floor_double(this.boundingBox.minY) - 1, MathHelper.floor_double(this.posZ));
+
+ if (var4 > 0) {
+ var3 = Block.blocksList[var4].slipperiness * 0.91F;
+ }
+ }
+
+ float var8 = 0.16277136F / (var3 * var3 * var3);
+ this.moveFlying(par1, par2, this.onGround ? 0.1F * var8 : 0.02F);
+ var3 = 0.91F;
+
+ if (this.onGround) {
+ var3 = 0.54600006F;
+ int var5 = this.worldObj.getBlockId(MathHelper.floor_double(this.posX),
+ MathHelper.floor_double(this.boundingBox.minY) - 1, MathHelper.floor_double(this.posZ));
+
+ if (var5 > 0) {
+ var3 = Block.blocksList[var5].slipperiness * 0.91F;
+ }
+ }
+
+ this.moveEntity(this.motionX, this.motionY, this.motionZ);
+ this.motionX *= (double) var3;
+ this.motionY *= (double) var3;
+ this.motionZ *= (double) var3;
+ }
+
+ this.prevLimbYaw = this.limbYaw;
+ double var10 = this.posX - this.prevPosX;
+ double var9 = this.posZ - this.prevPosZ;
+ float var7 = MathHelper.sqrt_double(var10 * var10 + var9 * var9) * 4.0F;
+
+ if (var7 > 1.0F) {
+ var7 = 1.0F;
+ }
+
+ this.limbYaw += (var7 - this.limbYaw) * 0.4F;
+ this.limbSwing += this.limbYaw;
+ }
+
+ /**
+ * returns true if this entity is by a ladder, false otherwise
+ */
+ public boolean isOnLadder() {
+ return false;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityGhast.java b/sp-server/src/main/java/net/minecraft/src/EntityGhast.java
new file mode 100644
index 0000000..49f0dcf
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityGhast.java
@@ -0,0 +1,263 @@
+package net.minecraft.src;
+
+public class EntityGhast extends EntityFlying implements IMob {
+ public int courseChangeCooldown = 0;
+ public double waypointX;
+ public double waypointY;
+ public double waypointZ;
+ private Entity targetedEntity = null;
+
+ /** Cooldown time between target loss and new target aquirement. */
+ private int aggroCooldown = 0;
+ public int prevAttackCounter = 0;
+ public int attackCounter = 0;
+
+ /** The explosion radius of spawned fireballs. */
+ private int explosionStrength = 1;
+
+ public EntityGhast(World par1World) {
+ super(par1World);
+ this.texture = "/mob/ghast.png";
+ this.setSize(4.0F, 4.0F);
+ this.isImmuneToFire = true;
+ this.experienceValue = 5;
+ }
+
+ /**
+ * Called when the entity is attacked.
+ */
+ public boolean attackEntityFrom(DamageSource par1DamageSource, int par2) {
+ if (this.isEntityInvulnerable()) {
+ return false;
+ } else if ("fireball".equals(par1DamageSource.getDamageType())
+ && par1DamageSource.getEntity() instanceof EntityPlayer) {
+ super.attackEntityFrom(par1DamageSource, 1000);
+ ((EntityPlayer) par1DamageSource.getEntity()).triggerAchievement(AchievementList.ghast);
+ return true;
+ } else {
+ return super.attackEntityFrom(par1DamageSource, par2);
+ }
+ }
+
+ protected void entityInit() {
+ super.entityInit();
+ this.dataWatcher.addObject(16, Byte.valueOf((byte) 0));
+ }
+
+ public int getMaxHealth() {
+ return 10;
+ }
+
+ /**
+ * Called to update the entity's position/logic.
+ */
+ public void onUpdate() {
+ super.onUpdate();
+ byte var1 = this.dataWatcher.getWatchableObjectByte(16);
+ this.texture = var1 == 1 ? "/mob/ghast_fire.png" : "/mob/ghast.png";
+ }
+
+ protected void updateEntityActionState() {
+ if (!this.worldObj.isRemote && this.worldObj.difficultySetting == 0) {
+ this.setDead();
+ }
+
+ this.despawnEntity();
+ this.prevAttackCounter = this.attackCounter;
+ double var1 = this.waypointX - this.posX;
+ double var3 = this.waypointY - this.posY;
+ double var5 = this.waypointZ - this.posZ;
+ double var7 = var1 * var1 + var3 * var3 + var5 * var5;
+
+ if (var7 < 1.0D || var7 > 3600.0D) {
+ this.waypointX = this.posX + (double) ((this.rand.nextFloat() * 2.0F - 1.0F) * 16.0F);
+ this.waypointY = this.posY + (double) ((this.rand.nextFloat() * 2.0F - 1.0F) * 16.0F);
+ this.waypointZ = this.posZ + (double) ((this.rand.nextFloat() * 2.0F - 1.0F) * 16.0F);
+ }
+
+ if (this.courseChangeCooldown-- <= 0) {
+ this.courseChangeCooldown += this.rand.nextInt(5) + 2;
+ var7 = (double) MathHelper.sqrt_double(var7);
+
+ if (this.isCourseTraversable(this.waypointX, this.waypointY, this.waypointZ, var7)) {
+ this.motionX += var1 / var7 * 0.1D;
+ this.motionY += var3 / var7 * 0.1D;
+ this.motionZ += var5 / var7 * 0.1D;
+ } else {
+ this.waypointX = this.posX;
+ this.waypointY = this.posY;
+ this.waypointZ = this.posZ;
+ }
+ }
+
+ if (this.targetedEntity != null && this.targetedEntity.isDead) {
+ this.targetedEntity = null;
+ }
+
+ if (this.targetedEntity == null || this.aggroCooldown-- <= 0) {
+ this.targetedEntity = this.worldObj.getClosestVulnerablePlayerToEntity(this, 100.0D);
+
+ if (this.targetedEntity != null) {
+ this.aggroCooldown = 20;
+ }
+ }
+
+ double var9 = 64.0D;
+
+ if (this.targetedEntity != null && this.targetedEntity.getDistanceSqToEntity(this) < var9 * var9) {
+ double var11 = this.targetedEntity.posX - this.posX;
+ double var13 = this.targetedEntity.boundingBox.minY + (double) (this.targetedEntity.height / 2.0F)
+ - (this.posY + (double) (this.height / 2.0F));
+ double var15 = this.targetedEntity.posZ - this.posZ;
+ this.renderYawOffset = this.rotationYaw = -((float) Math.atan2(var11, var15)) * 180.0F / (float) Math.PI;
+
+ if (this.canEntityBeSeen(this.targetedEntity)) {
+ if (this.attackCounter == 10) {
+ this.worldObj.playAuxSFXAtEntity((EntityPlayer) null, 1007, (int) this.posX, (int) this.posY,
+ (int) this.posZ, 0);
+ }
+
+ ++this.attackCounter;
+
+ if (this.attackCounter == 20) {
+ this.worldObj.playAuxSFXAtEntity((EntityPlayer) null, 1008, (int) this.posX, (int) this.posY,
+ (int) this.posZ, 0);
+ EntityLargeFireball var17 = new EntityLargeFireball(this.worldObj, this, var11, var13, var15);
+ var17.field_92057_e = this.explosionStrength;
+ double var18 = 4.0D;
+ Vec3 var20 = this.getLook(1.0F);
+ var17.posX = this.posX + var20.xCoord * var18;
+ var17.posY = this.posY + (double) (this.height / 2.0F) + 0.5D;
+ var17.posZ = this.posZ + var20.zCoord * var18;
+ this.worldObj.spawnEntityInWorld(var17);
+ this.attackCounter = -40;
+ }
+ } else if (this.attackCounter > 0) {
+ --this.attackCounter;
+ }
+ } else {
+ this.renderYawOffset = this.rotationYaw = -((float) Math.atan2(this.motionX, this.motionZ)) * 180.0F
+ / (float) Math.PI;
+
+ if (this.attackCounter > 0) {
+ --this.attackCounter;
+ }
+ }
+
+ if (!this.worldObj.isRemote) {
+ byte var21 = this.dataWatcher.getWatchableObjectByte(16);
+ byte var12 = (byte) (this.attackCounter > 10 ? 1 : 0);
+
+ if (var21 != var12) {
+ this.dataWatcher.updateObject(16, Byte.valueOf(var12));
+ }
+ }
+ }
+
+ /**
+ * True if the ghast has an unobstructed line of travel to the waypoint.
+ */
+ private boolean isCourseTraversable(double par1, double par3, double par5, double par7) {
+ double var9 = (this.waypointX - this.posX) / par7;
+ double var11 = (this.waypointY - this.posY) / par7;
+ double var13 = (this.waypointZ - this.posZ) / par7;
+ AxisAlignedBB var15 = this.boundingBox.copy();
+
+ for (int var16 = 1; (double) var16 < par7; ++var16) {
+ var15.offset(var9, var11, var13);
+
+ if (!this.worldObj.getCollidingBoundingBoxes(this, var15).isEmpty()) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns the sound this mob makes while it's alive.
+ */
+ protected String getLivingSound() {
+ return "mob.ghast.moan";
+ }
+
+ /**
+ * Returns the sound this mob makes when it is hurt.
+ */
+ protected String getHurtSound() {
+ return "mob.ghast.scream";
+ }
+
+ /**
+ * Returns the sound this mob makes on death.
+ */
+ protected String getDeathSound() {
+ return "mob.ghast.death";
+ }
+
+ /**
+ * Returns the item ID for the item the mob drops on death.
+ */
+ protected int getDropItemId() {
+ return Item.gunpowder.itemID;
+ }
+
+ /**
+ * Drop 0-2 items of this living's type
+ */
+ protected void dropFewItems(boolean par1, int par2) {
+ int var3 = this.rand.nextInt(2) + this.rand.nextInt(1 + par2);
+ int var4;
+
+ for (var4 = 0; var4 < var3; ++var4) {
+ this.dropItem(Item.ghastTear.itemID, 1);
+ }
+
+ var3 = this.rand.nextInt(3) + this.rand.nextInt(1 + par2);
+
+ for (var4 = 0; var4 < var3; ++var4) {
+ this.dropItem(Item.gunpowder.itemID, 1);
+ }
+ }
+
+ /**
+ * Returns the volume for the sounds this mob makes.
+ */
+ protected float getSoundVolume() {
+ return 10.0F;
+ }
+
+ /**
+ * Checks if the entity's current position is a valid location to spawn this
+ * entity.
+ */
+ public boolean getCanSpawnHere() {
+ return this.rand.nextInt(20) == 0 && super.getCanSpawnHere() && this.worldObj.difficultySetting > 0;
+ }
+
+ /**
+ * Will return how many at most can spawn in a chunk at once.
+ */
+ public int getMaxSpawnedInChunk() {
+ return 1;
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ super.writeEntityToNBT(par1NBTTagCompound);
+ par1NBTTagCompound.setInteger("ExplosionPower", this.explosionStrength);
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ super.readEntityFromNBT(par1NBTTagCompound);
+
+ if (par1NBTTagCompound.hasKey("ExplosionPower")) {
+ this.explosionStrength = par1NBTTagCompound.getInteger("ExplosionPower");
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityGiantZombie.java b/sp-server/src/main/java/net/minecraft/src/EntityGiantZombie.java
new file mode 100644
index 0000000..0b5571f
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityGiantZombie.java
@@ -0,0 +1,30 @@
+package net.minecraft.src;
+
+public class EntityGiantZombie extends EntityMob {
+ public EntityGiantZombie(World par1World) {
+ super(par1World);
+ this.texture = "/mob/zombie.png";
+ this.moveSpeed = 0.5F;
+ this.yOffset *= 6.0F;
+ this.setSize(this.width * 6.0F, this.height * 6.0F);
+ }
+
+ public int getMaxHealth() {
+ return 100;
+ }
+
+ /**
+ * Takes a coordinate in and returns a weight to determine how likely this
+ * creature will try to path to the block. Args: x, y, z
+ */
+ public float getBlockPathWeight(int par1, int par2, int par3) {
+ return this.worldObj.getLightBrightness(par1, par2, par3) - 0.5F;
+ }
+
+ /**
+ * Returns the amount of damage a mob should deal.
+ */
+ public int getAttackStrength(Entity par1Entity) {
+ return 50;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityGolem.java b/sp-server/src/main/java/net/minecraft/src/EntityGolem.java
new file mode 100644
index 0000000..f5f881e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityGolem.java
@@ -0,0 +1,48 @@
+package net.minecraft.src;
+
+public abstract class EntityGolem extends EntityCreature implements IAnimals {
+ public EntityGolem(World par1World) {
+ super(par1World);
+ }
+
+ /**
+ * Called when the mob is falling. Calculates and applies fall damage.
+ */
+ protected void fall(float par1) {
+ }
+
+ /**
+ * Returns the sound this mob makes while it's alive.
+ */
+ protected String getLivingSound() {
+ return "none";
+ }
+
+ /**
+ * Returns the sound this mob makes when it is hurt.
+ */
+ protected String getHurtSound() {
+ return "none";
+ }
+
+ /**
+ * Returns the sound this mob makes on death.
+ */
+ protected String getDeathSound() {
+ return "none";
+ }
+
+ /**
+ * Get number of ticks, at least during which the living entity will be silent.
+ */
+ public int getTalkInterval() {
+ return 120;
+ }
+
+ /**
+ * Determines if an entity can be despawned, used on idle far away entities
+ */
+ protected boolean canDespawn() {
+ return false;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityHanging.java b/sp-server/src/main/java/net/minecraft/src/EntityHanging.java
new file mode 100644
index 0000000..2c28a94
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityHanging.java
@@ -0,0 +1,301 @@
+package net.minecraft.src;
+
+import java.util.Iterator;
+import java.util.List;
+
+public abstract class EntityHanging extends Entity {
+ private int tickCounter1;
+ public int hangingDirection;
+ public int xPosition;
+ public int yPosition;
+ public int zPosition;
+
+ public EntityHanging(World par1World) {
+ super(par1World);
+ this.tickCounter1 = 0;
+ this.hangingDirection = 0;
+ this.yOffset = 0.0F;
+ this.setSize(0.5F, 0.5F);
+ }
+
+ public EntityHanging(World par1World, int par2, int par3, int par4, int par5) {
+ this(par1World);
+ this.xPosition = par2;
+ this.yPosition = par3;
+ this.zPosition = par4;
+ }
+
+ protected void entityInit() {
+ }
+
+ public void setDirection(int par1) {
+ this.hangingDirection = par1;
+ this.prevRotationYaw = this.rotationYaw = (float) (par1 * 90);
+ float var2 = (float) this.func_82329_d();
+ float var3 = (float) this.func_82330_g();
+ float var4 = (float) this.func_82329_d();
+
+ if (par1 != 2 && par1 != 0) {
+ var2 = 0.5F;
+ } else {
+ var4 = 0.5F;
+ this.rotationYaw = this.prevRotationYaw = (float) (Direction.footInvisibleFaceRemap[par1] * 90);
+ }
+
+ var2 /= 32.0F;
+ var3 /= 32.0F;
+ var4 /= 32.0F;
+ float var5 = (float) this.xPosition + 0.5F;
+ float var6 = (float) this.yPosition + 0.5F;
+ float var7 = (float) this.zPosition + 0.5F;
+ float var8 = 0.5625F;
+
+ if (par1 == 2) {
+ var7 -= var8;
+ }
+
+ if (par1 == 1) {
+ var5 -= var8;
+ }
+
+ if (par1 == 0) {
+ var7 += var8;
+ }
+
+ if (par1 == 3) {
+ var5 += var8;
+ }
+
+ if (par1 == 2) {
+ var5 -= this.func_70517_b(this.func_82329_d());
+ }
+
+ if (par1 == 1) {
+ var7 += this.func_70517_b(this.func_82329_d());
+ }
+
+ if (par1 == 0) {
+ var5 += this.func_70517_b(this.func_82329_d());
+ }
+
+ if (par1 == 3) {
+ var7 -= this.func_70517_b(this.func_82329_d());
+ }
+
+ var6 += this.func_70517_b(this.func_82330_g());
+ this.setPosition((double) var5, (double) var6, (double) var7);
+ float var9 = -0.03125F;
+ this.boundingBox.setBounds((double) (var5 - var2 - var9), (double) (var6 - var3 - var9),
+ (double) (var7 - var4 - var9), (double) (var5 + var2 + var9), (double) (var6 + var3 + var9),
+ (double) (var7 + var4 + var9));
+ }
+
+ private float func_70517_b(int par1) {
+ return par1 == 32 ? 0.5F : (par1 == 64 ? 0.5F : 0.0F);
+ }
+
+ /**
+ * Called to update the entity's position/logic.
+ */
+ public void onUpdate() {
+ if (this.tickCounter1++ == 100 && !this.worldObj.isRemote) {
+ this.tickCounter1 = 0;
+
+ if (!this.isDead && !this.onValidSurface()) {
+ this.setDead();
+ this.dropItemStack();
+ }
+ }
+ }
+
+ /**
+ * checks to make sure painting can be placed there
+ */
+ public boolean onValidSurface() {
+ if (!this.worldObj.getCollidingBoundingBoxes(this, this.boundingBox).isEmpty()) {
+ return false;
+ } else {
+ int var1 = Math.max(1, this.func_82329_d() / 16);
+ int var2 = Math.max(1, this.func_82330_g() / 16);
+ int var3 = this.xPosition;
+ int var4 = this.yPosition;
+ int var5 = this.zPosition;
+
+ if (this.hangingDirection == 2) {
+ var3 = MathHelper.floor_double(this.posX - (double) ((float) this.func_82329_d() / 32.0F));
+ }
+
+ if (this.hangingDirection == 1) {
+ var5 = MathHelper.floor_double(this.posZ - (double) ((float) this.func_82329_d() / 32.0F));
+ }
+
+ if (this.hangingDirection == 0) {
+ var3 = MathHelper.floor_double(this.posX - (double) ((float) this.func_82329_d() / 32.0F));
+ }
+
+ if (this.hangingDirection == 3) {
+ var5 = MathHelper.floor_double(this.posZ - (double) ((float) this.func_82329_d() / 32.0F));
+ }
+
+ var4 = MathHelper.floor_double(this.posY - (double) ((float) this.func_82330_g() / 32.0F));
+
+ for (int var6 = 0; var6 < var1; ++var6) {
+ for (int var7 = 0; var7 < var2; ++var7) {
+ Material var8;
+
+ if (this.hangingDirection != 2 && this.hangingDirection != 0) {
+ var8 = this.worldObj.getBlockMaterial(this.xPosition, var4 + var7, var5 + var6);
+ } else {
+ var8 = this.worldObj.getBlockMaterial(var3 + var6, var4 + var7, this.zPosition);
+ }
+
+ if (!var8.isSolid()) {
+ return false;
+ }
+ }
+ }
+
+ List var9 = this.worldObj.getEntitiesWithinAABBExcludingEntity(this, this.boundingBox);
+ Iterator var10 = var9.iterator();
+ Entity var11;
+
+ do {
+ if (!var10.hasNext()) {
+ return true;
+ }
+
+ var11 = (Entity) var10.next();
+ } while (!(var11 instanceof EntityHanging));
+
+ return false;
+ }
+ }
+
+ /**
+ * Returns true if other Entities should be prevented from moving through this
+ * Entity.
+ */
+ public boolean canBeCollidedWith() {
+ return true;
+ }
+
+ public boolean func_85031_j(Entity par1Entity) {
+ return par1Entity instanceof EntityPlayer
+ ? this.attackEntityFrom(DamageSource.causePlayerDamage((EntityPlayer) par1Entity), 0)
+ : false;
+ }
+
+ /**
+ * Called when the entity is attacked.
+ */
+ public boolean attackEntityFrom(DamageSource par1DamageSource, int par2) {
+ if (this.isEntityInvulnerable()) {
+ return false;
+ } else {
+ if (!this.isDead && !this.worldObj.isRemote) {
+ this.setDead();
+ this.setBeenAttacked();
+ EntityPlayer var3 = null;
+
+ if (par1DamageSource.getEntity() instanceof EntityPlayer) {
+ var3 = (EntityPlayer) par1DamageSource.getEntity();
+ }
+
+ if (var3 != null && var3.capabilities.isCreativeMode) {
+ return true;
+ }
+
+ this.dropItemStack();
+ }
+
+ return true;
+ }
+ }
+
+ /**
+ * Tries to moves the entity by the passed in displacement. Args: x, y, z
+ */
+ public void moveEntity(double par1, double par3, double par5) {
+ if (!this.worldObj.isRemote && !this.isDead && par1 * par1 + par3 * par3 + par5 * par5 > 0.0D) {
+ this.setDead();
+ this.dropItemStack();
+ }
+ }
+
+ /**
+ * Adds to the current velocity of the entity. Args: x, y, z
+ */
+ public void addVelocity(double par1, double par3, double par5) {
+ if (!this.worldObj.isRemote && !this.isDead && par1 * par1 + par3 * par3 + par5 * par5 > 0.0D) {
+ this.setDead();
+ this.dropItemStack();
+ }
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ par1NBTTagCompound.setByte("Direction", (byte) this.hangingDirection);
+ par1NBTTagCompound.setInteger("TileX", this.xPosition);
+ par1NBTTagCompound.setInteger("TileY", this.yPosition);
+ par1NBTTagCompound.setInteger("TileZ", this.zPosition);
+
+ switch (this.hangingDirection) {
+ case 0:
+ par1NBTTagCompound.setByte("Dir", (byte) 2);
+ break;
+
+ case 1:
+ par1NBTTagCompound.setByte("Dir", (byte) 1);
+ break;
+
+ case 2:
+ par1NBTTagCompound.setByte("Dir", (byte) 0);
+ break;
+
+ case 3:
+ par1NBTTagCompound.setByte("Dir", (byte) 3);
+ }
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ if (par1NBTTagCompound.hasKey("Direction")) {
+ this.hangingDirection = par1NBTTagCompound.getByte("Direction");
+ } else {
+ switch (par1NBTTagCompound.getByte("Dir")) {
+ case 0:
+ this.hangingDirection = 2;
+ break;
+
+ case 1:
+ this.hangingDirection = 1;
+ break;
+
+ case 2:
+ this.hangingDirection = 0;
+ break;
+
+ case 3:
+ this.hangingDirection = 3;
+ }
+ }
+
+ this.xPosition = par1NBTTagCompound.getInteger("TileX");
+ this.yPosition = par1NBTTagCompound.getInteger("TileY");
+ this.zPosition = par1NBTTagCompound.getInteger("TileZ");
+ this.setDirection(this.hangingDirection);
+ }
+
+ public abstract int func_82329_d();
+
+ public abstract int func_82330_g();
+
+ /**
+ * Drop the item currently on this item frame.
+ */
+ public abstract void dropItemStack();
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityIronGolem.java b/sp-server/src/main/java/net/minecraft/src/EntityIronGolem.java
new file mode 100644
index 0000000..31a0306
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityIronGolem.java
@@ -0,0 +1,236 @@
+package net.minecraft.src;
+
+public class EntityIronGolem extends EntityGolem {
+ /** deincrements, and a distance-to-home check is done at 0 */
+ private int homeCheckTimer = 0;
+ Village villageObj = null;
+ private int attackTimer;
+ private int holdRoseTick;
+
+ public EntityIronGolem(World par1World) {
+ super(par1World);
+ this.texture = "/mob/villager_golem.png";
+ this.setSize(1.4F, 2.9F);
+ this.getNavigator().setAvoidsWater(true);
+ this.tasks.addTask(1, new EntityAIAttackOnCollide(this, 0.25F, true));
+ this.tasks.addTask(2, new EntityAIMoveTowardsTarget(this, 0.22F, 32.0F));
+ this.tasks.addTask(3, new EntityAIMoveThroughVillage(this, 0.16F, true));
+ this.tasks.addTask(4, new EntityAIMoveTwardsRestriction(this, 0.16F));
+ this.tasks.addTask(5, new EntityAILookAtVillager(this));
+ this.tasks.addTask(6, new EntityAIWander(this, 0.16F));
+ this.tasks.addTask(7, new EntityAIWatchClosest(this, EntityPlayer.class, 6.0F));
+ this.tasks.addTask(8, new EntityAILookIdle(this));
+ this.targetTasks.addTask(1, new EntityAIDefendVillage(this));
+ this.targetTasks.addTask(2, new EntityAIHurtByTarget(this, false));
+ this.targetTasks.addTask(3,
+ new EntityAINearestAttackableTarget(this, EntityLiving.class, 16.0F, 0, false, true, IMob.mobSelector));
+ }
+
+ protected void entityInit() {
+ super.entityInit();
+ this.dataWatcher.addObject(16, Byte.valueOf((byte) 0));
+ }
+
+ /**
+ * Returns true if the newer Entity AI code should be run
+ */
+ public boolean isAIEnabled() {
+ return true;
+ }
+
+ /**
+ * main AI tick function, replaces updateEntityActionState
+ */
+ protected void updateAITick() {
+ if (--this.homeCheckTimer <= 0) {
+ this.homeCheckTimer = 70 + this.rand.nextInt(50);
+ this.villageObj = this.worldObj.villageCollectionObj.findNearestVillage(MathHelper.floor_double(this.posX),
+ MathHelper.floor_double(this.posY), MathHelper.floor_double(this.posZ), 32);
+
+ if (this.villageObj == null) {
+ this.detachHome();
+ } else {
+ ChunkCoordinates var1 = this.villageObj.getCenter();
+ this.setHomeArea(var1.posX, var1.posY, var1.posZ,
+ (int) ((float) this.villageObj.getVillageRadius() * 0.6F));
+ }
+ }
+
+ super.updateAITick();
+ }
+
+ public int getMaxHealth() {
+ return 100;
+ }
+
+ /**
+ * Decrements the entity's air supply when underwater
+ */
+ protected int decreaseAirSupply(int par1) {
+ return par1;
+ }
+
+ protected void collideWithEntity(Entity par1Entity) {
+ if (par1Entity instanceof IMob && this.getRNG().nextInt(20) == 0) {
+ this.setAttackTarget((EntityLiving) par1Entity);
+ }
+
+ super.collideWithEntity(par1Entity);
+ }
+
+ /**
+ * Called frequently so the entity can update its state every tick as required.
+ * For example, zombies and skeletons use this to react to sunlight and start to
+ * burn.
+ */
+ public void onLivingUpdate() {
+ super.onLivingUpdate();
+
+ if (this.attackTimer > 0) {
+ --this.attackTimer;
+ }
+
+ if (this.holdRoseTick > 0) {
+ --this.holdRoseTick;
+ }
+
+ if (this.motionX * this.motionX + this.motionZ * this.motionZ > 2.500000277905201E-7D
+ && this.rand.nextInt(5) == 0) {
+ int var1 = MathHelper.floor_double(this.posX);
+ int var2 = MathHelper.floor_double(this.posY - 0.20000000298023224D - (double) this.yOffset);
+ int var3 = MathHelper.floor_double(this.posZ);
+ int var4 = this.worldObj.getBlockId(var1, var2, var3);
+
+ if (var4 > 0) {
+ this.worldObj.spawnParticle(
+ "tilecrack_" + var4 + "_" + this.worldObj.getBlockMetadata(var1, var2, var3),
+ this.posX + ((double) this.rand.nextFloat() - 0.5D) * (double) this.width,
+ this.boundingBox.minY + 0.1D,
+ this.posZ + ((double) this.rand.nextFloat() - 0.5D) * (double) this.width,
+ 4.0D * ((double) this.rand.nextFloat() - 0.5D), 0.5D,
+ ((double) this.rand.nextFloat() - 0.5D) * 4.0D);
+ }
+ }
+ }
+
+ /**
+ * Returns true if this entity can attack entities of the specified class.
+ */
+ public boolean canAttackClass(Class par1Class) {
+ return this.isPlayerCreated() && EntityPlayer.class.isAssignableFrom(par1Class) ? false
+ : super.canAttackClass(par1Class);
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ super.writeEntityToNBT(par1NBTTagCompound);
+ par1NBTTagCompound.setBoolean("PlayerCreated", this.isPlayerCreated());
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ super.readEntityFromNBT(par1NBTTagCompound);
+ this.setPlayerCreated(par1NBTTagCompound.getBoolean("PlayerCreated"));
+ }
+
+ public boolean attackEntityAsMob(Entity par1Entity) {
+ this.attackTimer = 10;
+ this.worldObj.setEntityState(this, (byte) 4);
+ boolean var2 = par1Entity.attackEntityFrom(DamageSource.causeMobDamage(this), 7 + this.rand.nextInt(15));
+
+ if (var2) {
+ par1Entity.motionY += 0.4000000059604645D;
+ }
+
+ this.playSound("mob.irongolem.throw", 1.0F, 1.0F);
+ return var2;
+ }
+
+ public Village getVillage() {
+ return this.villageObj;
+ }
+
+ public void setHoldingRose(boolean par1) {
+ this.holdRoseTick = par1 ? 400 : 0;
+ this.worldObj.setEntityState(this, (byte) 11);
+ }
+
+ /**
+ * Returns the sound this mob makes while it's alive.
+ */
+ protected String getLivingSound() {
+ return "none";
+ }
+
+ /**
+ * Returns the sound this mob makes when it is hurt.
+ */
+ protected String getHurtSound() {
+ return "mob.irongolem.hit";
+ }
+
+ /**
+ * Returns the sound this mob makes on death.
+ */
+ protected String getDeathSound() {
+ return "mob.irongolem.death";
+ }
+
+ /**
+ * Plays step sound at given x, y, z for the entity
+ */
+ protected void playStepSound(int par1, int par2, int par3, int par4) {
+ this.playSound("mob.irongolem.walk", 1.0F, 1.0F);
+ }
+
+ /**
+ * Drop 0-2 items of this living's type
+ */
+ protected void dropFewItems(boolean par1, int par2) {
+ int var3 = this.rand.nextInt(3);
+ int var4;
+
+ for (var4 = 0; var4 < var3; ++var4) {
+ this.dropItem(Block.plantRed.blockID, 1);
+ }
+
+ var4 = 3 + this.rand.nextInt(3);
+
+ for (int var5 = 0; var5 < var4; ++var5) {
+ this.dropItem(Item.ingotIron.itemID, 1);
+ }
+ }
+
+ public int getHoldRoseTick() {
+ return this.holdRoseTick;
+ }
+
+ public boolean isPlayerCreated() {
+ return (this.dataWatcher.getWatchableObjectByte(16) & 1) != 0;
+ }
+
+ public void setPlayerCreated(boolean par1) {
+ byte var2 = this.dataWatcher.getWatchableObjectByte(16);
+
+ if (par1) {
+ this.dataWatcher.updateObject(16, Byte.valueOf((byte) (var2 | 1)));
+ } else {
+ this.dataWatcher.updateObject(16, Byte.valueOf((byte) (var2 & -2)));
+ }
+ }
+
+ /**
+ * Called when the mob's health reaches 0.
+ */
+ public void onDeath(DamageSource par1DamageSource) {
+ if (!this.isPlayerCreated() && this.attackingPlayer != null && this.villageObj != null) {
+ this.villageObj.setReputationForPlayer(this.attackingPlayer.getCommandSenderName(), -5);
+ }
+
+ super.onDeath(par1DamageSource);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityItem.java b/sp-server/src/main/java/net/minecraft/src/EntityItem.java
new file mode 100644
index 0000000..ee07f8a
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityItem.java
@@ -0,0 +1,326 @@
+package net.minecraft.src;
+
+import java.util.Iterator;
+
+public class EntityItem extends Entity {
+ /**
+ * The age of this EntityItem (used to animate it up and down as well as expire
+ * it)
+ */
+ public int age;
+ public int delayBeforeCanPickup;
+
+ /** The health of this EntityItem. (For example, damage for tools) */
+ private int health;
+
+ /** The EntityItem's random initial float height. */
+ public float hoverStart;
+
+ public EntityItem(World par1World, double par2, double par4, double par6) {
+ super(par1World);
+ this.age = 0;
+ this.health = 5;
+ this.hoverStart = (float) (Math.random() * Math.PI * 2.0D);
+ this.setSize(0.25F, 0.25F);
+ this.yOffset = this.height / 2.0F;
+ this.setPosition(par2, par4, par6);
+ this.rotationYaw = (float) (Math.random() * 360.0D);
+ this.motionX = (double) ((float) (Math.random() * 0.20000000298023224D - 0.10000000149011612D));
+ this.motionY = 0.20000000298023224D;
+ this.motionZ = (double) ((float) (Math.random() * 0.20000000298023224D - 0.10000000149011612D));
+ }
+
+ public EntityItem(World par1World, double par2, double par4, double par6, ItemStack par8ItemStack) {
+ this(par1World, par2, par4, par6);
+ this.setEntityItemStack(par8ItemStack);
+ }
+
+ /**
+ * returns if this entity triggers Block.onEntityWalking on the blocks they walk
+ * on. used for spiders and wolves to prevent them from trampling crops
+ */
+ protected boolean canTriggerWalking() {
+ return false;
+ }
+
+ public EntityItem(World par1World) {
+ super(par1World);
+ this.age = 0;
+ this.health = 5;
+ this.hoverStart = (float) (Math.random() * Math.PI * 2.0D);
+ this.setSize(0.25F, 0.25F);
+ this.yOffset = this.height / 2.0F;
+ }
+
+ protected void entityInit() {
+ this.getDataWatcher().addObjectByDataType(10, 5);
+ }
+
+ /**
+ * Called to update the entity's position/logic.
+ */
+ public void onUpdate() {
+ super.onUpdate();
+
+ if (this.delayBeforeCanPickup > 0) {
+ --this.delayBeforeCanPickup;
+ }
+
+ this.prevPosX = this.posX;
+ this.prevPosY = this.posY;
+ this.prevPosZ = this.posZ;
+ this.motionY -= 0.03999999910593033D;
+ this.noClip = this.pushOutOfBlocks(this.posX, (this.boundingBox.minY + this.boundingBox.maxY) / 2.0D,
+ this.posZ);
+ this.moveEntity(this.motionX, this.motionY, this.motionZ);
+ boolean var1 = (int) this.prevPosX != (int) this.posX || (int) this.prevPosY != (int) this.posY
+ || (int) this.prevPosZ != (int) this.posZ;
+
+ if (var1 || this.ticksExisted % 25 == 0) {
+ if (this.worldObj.getBlockMaterial(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY),
+ MathHelper.floor_double(this.posZ)) == Material.lava) {
+ this.motionY = 0.20000000298023224D;
+ this.motionX = (double) ((this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F);
+ this.motionZ = (double) ((this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F);
+ this.playSound("random.fizz", 0.4F, 2.0F + this.rand.nextFloat() * 0.4F);
+ }
+
+ if (!this.worldObj.isRemote) {
+ this.searchForOtherItemsNearby();
+ }
+ }
+
+ float var2 = 0.98F;
+
+ if (this.onGround) {
+ var2 = 0.58800006F;
+ int var3 = this.worldObj.getBlockId(MathHelper.floor_double(this.posX),
+ MathHelper.floor_double(this.boundingBox.minY) - 1, MathHelper.floor_double(this.posZ));
+
+ if (var3 > 0) {
+ var2 = Block.blocksList[var3].slipperiness * 0.98F;
+ }
+ }
+
+ this.motionX *= (double) var2;
+ this.motionY *= 0.9800000190734863D;
+ this.motionZ *= (double) var2;
+
+ if (this.onGround) {
+ this.motionY *= -0.5D;
+ }
+
+ ++this.age;
+
+ if (!this.worldObj.isRemote && this.age >= 6000) {
+ this.setDead();
+ }
+ }
+
+ /**
+ * Looks for other itemstacks nearby and tries to stack them together
+ */
+ private void searchForOtherItemsNearby() {
+ Iterator var1 = this.worldObj.getEntitiesWithinAABB(EntityItem.class, this.boundingBox.expand(0.5D, 0.0D, 0.5D))
+ .iterator();
+
+ while (var1.hasNext()) {
+ EntityItem var2 = (EntityItem) var1.next();
+ this.combineItems(var2);
+ }
+ }
+
+ /**
+ * Tries to merge this item with the item passed as the parameter. Returns true
+ * if successful. Either this item or the other item will be removed from the
+ * world.
+ */
+ public boolean combineItems(EntityItem par1EntityItem) {
+ if (par1EntityItem == this) {
+ return false;
+ } else if (par1EntityItem.isEntityAlive() && this.isEntityAlive()) {
+ ItemStack var2 = this.getEntityItem();
+ ItemStack var3 = par1EntityItem.getEntityItem();
+
+ if (var3.getItem() != var2.getItem()) {
+ return false;
+ } else if (var3.hasTagCompound() ^ var2.hasTagCompound()) {
+ return false;
+ } else if (var3.hasTagCompound() && !var3.getTagCompound().equals(var2.getTagCompound())) {
+ return false;
+ } else if (var3.getItem().getHasSubtypes() && var3.getItemDamage() != var2.getItemDamage()) {
+ return false;
+ } else if (var3.stackSize < var2.stackSize) {
+ return par1EntityItem.combineItems(this);
+ } else if (var3.stackSize + var2.stackSize > var3.getMaxStackSize()) {
+ return false;
+ } else {
+ var3.stackSize += var2.stackSize;
+ par1EntityItem.delayBeforeCanPickup = Math.max(par1EntityItem.delayBeforeCanPickup,
+ this.delayBeforeCanPickup);
+ par1EntityItem.age = Math.min(par1EntityItem.age, this.age);
+ par1EntityItem.setEntityItemStack(var3);
+ this.setDead();
+ return true;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * sets the age of the item so that it'll despawn one minute after it has been
+ * dropped (instead of five). Used when items are dropped from players in
+ * creative mode
+ */
+ public void setAgeToCreativeDespawnTime() {
+ this.age = 4800;
+ }
+
+ /**
+ * Returns if this entity is in water and will end up adding the waters velocity
+ * to the entity
+ */
+ public boolean handleWaterMovement() {
+ return this.worldObj.handleMaterialAcceleration(this.boundingBox, Material.water, this);
+ }
+
+ /**
+ * Will deal the specified amount of damage to the entity if the entity isn't
+ * immune to fire damage. Args: amountDamage
+ */
+ protected void dealFireDamage(int par1) {
+ this.attackEntityFrom(DamageSource.inFire, par1);
+ }
+
+ /**
+ * Called when the entity is attacked.
+ */
+ public boolean attackEntityFrom(DamageSource par1DamageSource, int par2) {
+ if (this.isEntityInvulnerable()) {
+ return false;
+ } else if (this.getEntityItem() != null && this.getEntityItem().itemID == Item.netherStar.itemID
+ && par1DamageSource.isExplosion()) {
+ return false;
+ } else {
+ this.setBeenAttacked();
+ this.health -= par2;
+
+ if (this.health <= 0) {
+ this.setDead();
+ }
+
+ return false;
+ }
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ par1NBTTagCompound.setShort("Health", (short) ((byte) this.health));
+ par1NBTTagCompound.setShort("Age", (short) this.age);
+
+ if (this.getEntityItem() != null) {
+ par1NBTTagCompound.setCompoundTag("Item", this.getEntityItem().writeToNBT(new NBTTagCompound()));
+ }
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ this.health = par1NBTTagCompound.getShort("Health") & 255;
+ this.age = par1NBTTagCompound.getShort("Age");
+ NBTTagCompound var2 = par1NBTTagCompound.getCompoundTag("Item");
+ this.setEntityItemStack(ItemStack.loadItemStackFromNBT(var2));
+
+ if (this.getEntityItem() == null) {
+ this.setDead();
+ }
+ }
+
+ /**
+ * Called by a player entity when they collide with an entity
+ */
+ public void onCollideWithPlayer(EntityPlayer par1EntityPlayer) {
+ if (!this.worldObj.isRemote) {
+ ItemStack var2 = this.getEntityItem();
+ int var3 = var2.stackSize;
+
+ if (this.delayBeforeCanPickup == 0 && par1EntityPlayer.inventory.addItemStackToInventory(var2)) {
+ if (var2.itemID == Block.wood.blockID) {
+ par1EntityPlayer.triggerAchievement(AchievementList.mineWood);
+ }
+
+ if (var2.itemID == Item.leather.itemID) {
+ par1EntityPlayer.triggerAchievement(AchievementList.killCow);
+ }
+
+ if (var2.itemID == Item.diamond.itemID) {
+ par1EntityPlayer.triggerAchievement(AchievementList.diamonds);
+ }
+
+ if (var2.itemID == Item.blazeRod.itemID) {
+ par1EntityPlayer.triggerAchievement(AchievementList.blazeRod);
+ }
+
+ this.playSound("random.pop", 0.2F,
+ ((this.rand.nextFloat() - this.rand.nextFloat()) * 0.7F + 1.0F) * 2.0F);
+ par1EntityPlayer.onItemPickup(this, var3);
+
+ if (var2.stackSize <= 0) {
+ this.setDead();
+ }
+ }
+ }
+ }
+
+ /**
+ * Gets the username of the entity.
+ */
+ public String getEntityName() {
+ return StatCollector.translateToLocal("item." + this.getEntityItem().getItemName());
+ }
+
+ /**
+ * If returns false, the item will not inflict any damage against entities.
+ */
+ public boolean canAttackWithItem() {
+ return false;
+ }
+
+ public void travelToTheEnd(int par1) {
+ super.travelToTheEnd(par1);
+
+ if (!this.worldObj.isRemote) {
+ this.searchForOtherItemsNearby();
+ }
+ }
+
+ /**
+ * Returns the ItemStack corresponding to the Entity (Note: if no item exists,
+ * will log an error but still return an ItemStack containing Block.stone)
+ */
+ public ItemStack getEntityItem() {
+ ItemStack var1 = this.getDataWatcher().getWatchableObjectItemStack(10);
+
+ if (var1 == null) {
+ if (this.worldObj != null) {
+ this.worldObj.getWorldLogAgent().logSevere("Item entity " + this.entityId + " has no item?!");
+ }
+
+ return new ItemStack(Block.stone);
+ } else {
+ return var1;
+ }
+ }
+
+ /**
+ * Sets the ItemStack for this entity
+ */
+ public void setEntityItemStack(ItemStack par1ItemStack) {
+ this.getDataWatcher().updateObject(10, par1ItemStack);
+ this.getDataWatcher().setObjectWatched(10);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityItemFrame.java b/sp-server/src/main/java/net/minecraft/src/EntityItemFrame.java
new file mode 100644
index 0000000..2d40c57
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityItemFrame.java
@@ -0,0 +1,119 @@
+package net.minecraft.src;
+
+public class EntityItemFrame extends EntityHanging {
+ /** Chance for this item frame's item to drop from the frame. */
+ private float itemDropChance = 1.0F;
+
+ public EntityItemFrame(World par1World) {
+ super(par1World);
+ }
+
+ public EntityItemFrame(World par1World, int par2, int par3, int par4, int par5) {
+ super(par1World, par2, par3, par4, par5);
+ this.setDirection(par5);
+ }
+
+ protected void entityInit() {
+ this.getDataWatcher().addObjectByDataType(2, 5);
+ this.getDataWatcher().addObject(3, Byte.valueOf((byte) 0));
+ }
+
+ public int func_82329_d() {
+ return 9;
+ }
+
+ public int func_82330_g() {
+ return 9;
+ }
+
+ /**
+ * Drop the item currently on this item frame.
+ */
+ public void dropItemStack() {
+ this.entityDropItem(new ItemStack(Item.itemFrame), 0.0F);
+ ItemStack var1 = this.getDisplayedItem();
+
+ if (var1 != null && this.rand.nextFloat() < this.itemDropChance) {
+ var1 = var1.copy();
+ var1.setItemFrame((EntityItemFrame) null);
+ this.entityDropItem(var1, 0.0F);
+ }
+ }
+
+ public ItemStack getDisplayedItem() {
+ return this.getDataWatcher().getWatchableObjectItemStack(2);
+ }
+
+ public void setDisplayedItem(ItemStack par1ItemStack) {
+ par1ItemStack = par1ItemStack.copy();
+ par1ItemStack.stackSize = 1;
+ par1ItemStack.setItemFrame(this);
+ this.getDataWatcher().updateObject(2, par1ItemStack);
+ this.getDataWatcher().setObjectWatched(2);
+ }
+
+ /**
+ * Return the rotation of the item currently on this frame.
+ */
+ public int getRotation() {
+ return this.getDataWatcher().getWatchableObjectByte(3);
+ }
+
+ public void setItemRotation(int par1) {
+ this.getDataWatcher().updateObject(3, Byte.valueOf((byte) (par1 % 4)));
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ if (this.getDisplayedItem() != null) {
+ par1NBTTagCompound.setCompoundTag("Item", this.getDisplayedItem().writeToNBT(new NBTTagCompound()));
+ par1NBTTagCompound.setByte("ItemRotation", (byte) this.getRotation());
+ par1NBTTagCompound.setFloat("ItemDropChance", this.itemDropChance);
+ }
+
+ super.writeEntityToNBT(par1NBTTagCompound);
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ NBTTagCompound var2 = par1NBTTagCompound.getCompoundTag("Item");
+
+ if (var2 != null && !var2.hasNoTags()) {
+ this.setDisplayedItem(ItemStack.loadItemStackFromNBT(var2));
+ this.setItemRotation(par1NBTTagCompound.getByte("ItemRotation"));
+
+ if (par1NBTTagCompound.hasKey("ItemDropChance")) {
+ this.itemDropChance = par1NBTTagCompound.getFloat("ItemDropChance");
+ }
+ }
+
+ super.readEntityFromNBT(par1NBTTagCompound);
+ }
+
+ /**
+ * Called when a player interacts with a mob. e.g. gets milk from a cow, gets
+ * into the saddle on a pig.
+ */
+ public boolean interact(EntityPlayer par1EntityPlayer) {
+ if (this.getDisplayedItem() == null) {
+ ItemStack var2 = par1EntityPlayer.getHeldItem();
+
+ if (var2 != null && !this.worldObj.isRemote) {
+ this.setDisplayedItem(var2);
+
+ if (!par1EntityPlayer.capabilities.isCreativeMode && --var2.stackSize <= 0) {
+ par1EntityPlayer.inventory.setInventorySlotContents(par1EntityPlayer.inventory.currentItem,
+ (ItemStack) null);
+ }
+ }
+ } else if (!this.worldObj.isRemote) {
+ this.setItemRotation(this.getRotation() + 1);
+ }
+
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityJumpHelper.java b/sp-server/src/main/java/net/minecraft/src/EntityJumpHelper.java
new file mode 100644
index 0000000..3914cfe
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityJumpHelper.java
@@ -0,0 +1,22 @@
+package net.minecraft.src;
+
+public class EntityJumpHelper {
+ private EntityLiving entity;
+ private boolean isJumping = false;
+
+ public EntityJumpHelper(EntityLiving par1EntityLiving) {
+ this.entity = par1EntityLiving;
+ }
+
+ public void setJumping() {
+ this.isJumping = true;
+ }
+
+ /**
+ * Called to actually make the entity jump if isJumping is true.
+ */
+ public void doJump() {
+ this.entity.setJumping(this.isJumping);
+ this.isJumping = false;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityLargeFireball.java b/sp-server/src/main/java/net/minecraft/src/EntityLargeFireball.java
new file mode 100644
index 0000000..35f2b9e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityLargeFireball.java
@@ -0,0 +1,48 @@
+package net.minecraft.src;
+
+public class EntityLargeFireball extends EntityFireball {
+ public int field_92057_e = 1;
+
+ public EntityLargeFireball(World par1World) {
+ super(par1World);
+ }
+
+ public EntityLargeFireball(World par1World, EntityLiving par2EntityLiving, double par3, double par5, double par7) {
+ super(par1World, par2EntityLiving, par3, par5, par7);
+ }
+
+ /**
+ * Called when this EntityFireball hits a block or entity.
+ */
+ protected void onImpact(MovingObjectPosition par1MovingObjectPosition) {
+ if (!this.worldObj.isRemote) {
+ if (par1MovingObjectPosition.entityHit != null) {
+ par1MovingObjectPosition.entityHit
+ .attackEntityFrom(DamageSource.causeFireballDamage(this, this.shootingEntity), 6);
+ }
+
+ this.worldObj.newExplosion((Entity) null, this.posX, this.posY, this.posZ, (float) this.field_92057_e, true,
+ this.worldObj.getGameRules().getGameRuleBooleanValue("mobGriefing"));
+ this.setDead();
+ }
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ super.writeEntityToNBT(par1NBTTagCompound);
+ par1NBTTagCompound.setInteger("ExplosionPower", this.field_92057_e);
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ super.readEntityFromNBT(par1NBTTagCompound);
+
+ if (par1NBTTagCompound.hasKey("ExplosionPower")) {
+ this.field_92057_e = par1NBTTagCompound.getInteger("ExplosionPower");
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityLightningBolt.java b/sp-server/src/main/java/net/minecraft/src/EntityLightningBolt.java
new file mode 100644
index 0000000..95cb030
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityLightningBolt.java
@@ -0,0 +1,123 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+public class EntityLightningBolt extends EntityWeatherEffect {
+ /**
+ * Declares which state the lightning bolt is in. Whether it's in the air, hit
+ * the ground, etc.
+ */
+ private int lightningState;
+
+ /**
+ * A random long that is used to change the vertex of the lightning rendered in
+ * RenderLightningBolt
+ */
+ public long boltVertex = 0L;
+
+ /**
+ * Determines the time before the EntityLightningBolt is destroyed. It is a
+ * random integer decremented over time.
+ */
+ private int boltLivingTime;
+
+ public EntityLightningBolt(World par1World, double par2, double par4, double par6) {
+ super(par1World);
+ this.setLocationAndAngles(par2, par4, par6, 0.0F, 0.0F);
+ this.lightningState = 2;
+ this.boltVertex = this.rand.nextLong();
+ this.boltLivingTime = this.rand.nextInt(3) + 1;
+
+ if (!par1World.isRemote && par1World.difficultySetting >= 2 && par1World.doChunksNearChunkExist(
+ MathHelper.floor_double(par2), MathHelper.floor_double(par4), MathHelper.floor_double(par6), 10)) {
+ int var8 = MathHelper.floor_double(par2);
+ int var9 = MathHelper.floor_double(par4);
+ int var10 = MathHelper.floor_double(par6);
+
+ if (par1World.getBlockId(var8, var9, var10) == 0
+ && Block.fire.canPlaceBlockAt(par1World, var8, var9, var10)) {
+ par1World.setBlock(var8, var9, var10, Block.fire.blockID);
+ }
+
+ for (var8 = 0; var8 < 4; ++var8) {
+ var9 = MathHelper.floor_double(par2) + this.rand.nextInt(3) - 1;
+ var10 = MathHelper.floor_double(par4) + this.rand.nextInt(3) - 1;
+ int var11 = MathHelper.floor_double(par6) + this.rand.nextInt(3) - 1;
+
+ if (par1World.getBlockId(var9, var10, var11) == 0
+ && Block.fire.canPlaceBlockAt(par1World, var9, var10, var11)) {
+ par1World.setBlock(var9, var10, var11, Block.fire.blockID);
+ }
+ }
+ }
+ }
+
+ /**
+ * Called to update the entity's position/logic.
+ */
+ public void onUpdate() {
+ super.onUpdate();
+
+ if (this.lightningState == 2) {
+ this.worldObj.playSoundEffect(this.posX, this.posY, this.posZ, "ambient.weather.thunder", 10000.0F,
+ 0.8F + this.rand.nextFloat() * 0.2F);
+ this.worldObj.playSoundEffect(this.posX, this.posY, this.posZ, "random.explode", 2.0F,
+ 0.5F + this.rand.nextFloat() * 0.2F);
+ }
+
+ --this.lightningState;
+
+ if (this.lightningState < 0) {
+ if (this.boltLivingTime == 0) {
+ this.setDead();
+ } else if (this.lightningState < -this.rand.nextInt(10)) {
+ --this.boltLivingTime;
+ this.lightningState = 1;
+ this.boltVertex = this.rand.nextLong();
+
+ if (!this.worldObj.isRemote && this.worldObj.doChunksNearChunkExist(MathHelper.floor_double(this.posX),
+ MathHelper.floor_double(this.posY), MathHelper.floor_double(this.posZ), 10)) {
+ int var1 = MathHelper.floor_double(this.posX);
+ int var2 = MathHelper.floor_double(this.posY);
+ int var3 = MathHelper.floor_double(this.posZ);
+
+ if (this.worldObj.getBlockId(var1, var2, var3) == 0
+ && Block.fire.canPlaceBlockAt(this.worldObj, var1, var2, var3)) {
+ this.worldObj.setBlock(var1, var2, var3, Block.fire.blockID);
+ }
+ }
+ }
+ }
+
+ if (this.lightningState >= 0) {
+ if (this.worldObj.isRemote) {
+ this.worldObj.lastLightningBolt = 2;
+ } else {
+ double var6 = 3.0D;
+ List var7 = this.worldObj.getEntitiesWithinAABBExcludingEntity(this,
+ AxisAlignedBB.getAABBPool().getAABB(this.posX - var6, this.posY - var6, this.posZ - var6,
+ this.posX + var6, this.posY + 6.0D + var6, this.posZ + var6));
+
+ for (int var4 = 0; var4 < var7.size(); ++var4) {
+ Entity var5 = (Entity) var7.get(var4);
+ var5.onStruckByLightning(this);
+ }
+ }
+ }
+ }
+
+ protected void entityInit() {
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ protected void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ protected void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityList.java b/sp-server/src/main/java/net/minecraft/src/EntityList.java
new file mode 100644
index 0000000..62bbc27
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityList.java
@@ -0,0 +1,221 @@
+package net.minecraft.src;
+
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.function.Function;
+
+public class EntityList {
+ /** Provides a mapping between entity classes and a string */
+ private static Map stringToClassMapping = new HashMap();
+ private static Map stringToClassReflectMapping = new HashMap();
+
+ /** Provides a mapping between a string and an entity classes */
+ private static Map classToStringMapping = new HashMap();
+
+ /** provides a mapping between an entityID and an Entity Class */
+ private static Map IDtoClassMapping = new HashMap();
+ private static Map IDtoClassReflectMapping = new HashMap();
+
+ /** provides a mapping between an Entity Class and an entity ID */
+ private static Map classToIDMapping = new HashMap();
+
+ /** Maps entity names to their numeric identifiers */
+ private static Map stringToIDMapping = new HashMap();
+
+ /** This is a HashMap of the Creative Entity Eggs/Spawners. */
+ public static HashMap entityEggs = new LinkedHashMap();
+
+ /**
+ * adds a mapping between Entity classes and both a string representation and an
+ * ID
+ */
+ private static void addMapping(Class par0Class, Function constructor, String par1Str, int par2) {
+ stringToClassMapping.put(par1Str, constructor);
+ stringToClassReflectMapping.put(par1Str, par0Class);
+ classToStringMapping.put(par0Class, par1Str);
+ IDtoClassMapping.put(Integer.valueOf(par2), constructor);
+ IDtoClassReflectMapping.put(Integer.valueOf(par2), par0Class);
+ classToIDMapping.put(par0Class, Integer.valueOf(par2));
+ stringToIDMapping.put(par1Str, Integer.valueOf(par2));
+ }
+
+ /**
+ * Adds a entity mapping with egg info.
+ */
+ private static void addMapping(Class par0Class, Function constructor, String par1Str, int par2, int par3, int par4) {
+ addMapping(par0Class, constructor, par1Str, par2);
+ entityEggs.put(Integer.valueOf(par2), new EntityEggInfo(par2, par3, par4));
+ }
+
+ /**
+ * Create a new instance of an entity in the world by using the entity name.
+ */
+ public static Entity createEntityByName(String par0Str, World par1World) {
+ Entity var2 = null;
+
+ try {
+ Function var3 = (Function) stringToClassMapping.get(par0Str);
+
+ if (var3 != null) {
+ var2 = var3.apply(par1World);
+ }
+ } catch (Exception var4) {
+ var4.printStackTrace();
+ }
+
+ return var2;
+ }
+
+ /**
+ * create a new instance of an entity from NBT store
+ */
+ public static Entity createEntityFromNBT(NBTTagCompound par0NBTTagCompound, World par1World) {
+ Entity var2 = null;
+
+ if ("Minecart".equals(par0NBTTagCompound.getString("id"))) {
+ switch (par0NBTTagCompound.getInteger("Type")) {
+ case 0:
+ par0NBTTagCompound.setString("id", "MinecartRideable");
+ break;
+
+ case 1:
+ par0NBTTagCompound.setString("id", "MinecartChest");
+ break;
+
+ case 2:
+ par0NBTTagCompound.setString("id", "MinecartFurnace");
+ }
+
+ par0NBTTagCompound.removeTag("Type");
+ }
+
+ try {
+ Function var3 = (Function) stringToClassMapping.get(par0NBTTagCompound.getString("id"));
+
+ if (var3 != null) {
+ var2 = var3.apply(par1World);
+ }
+ } catch (Exception var4) {
+ var4.printStackTrace();
+ }
+
+ if (var2 != null) {
+ var2.readFromNBT(par0NBTTagCompound);
+ } else {
+ par1World.getWorldLogAgent().func_98236_b("Skipping Entity with id " + par0NBTTagCompound.getString("id"));
+ }
+
+ return var2;
+ }
+
+ /**
+ * Create a new instance of an entity in the world by using an entity ID.
+ */
+ public static Entity createEntityByID(int par0, World par1World) {
+ Entity var2 = null;
+
+ try {
+ Function var3 = (Function) IDtoClassMapping.get(par0);
+
+ if (var3 != null) {
+ var2 = var3.apply(par1World);
+ }
+ } catch (Exception var4) {
+ var4.printStackTrace();
+ }
+
+ if (var2 == null) {
+ par1World.getWorldLogAgent().func_98236_b("Skipping Entity with id " + par0);
+ }
+
+ return var2;
+ }
+
+ /**
+ * gets the entityID of a specific entity
+ */
+ public static int getEntityID(Entity par0Entity) {
+ Class var1 = par0Entity.getClass();
+ return classToIDMapping.containsKey(var1) ? ((Integer) classToIDMapping.get(var1)).intValue() : 0;
+ }
+
+ /**
+ * Return the class assigned to this entity ID.
+ */
+ public static Class getClassFromID(int par0) {
+ return (Class) IDtoClassReflectMapping.get(Integer.valueOf(par0));
+ }
+
+ /**
+ * Gets the string representation of a specific entity.
+ */
+ public static String getEntityString(Entity par0Entity) {
+ return (String) classToStringMapping.get(par0Entity.getClass());
+ }
+
+ /**
+ * Finds the class using IDtoClassMapping and classToStringMapping
+ */
+ public static String getStringFromID(int par0) {
+ Class var1 = getClassFromID(par0);
+ return var1 != null ? (String) classToStringMapping.get(var1) : null;
+ }
+
+ static {
+ addMapping(EntityItem.class, (w) -> new EntityItem(w), "Item", 1);
+ addMapping(EntityXPOrb.class, (w) -> new EntityXPOrb(w), "XPOrb", 2);
+ addMapping(EntityPainting.class, (w) -> new EntityPainting(w), "Painting", 9);
+ addMapping(EntityArrow.class, (w) -> new EntityArrow(w), "Arrow", 10);
+ addMapping(EntitySnowball.class, (w) -> new EntitySnowball(w), "Snowball", 11);
+ addMapping(EntityLargeFireball.class, (w) -> new EntityLargeFireball(w), "Fireball", 12);
+ addMapping(EntitySmallFireball.class, (w) -> new EntitySmallFireball(w), "SmallFireball", 13);
+ addMapping(EntityEnderPearl.class, (w) -> new EntityEnderPearl(w), "ThrownEnderpearl", 14);
+ addMapping(EntityEnderEye.class, (w) -> new EntityEnderEye(w), "EyeOfEnderSignal", 15);
+ addMapping(EntityPotion.class, (w) -> new EntityPotion(w), "ThrownPotion", 16);
+ addMapping(EntityExpBottle.class, (w) -> new EntityExpBottle(w), "ThrownExpBottle", 17);
+ addMapping(EntityItemFrame.class, (w) -> new EntityItemFrame(w), "ItemFrame", 18);
+ addMapping(EntityWitherSkull.class, (w) -> new EntityWitherSkull(w), "WitherSkull", 19);
+ addMapping(EntityTNTPrimed.class, (w) -> new EntityTNTPrimed(w), "PrimedTnt", 20);
+ addMapping(EntityFallingSand.class, (w) -> new EntityFallingSand(w), "FallingSand", 21);
+ addMapping(EntityFireworkRocket.class, (w) -> new EntityFireworkRocket(w), "FireworksRocketEntity", 22);
+ addMapping(EntityBoat.class, (w) -> new EntityBoat(w), "Boat", 41);
+ addMapping(EntityMinecartEmpty.class, (w) -> new EntityMinecartEmpty(w), "MinecartRideable", 42);
+ addMapping(EntityMinecartChest.class, (w) -> new EntityMinecartChest(w), "MinecartChest", 43);
+ addMapping(EntityMinecartFurnace.class, (w) -> new EntityMinecartFurnace(w), "MinecartFurnace", 44);
+ addMapping(EntityMinecartTNT.class, (w) -> new EntityMinecartTNT(w), "MinecartTNT", 45);
+ addMapping(EntityMinecartHopper.class, (w) -> new EntityMinecartHopper(w), "MinecartHopper", 46);
+ addMapping(EntityMinecartMobSpawner.class, (w) -> new EntityMinecartMobSpawner(w), "MinecartSpawner", 47);
+ addMapping(EntityLiving.class, null, "Mob", 48);
+ addMapping(EntityMob.class, null, "Monster", 49);
+ addMapping(EntityCreeper.class, (w) -> new EntityCreeper(w), "Creeper", 50, 894731, 0);
+ addMapping(EntitySkeleton.class, (w) -> new EntitySkeleton(w), "Skeleton", 51, 12698049, 4802889);
+ addMapping(EntitySpider.class, (w) -> new EntitySpider(w), "Spider", 52, 3419431, 11013646);
+ addMapping(EntityGiantZombie.class, (w) -> new EntityGiantZombie(w), "Giant", 53);
+ addMapping(EntityZombie.class, (w) -> new EntityZombie(w), "Zombie", 54, 44975, 7969893);
+ addMapping(EntitySlime.class, (w) -> new EntitySlime(w), "Slime", 55, 5349438, 8306542);
+ addMapping(EntityGhast.class, (w) -> new EntityGhast(w), "Ghast", 56, 16382457, 12369084);
+ addMapping(EntityPigZombie.class, (w) -> new EntityPigZombie(w), "PigZombie", 57, 15373203, 5009705);
+ addMapping(EntityEnderman.class, (w) -> new EntityEnderman(w), "Enderman", 58, 1447446, 0);
+ addMapping(EntityCaveSpider.class, (w) -> new EntityCaveSpider(w), "CaveSpider", 59, 803406, 11013646);
+ addMapping(EntitySilverfish.class, (w) -> new EntitySilverfish(w), "Silverfish", 60, 7237230, 3158064);
+ addMapping(EntityBlaze.class, (w) -> new EntityBlaze(w), "Blaze", 61, 16167425, 16775294);
+ addMapping(EntityMagmaCube.class, (w) -> new EntityMagmaCube(w), "LavaSlime", 62, 3407872, 16579584);
+ addMapping(EntityDragon.class, (w) -> new EntityDragon(w), "EnderDragon", 63);
+ addMapping(EntityWither.class, (w) -> new EntityWither(w), "WitherBoss", 64);
+ addMapping(EntityBat.class, (w) -> new EntityBat(w), "Bat", 65, 4996656, 986895);
+ addMapping(EntityWitch.class, (w) -> new EntityWitch(w), "Witch", 66, 3407872, 5349438);
+ addMapping(EntityPig.class, (w) -> new EntityPig(w), "Pig", 90, 15771042, 14377823);
+ addMapping(EntitySheep.class, (w) -> new EntitySheep(w), "Sheep", 91, 15198183, 16758197);
+ addMapping(EntityCow.class, (w) -> new EntityCow(w), "Cow", 92, 4470310, 10592673);
+ addMapping(EntityChicken.class, (w) -> new EntityChicken(w), "Chicken", 93, 10592673, 16711680);
+ addMapping(EntitySquid.class, (w) -> new EntitySquid(w), "Squid", 94, 2243405, 7375001);
+ addMapping(EntityWolf.class, (w) -> new EntityWolf(w), "Wolf", 95, 14144467, 13545366);
+ addMapping(EntityMooshroom.class, (w) -> new EntityMooshroom(w), "MushroomCow", 96, 10489616, 12040119);
+ addMapping(EntitySnowman.class, (w) -> new EntitySnowman(w), "SnowMan", 97);
+ addMapping(EntityOcelot.class, (w) -> new EntityOcelot(w), "Ozelot", 98, 15720061, 5653556);
+ addMapping(EntityIronGolem.class, (w) -> new EntityIronGolem(w), "VillagerGolem", 99);
+ addMapping(EntityVillager.class, (w) -> new EntityVillager(w), "Villager", 120, 5651507, 12422002);
+ addMapping(EntityEnderCrystal.class, (w) -> new EntityEnderCrystal(w), "EnderCrystal", 200);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityLiving.java b/sp-server/src/main/java/net/minecraft/src/EntityLiving.java
new file mode 100644
index 0000000..50ec0de
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityLiving.java
@@ -0,0 +1,2446 @@
+package net.minecraft.src;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public abstract class EntityLiving extends Entity {
+ /**
+ * An array of probabilities that determines whether a random enchantment should
+ * be added to the held item. Indexed by difficulty.
+ */
+ private static final float[] enchantmentProbability = new float[] { 0.0F, 0.0F, 0.1F, 0.2F };
+
+ /** Probability to get enchanted armor */
+ private static final float[] armorEnchantmentProbability = new float[] { 0.0F, 0.0F, 0.25F, 0.5F };
+
+ /** Probability to get armor */
+ private static final float[] armorProbability = new float[] { 0.0F, 0.0F, 0.05F, 0.07F };
+
+ /** Probability to pick up loot */
+ public static final float[] pickUpLootProability = new float[] { 0.0F, 0.1F, 0.15F, 0.45F };
+ public int maxHurtResistantTime = 20;
+ public float field_70769_ao;
+ public float field_70770_ap;
+ public float renderYawOffset = 0.0F;
+ public float prevRenderYawOffset = 0.0F;
+
+ /** Entity head rotation yaw */
+ public float rotationYawHead = 0.0F;
+
+ /** Entity head rotation yaw at previous tick */
+ public float prevRotationYawHead = 0.0F;
+ protected float field_70768_au;
+ protected float field_70766_av;
+ protected float field_70764_aw;
+ protected float field_70763_ax;
+ protected boolean field_70753_ay = true;
+
+ /** the path for the texture of this entityLiving */
+ protected String texture = "/mob/char.png";
+ protected boolean field_70740_aA = true;
+ protected float field_70741_aB = 0.0F;
+
+ /**
+ * a string holding the type of entity it is currently only implemented in
+ * entityPlayer(as 'humanoid')
+ */
+ protected String entityType = null;
+ protected float field_70743_aD = 1.0F;
+
+ /** The score value of the Mob, the amount of points the mob is worth. */
+ protected int scoreValue = 0;
+ protected float field_70745_aF = 0.0F;
+
+ /**
+ * A factor used to determine how far this entity will move each tick if it is
+ * walking on land. Adjusted by speed, and slipperiness of the current block.
+ */
+ public float landMovementFactor = 0.1F;
+
+ /**
+ * A factor used to determine how far this entity will move each tick if it is
+ * jumping or falling.
+ */
+ public float jumpMovementFactor = 0.02F;
+ public float prevSwingProgress;
+ public float swingProgress;
+ protected int health = this.getMaxHealth();
+ public int prevHealth;
+
+ /**
+ * in each step in the damage calculations, this is set to the 'carryover' that
+ * would result if someone was damaged .25 hearts (for example), and added to
+ * the damage in the next step
+ */
+ protected int carryoverDamage;
+
+ /** Number of ticks since this EntityLiving last produced its sound */
+ public int livingSoundTime;
+
+ /**
+ * The amount of time remaining this entity should act 'hurt'. (Visual
+ * appearance of red tint)
+ */
+ public int hurtTime;
+
+ /** What the hurt time was max set to last. */
+ public int maxHurtTime;
+
+ /** The yaw at which this entity was last attacked from. */
+ public float attackedAtYaw = 0.0F;
+
+ /**
+ * The amount of time remaining this entity should act 'dead', i.e. have a
+ * corpse in the world.
+ */
+ public int deathTime = 0;
+ public int attackTime = 0;
+ public float prevCameraPitch;
+ public float cameraPitch;
+
+ /**
+ * This gets set on entity death, but never used. Looks like a duplicate of
+ * isDead
+ */
+ protected boolean dead = false;
+
+ /** The experience points the Entity gives. */
+ protected int experienceValue;
+ public int field_70731_aW = -1;
+ public float field_70730_aX = (float) (Math.random() * 0.8999999761581421D + 0.10000000149011612D);
+ public float prevLimbYaw;
+ public float limbYaw;
+
+ /**
+ * Only relevant when limbYaw is not 0(the entity is moving). Influences where
+ * in its swing legs and arms currently are.
+ */
+ public float limbSwing;
+
+ /** The most recent player that has attacked this entity */
+ protected EntityPlayer attackingPlayer = null;
+
+ /**
+ * Set to 60 when hit by the player or the player's wolf, then decrements. Used
+ * to determine whether the entity should drop items on death.
+ */
+ protected int recentlyHit = 0;
+
+ /** is only being set, has no uses as of MC 1.1 */
+ private EntityLiving entityLivingToAttack = null;
+ private int revengeTimer = 0;
+ private EntityLiving lastAttackingEntity = null;
+ public int arrowHitTimer = 0;
+ protected HashMap activePotionsMap = new HashMap();
+
+ /** Whether the DataWatcher needs to be updated with the active potions */
+ private boolean potionsNeedUpdate = true;
+ private int field_70748_f;
+ private EntityLookHelper lookHelper;
+ private EntityMoveHelper moveHelper;
+
+ /** Entity jumping helper */
+ private EntityJumpHelper jumpHelper;
+ private EntityBodyHelper bodyHelper;
+ private PathNavigate navigator;
+ protected final EntityAITasks tasks;
+ protected final EntityAITasks targetTasks;
+
+ /** The active target the Task system uses for tracking */
+ private EntityLiving attackTarget;
+ private EntitySenses senses;
+ private float AIMoveSpeed;
+ private ChunkCoordinates homePosition = new ChunkCoordinates(0, 0, 0);
+
+ /** If -1 there is no maximum distance */
+ private float maximumHomeDistance = -1.0F;
+
+ /** Equipment (armor and held item) for this entity. */
+ private ItemStack[] equipment = new ItemStack[5];
+
+ /** Chances for each equipment piece from dropping when this entity dies. */
+ protected float[] equipmentDropChances = new float[5];
+
+ /** The equipment this mob was previously wearing, used for syncing. */
+ private ItemStack[] previousEquipment = new ItemStack[5];
+
+ /** Whether an arm swing is currently in progress. */
+ public boolean isSwingInProgress = false;
+ public int swingProgressInt = 0;
+
+ /** Whether this entity can pick up items from the ground. */
+ private boolean canPickUpLoot = false;
+
+ /** Whether this entity should NOT despawn. */
+ private boolean persistenceRequired = false;
+ protected final CombatTracker field_94063_bt = new CombatTracker(this);
+
+ /**
+ * The number of updates over which the new position and rotation are to be
+ * applied to the entity.
+ */
+ protected int newPosRotationIncrements;
+
+ /** The new X position to be applied to the entity. */
+ protected double newPosX;
+
+ /** The new Y position to be applied to the entity. */
+ protected double newPosY;
+
+ /** The new Z position to be applied to the entity. */
+ protected double newPosZ;
+
+ /** The new yaw rotation to be applied to the entity. */
+ protected double newRotationYaw;
+
+ /** The new yaw rotation to be applied to the entity. */
+ protected double newRotationPitch;
+ float field_70706_bo = 0.0F;
+
+ /** Amount of damage taken in last hit, in half-hearts */
+ protected int lastDamage = 0;
+
+ /** The age of this EntityLiving (used to determine when it dies) */
+ protected int entityAge = 0;
+ protected float moveStrafing;
+ protected float moveForward;
+ protected float randomYawVelocity;
+
+ /** used to check whether entity is jumping. */
+ protected boolean isJumping = false;
+ protected float defaultPitch = 0.0F;
+ protected float moveSpeed = 0.7F;
+
+ /** Number of ticks since last jump */
+ private int jumpTicks = 0;
+
+ /** This entity's current target. */
+ private Entity currentTarget;
+
+ /** How long to keep a specific target entity */
+ protected int numTicksToChaseTarget = 0;
+
+ public EntityLiving(World par1World) {
+ super(par1World);
+ this.preventEntitySpawning = true;
+ this.tasks = new EntityAITasks();
+ this.targetTasks = new EntityAITasks();
+ this.lookHelper = new EntityLookHelper(this);
+ this.moveHelper = new EntityMoveHelper(this);
+ this.jumpHelper = new EntityJumpHelper(this);
+ this.bodyHelper = new EntityBodyHelper(this);
+ this.navigator = new PathNavigate(this, par1World, (float) this.func_96121_ay());
+ this.senses = new EntitySenses(this);
+ this.field_70770_ap = (float) (Math.random() + 1.0D) * 0.01F;
+ this.setPosition(this.posX, this.posY, this.posZ);
+ this.field_70769_ao = (float) Math.random() * 12398.0F;
+ this.rotationYaw = (float) (Math.random() * Math.PI * 2.0D);
+ this.rotationYawHead = this.rotationYaw;
+
+ for (int var2 = 0; var2 < this.equipmentDropChances.length; ++var2) {
+ this.equipmentDropChances[var2] = 0.085F;
+ }
+
+ this.stepHeight = 0.5F;
+ }
+
+ protected int func_96121_ay() {
+ return 16;
+ }
+
+ public EntityLookHelper getLookHelper() {
+ return this.lookHelper;
+ }
+
+ public EntityMoveHelper getMoveHelper() {
+ return this.moveHelper;
+ }
+
+ public EntityJumpHelper getJumpHelper() {
+ return this.jumpHelper;
+ }
+
+ public PathNavigate getNavigator() {
+ return this.navigator;
+ }
+
+ /**
+ * returns the EntitySenses Object for the EntityLiving
+ */
+ public EntitySenses getEntitySenses() {
+ return this.senses;
+ }
+
+ public EaglercraftRandom getRNG() {
+ return this.rand;
+ }
+
+ public EntityLiving getAITarget() {
+ return this.entityLivingToAttack;
+ }
+
+ public EntityLiving getLastAttackingEntity() {
+ return this.lastAttackingEntity;
+ }
+
+ public void setLastAttackingEntity(Entity par1Entity) {
+ if (par1Entity instanceof EntityLiving) {
+ this.lastAttackingEntity = (EntityLiving) par1Entity;
+ }
+ }
+
+ public int getAge() {
+ return this.entityAge;
+ }
+
+ public float getRotationYawHead() {
+ return this.rotationYawHead;
+ }
+
+ /**
+ * the movespeed used for the new AI system
+ */
+ public float getAIMoveSpeed() {
+ return this.AIMoveSpeed;
+ }
+
+ /**
+ * set the movespeed used for the new AI system
+ */
+ public void setAIMoveSpeed(float par1) {
+ this.AIMoveSpeed = par1;
+ this.setMoveForward(par1);
+ }
+
+ public boolean attackEntityAsMob(Entity par1Entity) {
+ this.setLastAttackingEntity(par1Entity);
+ return false;
+ }
+
+ /**
+ * Gets the active target the Task system uses for tracking
+ */
+ public EntityLiving getAttackTarget() {
+ return this.attackTarget;
+ }
+
+ /**
+ * Sets the active target the Task system uses for tracking
+ */
+ public void setAttackTarget(EntityLiving par1EntityLiving) {
+ this.attackTarget = par1EntityLiving;
+ }
+
+ /**
+ * Returns true if this entity can attack entities of the specified class.
+ */
+ public boolean canAttackClass(Class par1Class) {
+ return EntityCreeper.class != par1Class && EntityGhast.class != par1Class;
+ }
+
+ /**
+ * This function applies the benefits of growing back wool and faster growing up
+ * to the acting entity. (This function is used in the AIEatGrass)
+ */
+ public void eatGrassBonus() {
+ }
+
+ /**
+ * Takes in the distance the entity has fallen this tick and whether its on the
+ * ground to update the fall distance and deal fall damage if landing on the
+ * ground. Args: distanceFallenThisTick, onGround
+ */
+ protected void updateFallState(double par1, boolean par3) {
+ if (!this.isInWater()) {
+ this.handleWaterMovement();
+ }
+
+ if (par3 && this.fallDistance > 0.0F) {
+ int var4 = MathHelper.floor_double(this.posX);
+ int var5 = MathHelper.floor_double(this.posY - 0.20000000298023224D - (double) this.yOffset);
+ int var6 = MathHelper.floor_double(this.posZ);
+ int var7 = this.worldObj.getBlockId(var4, var5, var6);
+
+ if (var7 == 0) {
+ int var8 = this.worldObj.blockGetRenderType(var4, var5 - 1, var6);
+
+ if (var8 == 11 || var8 == 32 || var8 == 21) {
+ var7 = this.worldObj.getBlockId(var4, var5 - 1, var6);
+ }
+ }
+
+ if (var7 > 0) {
+ Block.blocksList[var7].onFallenUpon(this.worldObj, var4, var5, var6, this, this.fallDistance);
+ }
+ }
+
+ super.updateFallState(par1, par3);
+ }
+
+ /**
+ * Returns true if entity is within home distance from current position
+ */
+ public boolean isWithinHomeDistanceCurrentPosition() {
+ return this.isWithinHomeDistance(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY),
+ MathHelper.floor_double(this.posZ));
+ }
+
+ public boolean isWithinHomeDistance(int par1, int par2, int par3) {
+ return this.maximumHomeDistance == -1.0F ? true
+ : this.homePosition.getDistanceSquared(par1, par2, par3) < this.maximumHomeDistance
+ * this.maximumHomeDistance;
+ }
+
+ public void setHomeArea(int par1, int par2, int par3, int par4) {
+ this.homePosition.set(par1, par2, par3);
+ this.maximumHomeDistance = (float) par4;
+ }
+
+ public ChunkCoordinates getHomePosition() {
+ return this.homePosition;
+ }
+
+ public float getMaximumHomeDistance() {
+ return this.maximumHomeDistance;
+ }
+
+ public void detachHome() {
+ this.maximumHomeDistance = -1.0F;
+ }
+
+ public boolean hasHome() {
+ return this.maximumHomeDistance != -1.0F;
+ }
+
+ public void setRevengeTarget(EntityLiving par1EntityLiving) {
+ this.entityLivingToAttack = par1EntityLiving;
+ this.revengeTimer = this.entityLivingToAttack != null ? 100 : 0;
+ }
+
+ protected void entityInit() {
+ this.dataWatcher.addObject(8, Integer.valueOf(this.field_70748_f));
+ this.dataWatcher.addObject(9, Byte.valueOf((byte) 0));
+ this.dataWatcher.addObject(10, Byte.valueOf((byte) 0));
+ this.dataWatcher.addObject(6, Byte.valueOf((byte) 0));
+ this.dataWatcher.addObject(5, "");
+ }
+
+ /**
+ * returns true if the entity provided in the argument can be seen. (Raytrace)
+ */
+ public boolean canEntityBeSeen(Entity par1Entity) {
+ return this.worldObj.rayTraceBlocks(
+ this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX, this.posY + (double) this.getEyeHeight(),
+ this.posZ),
+ this.worldObj.getWorldVec3Pool().getVecFromPool(par1Entity.posX,
+ par1Entity.posY + (double) par1Entity.getEyeHeight(), par1Entity.posZ)) == null;
+ }
+
+ /**
+ * Returns true if other Entities should be prevented from moving through this
+ * Entity.
+ */
+ public boolean canBeCollidedWith() {
+ return !this.isDead;
+ }
+
+ /**
+ * Returns true if this entity should push and be pushed by other entities when
+ * colliding.
+ */
+ public boolean canBePushed() {
+ return !this.isDead;
+ }
+
+ public float getEyeHeight() {
+ return this.height * 0.85F;
+ }
+
+ /**
+ * Get number of ticks, at least during which the living entity will be silent.
+ */
+ public int getTalkInterval() {
+ return 80;
+ }
+
+ /**
+ * Plays living's sound at its position
+ */
+ public void playLivingSound() {
+ String var1 = this.getLivingSound();
+
+ if (var1 != null) {
+ this.playSound(var1, this.getSoundVolume(), this.getSoundPitch());
+ }
+ }
+
+ /**
+ * Gets called every tick from main Entity class
+ */
+ public void onEntityUpdate() {
+ this.prevSwingProgress = this.swingProgress;
+ super.onEntityUpdate();
+
+ if (this.isEntityAlive() && this.rand.nextInt(1000) < this.livingSoundTime++) {
+ this.livingSoundTime = -this.getTalkInterval();
+ this.playLivingSound();
+ }
+
+ if (this.isEntityAlive() && this.isEntityInsideOpaqueBlock()) {
+ this.attackEntityFrom(DamageSource.inWall, 1);
+ }
+
+ if (this.isImmuneToFire() || this.worldObj.isRemote) {
+ this.extinguish();
+ }
+
+ boolean var1 = this instanceof EntityPlayer && ((EntityPlayer) this).capabilities.disableDamage;
+
+ if (this.isEntityAlive() && this.isInsideOfMaterial(Material.water) && !this.canBreatheUnderwater()
+ && !this.activePotionsMap.containsKey(Integer.valueOf(Potion.waterBreathing.id)) && !var1) {
+ this.setAir(this.decreaseAirSupply(this.getAir()));
+
+ if (this.getAir() == -20) {
+ this.setAir(0);
+
+ for (int var2 = 0; var2 < 8; ++var2) {
+ float var3 = this.rand.nextFloat() - this.rand.nextFloat();
+ float var4 = this.rand.nextFloat() - this.rand.nextFloat();
+ float var5 = this.rand.nextFloat() - this.rand.nextFloat();
+ this.worldObj.spawnParticle("bubble", this.posX + (double) var3, this.posY + (double) var4,
+ this.posZ + (double) var5, this.motionX, this.motionY, this.motionZ);
+ }
+
+ this.attackEntityFrom(DamageSource.drown, 2);
+ }
+
+ this.extinguish();
+ } else {
+ this.setAir(300);
+ }
+
+ this.prevCameraPitch = this.cameraPitch;
+
+ if (this.attackTime > 0) {
+ --this.attackTime;
+ }
+
+ if (this.hurtTime > 0) {
+ --this.hurtTime;
+ }
+
+ if (this.hurtResistantTime > 0) {
+ --this.hurtResistantTime;
+ }
+
+ if (this.health <= 0) {
+ this.onDeathUpdate();
+ }
+
+ if (this.recentlyHit > 0) {
+ --this.recentlyHit;
+ } else {
+ this.attackingPlayer = null;
+ }
+
+ if (this.lastAttackingEntity != null && !this.lastAttackingEntity.isEntityAlive()) {
+ this.lastAttackingEntity = null;
+ }
+
+ if (this.entityLivingToAttack != null) {
+ if (!this.entityLivingToAttack.isEntityAlive()) {
+ this.setRevengeTarget((EntityLiving) null);
+ } else if (this.revengeTimer > 0) {
+ --this.revengeTimer;
+ } else {
+ this.setRevengeTarget((EntityLiving) null);
+ }
+ }
+
+ this.updatePotionEffects();
+ this.field_70763_ax = this.field_70764_aw;
+ this.prevRenderYawOffset = this.renderYawOffset;
+ this.prevRotationYawHead = this.rotationYawHead;
+ this.prevRotationYaw = this.rotationYaw;
+ this.prevRotationPitch = this.rotationPitch;
+ }
+
+ /**
+ * handles entity death timer, experience orb and particle creation
+ */
+ protected void onDeathUpdate() {
+ ++this.deathTime;
+
+ if (this.deathTime == 20) {
+ int var1;
+
+ if (!this.worldObj.isRemote && (this.recentlyHit > 0 || this.isPlayer()) && !this.isChild()
+ && this.worldObj.getGameRules().getGameRuleBooleanValue("doMobLoot")) {
+ var1 = this.getExperiencePoints(this.attackingPlayer);
+
+ while (var1 > 0) {
+ int var2 = EntityXPOrb.getXPSplit(var1);
+ var1 -= var2;
+ this.worldObj
+ .spawnEntityInWorld(new EntityXPOrb(this.worldObj, this.posX, this.posY, this.posZ, var2));
+ }
+ }
+
+ this.setDead();
+
+ for (var1 = 0; var1 < 20; ++var1) {
+ double var8 = this.rand.nextGaussian() * 0.02D;
+ double var4 = this.rand.nextGaussian() * 0.02D;
+ double var6 = this.rand.nextGaussian() * 0.02D;
+ this.worldObj.spawnParticle("explode",
+ this.posX + (double) (this.rand.nextFloat() * this.width * 2.0F) - (double) this.width,
+ this.posY + (double) (this.rand.nextFloat() * this.height),
+ this.posZ + (double) (this.rand.nextFloat() * this.width * 2.0F) - (double) this.width, var8,
+ var4, var6);
+ }
+ }
+ }
+
+ /**
+ * Decrements the entity's air supply when underwater
+ */
+ protected int decreaseAirSupply(int par1) {
+ int var2 = EnchantmentHelper.getRespiration(this);
+ return var2 > 0 && this.rand.nextInt(var2 + 1) > 0 ? par1 : par1 - 1;
+ }
+
+ /**
+ * Get the experience points the entity currently has.
+ */
+ protected int getExperiencePoints(EntityPlayer par1EntityPlayer) {
+ if (this.experienceValue > 0) {
+ int var2 = this.experienceValue;
+ ItemStack[] var3 = this.getInventory();
+
+ for (int var4 = 0; var4 < var3.length; ++var4) {
+ if (var3[var4] != null && this.equipmentDropChances[var4] <= 1.0F) {
+ var2 += 1 + this.rand.nextInt(3);
+ }
+ }
+
+ return var2;
+ } else {
+ return this.experienceValue;
+ }
+ }
+
+ /**
+ * Only use is to identify if class is an instance of player for experience
+ * dropping
+ */
+ protected boolean isPlayer() {
+ return false;
+ }
+
+ /**
+ * Spawns an explosion particle around the Entity's location
+ */
+ public void spawnExplosionParticle() {
+ for (int var1 = 0; var1 < 20; ++var1) {
+ double var2 = this.rand.nextGaussian() * 0.02D;
+ double var4 = this.rand.nextGaussian() * 0.02D;
+ double var6 = this.rand.nextGaussian() * 0.02D;
+ double var8 = 10.0D;
+ this.worldObj.spawnParticle("explode",
+ this.posX + (double) (this.rand.nextFloat() * this.width * 2.0F) - (double) this.width
+ - var2 * var8,
+ this.posY + (double) (this.rand.nextFloat() * this.height) - var4 * var8, this.posZ
+ + (double) (this.rand.nextFloat() * this.width * 2.0F) - (double) this.width - var6 * var8,
+ var2, var4, var6);
+ }
+ }
+
+ /**
+ * Handles updating while being ridden by an entity
+ */
+ public void updateRidden() {
+ super.updateRidden();
+ this.field_70768_au = this.field_70766_av;
+ this.field_70766_av = 0.0F;
+ this.fallDistance = 0.0F;
+ }
+
+ /**
+ * Called to update the entity's position/logic.
+ */
+ public void onUpdate() {
+ super.onUpdate();
+
+ if (!this.worldObj.isRemote) {
+ int var1;
+
+ for (var1 = 0; var1 < 5; ++var1) {
+ ItemStack var2 = this.getEquipmentInSlot(var1);
+
+ if (!ItemStack.areItemStacksEqual(var2, this.previousEquipment[var1])) {
+ ((WorldServer) this.worldObj).getEntityTracker().sendPacketToTrackedPlayers(this,
+ new Packet5PlayerInventory(this.entityId, var1, var2));
+ this.previousEquipment[var1] = var2 == null ? null : var2.copy();
+ }
+ }
+
+ var1 = this.getArrowCountInEntity();
+
+ if (var1 > 0) {
+ if (this.arrowHitTimer <= 0) {
+ this.arrowHitTimer = 20 * (30 - var1);
+ }
+
+ --this.arrowHitTimer;
+
+ if (this.arrowHitTimer <= 0) {
+ this.setArrowCountInEntity(var1 - 1);
+ }
+ }
+ }
+
+ this.onLivingUpdate();
+ double var12 = this.posX - this.prevPosX;
+ double var3 = this.posZ - this.prevPosZ;
+ float var5 = (float) (var12 * var12 + var3 * var3);
+ float var6 = this.renderYawOffset;
+ float var7 = 0.0F;
+ this.field_70768_au = this.field_70766_av;
+ float var8 = 0.0F;
+
+ if (var5 > 0.0025000002F) {
+ var8 = 1.0F;
+ var7 = (float) Math.sqrt((double) var5) * 3.0F;
+ var6 = (float) Math.atan2(var3, var12) * 180.0F / (float) Math.PI - 90.0F;
+ }
+
+ if (this.swingProgress > 0.0F) {
+ var6 = this.rotationYaw;
+ }
+
+ if (!this.onGround) {
+ var8 = 0.0F;
+ }
+
+ this.field_70766_av += (var8 - this.field_70766_av) * 0.3F;
+
+ if (this.isAIEnabled()) {
+ this.bodyHelper.func_75664_a();
+ } else {
+ float var9 = MathHelper.wrapAngleTo180_float(var6 - this.renderYawOffset);
+ this.renderYawOffset += var9 * 0.3F;
+ float var10 = MathHelper.wrapAngleTo180_float(this.rotationYaw - this.renderYawOffset);
+ boolean var11 = var10 < -90.0F || var10 >= 90.0F;
+
+ if (var10 < -75.0F) {
+ var10 = -75.0F;
+ }
+
+ if (var10 >= 75.0F) {
+ var10 = 75.0F;
+ }
+
+ this.renderYawOffset = this.rotationYaw - var10;
+
+ if (var10 * var10 > 2500.0F) {
+ this.renderYawOffset += var10 * 0.2F;
+ }
+
+ if (var11) {
+ var7 *= -1.0F;
+ }
+ }
+
+ while (this.rotationYaw - this.prevRotationYaw < -180.0F) {
+ this.prevRotationYaw -= 360.0F;
+ }
+
+ while (this.rotationYaw - this.prevRotationYaw >= 180.0F) {
+ this.prevRotationYaw += 360.0F;
+ }
+
+ while (this.renderYawOffset - this.prevRenderYawOffset < -180.0F) {
+ this.prevRenderYawOffset -= 360.0F;
+ }
+
+ while (this.renderYawOffset - this.prevRenderYawOffset >= 180.0F) {
+ this.prevRenderYawOffset += 360.0F;
+ }
+
+ while (this.rotationPitch - this.prevRotationPitch < -180.0F) {
+ this.prevRotationPitch -= 360.0F;
+ }
+
+ while (this.rotationPitch - this.prevRotationPitch >= 180.0F) {
+ this.prevRotationPitch += 360.0F;
+ }
+
+ while (this.rotationYawHead - this.prevRotationYawHead < -180.0F) {
+ this.prevRotationYawHead -= 360.0F;
+ }
+
+ while (this.rotationYawHead - this.prevRotationYawHead >= 180.0F) {
+ this.prevRotationYawHead += 360.0F;
+ }
+
+ this.field_70764_aw += var7;
+ }
+
+ /**
+ * Heal living entity (param: amount of half-hearts)
+ */
+ public void heal(int par1) {
+ if (this.health > 0) {
+ this.setEntityHealth(this.getHealth() + par1);
+
+ if (this.health > this.getMaxHealth()) {
+ this.setEntityHealth(this.getMaxHealth());
+ }
+
+ this.hurtResistantTime = this.maxHurtResistantTime / 2;
+ }
+ }
+
+ public abstract int getMaxHealth();
+
+ public int getHealth() {
+ return this.health;
+ }
+
+ public void setEntityHealth(int par1) {
+ this.health = par1;
+
+ if (par1 > this.getMaxHealth()) {
+ par1 = this.getMaxHealth();
+ }
+ }
+
+ /**
+ * Called when the entity is attacked.
+ */
+ public boolean attackEntityFrom(DamageSource par1DamageSource, int par2) {
+ if (this.isEntityInvulnerable()) {
+ return false;
+ } else if (this.worldObj.isRemote) {
+ return false;
+ } else {
+ this.entityAge = 0;
+
+ if (this.health <= 0) {
+ return false;
+ } else if (par1DamageSource.isFireDamage() && this.isPotionActive(Potion.fireResistance)) {
+ return false;
+ } else {
+ if ((par1DamageSource == DamageSource.anvil || par1DamageSource == DamageSource.fallingBlock)
+ && this.getEquipmentInSlot(4) != null) {
+ this.getEquipmentInSlot(4).damageItem(par2 * 4 + this.rand.nextInt(par2 * 2), this);
+ par2 = (int) ((float) par2 * 0.75F);
+ }
+
+ this.limbYaw = 1.5F;
+ boolean var3 = true;
+
+ if ((float) this.hurtResistantTime > (float) this.maxHurtResistantTime / 2.0F) {
+ if (par2 <= this.lastDamage) {
+ return false;
+ }
+
+ this.damageEntity(par1DamageSource, par2 - this.lastDamage);
+ this.lastDamage = par2;
+ var3 = false;
+ } else {
+ this.lastDamage = par2;
+ this.prevHealth = this.health;
+ this.hurtResistantTime = this.maxHurtResistantTime;
+ this.damageEntity(par1DamageSource, par2);
+ this.hurtTime = this.maxHurtTime = 10;
+ }
+
+ this.attackedAtYaw = 0.0F;
+ Entity var4 = par1DamageSource.getEntity();
+
+ if (var4 != null) {
+ if (var4 instanceof EntityLiving) {
+ this.setRevengeTarget((EntityLiving) var4);
+ }
+
+ if (var4 instanceof EntityPlayer) {
+ this.recentlyHit = 100;
+ this.attackingPlayer = (EntityPlayer) var4;
+ } else if (var4 instanceof EntityWolf) {
+ EntityWolf var5 = (EntityWolf) var4;
+
+ if (var5.isTamed()) {
+ this.recentlyHit = 100;
+ this.attackingPlayer = null;
+ }
+ }
+ }
+
+ if (var3) {
+ this.worldObj.setEntityState(this, (byte) 2);
+
+ if (par1DamageSource != DamageSource.drown) {
+ this.setBeenAttacked();
+ }
+
+ if (var4 != null) {
+ double var9 = var4.posX - this.posX;
+ double var7;
+
+ for (var7 = var4.posZ - this.posZ; var9 * var9
+ + var7 * var7 < 1.0E-4D; var7 = (Math.random() - Math.random()) * 0.01D) {
+ var9 = (Math.random() - Math.random()) * 0.01D;
+ }
+
+ this.attackedAtYaw = (float) (Math.atan2(var7, var9) * 180.0D / Math.PI) - this.rotationYaw;
+ this.knockBack(var4, par2, var9, var7);
+ } else {
+ this.attackedAtYaw = (float) ((int) (Math.random() * 2.0D) * 180);
+ }
+ }
+
+ if (this.health <= 0) {
+ if (var3) {
+ this.playSound(this.getDeathSound(), this.getSoundVolume(), this.getSoundPitch());
+ }
+
+ this.onDeath(par1DamageSource);
+ } else if (var3) {
+ this.playSound(this.getHurtSound(), this.getSoundVolume(), this.getSoundPitch());
+ }
+
+ return true;
+ }
+ }
+ }
+
+ /**
+ * Gets the pitch of living sounds in living entities.
+ */
+ protected float getSoundPitch() {
+ return this.isChild() ? (this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F + 1.5F
+ : (this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F + 1.0F;
+ }
+
+ /**
+ * Returns the current armor value as determined by a call to
+ * InventoryPlayer.getTotalArmorValue
+ */
+ public int getTotalArmorValue() {
+ int var1 = 0;
+ ItemStack[] var2 = this.getInventory();
+ int var3 = var2.length;
+
+ for (int var4 = 0; var4 < var3; ++var4) {
+ ItemStack var5 = var2[var4];
+
+ if (var5 != null && var5.getItem() instanceof ItemArmor) {
+ int var6 = ((ItemArmor) var5.getItem()).damageReduceAmount;
+ var1 += var6;
+ }
+ }
+
+ return var1;
+ }
+
+ protected void damageArmor(int par1) {
+ }
+
+ /**
+ * Reduces damage, depending on armor
+ */
+ protected int applyArmorCalculations(DamageSource par1DamageSource, int par2) {
+ if (!par1DamageSource.isUnblockable()) {
+ int var3 = 25 - this.getTotalArmorValue();
+ int var4 = par2 * var3 + this.carryoverDamage;
+ this.damageArmor(par2);
+ par2 = var4 / 25;
+ this.carryoverDamage = var4 % 25;
+ }
+
+ return par2;
+ }
+
+ /**
+ * Reduces damage, depending on potions
+ */
+ protected int applyPotionDamageCalculations(DamageSource par1DamageSource, int par2) {
+ int var3;
+ int var4;
+ int var5;
+
+ if (this.isPotionActive(Potion.resistance)) {
+ var3 = (this.getActivePotionEffect(Potion.resistance).getAmplifier() + 1) * 5;
+ var4 = 25 - var3;
+ var5 = par2 * var4 + this.carryoverDamage;
+ par2 = var5 / 25;
+ this.carryoverDamage = var5 % 25;
+ }
+
+ if (par2 <= 0) {
+ return 0;
+ } else {
+ var3 = EnchantmentHelper.getEnchantmentModifierDamage(this.getInventory(), par1DamageSource);
+
+ if (var3 > 20) {
+ var3 = 20;
+ }
+
+ if (var3 > 0 && var3 <= 20) {
+ var4 = 25 - var3;
+ var5 = par2 * var4 + this.carryoverDamage;
+ par2 = var5 / 25;
+ this.carryoverDamage = var5 % 25;
+ }
+
+ return par2;
+ }
+ }
+
+ /**
+ * Deals damage to the entity. If its a EntityPlayer then will take damage from
+ * the armor first and then health second with the reduced value. Args:
+ * damageAmount
+ */
+ protected void damageEntity(DamageSource par1DamageSource, int par2) {
+ if (!this.isEntityInvulnerable()) {
+ par2 = this.applyArmorCalculations(par1DamageSource, par2);
+ par2 = this.applyPotionDamageCalculations(par1DamageSource, par2);
+ int var3 = this.getHealth();
+ this.health -= par2;
+ this.field_94063_bt.func_94547_a(par1DamageSource, var3, par2);
+ }
+ }
+
+ /**
+ * Returns the volume for the sounds this mob makes.
+ */
+ protected float getSoundVolume() {
+ return 1.0F;
+ }
+
+ /**
+ * Returns the sound this mob makes while it's alive.
+ */
+ protected String getLivingSound() {
+ return null;
+ }
+
+ /**
+ * Returns the sound this mob makes when it is hurt.
+ */
+ protected String getHurtSound() {
+ return "damage.hit";
+ }
+
+ /**
+ * Returns the sound this mob makes on death.
+ */
+ protected String getDeathSound() {
+ return "damage.hit";
+ }
+
+ /**
+ * knocks back this entity
+ */
+ public void knockBack(Entity par1Entity, int par2, double par3, double par5) {
+ this.isAirBorne = true;
+ float var7 = MathHelper.sqrt_double(par3 * par3 + par5 * par5);
+ float var8 = 0.4F;
+ this.motionX /= 2.0D;
+ this.motionY /= 2.0D;
+ this.motionZ /= 2.0D;
+ this.motionX -= par3 / (double) var7 * (double) var8;
+ this.motionY += (double) var8;
+ this.motionZ -= par5 / (double) var7 * (double) var8;
+
+ if (this.motionY > 0.4000000059604645D) {
+ this.motionY = 0.4000000059604645D;
+ }
+ }
+
+ /**
+ * Called when the mob's health reaches 0.
+ */
+ public void onDeath(DamageSource par1DamageSource) {
+ Entity var2 = par1DamageSource.getEntity();
+ EntityLiving var3 = this.func_94060_bK();
+
+ if (this.scoreValue >= 0 && var3 != null) {
+ var3.addToPlayerScore(this, this.scoreValue);
+ }
+
+ if (var2 != null) {
+ var2.onKillEntity(this);
+ }
+
+ this.dead = true;
+
+ if (!this.worldObj.isRemote) {
+ int var4 = 0;
+
+ if (var2 instanceof EntityPlayer) {
+ var4 = EnchantmentHelper.getLootingModifier((EntityLiving) var2);
+ }
+
+ if (!this.isChild() && this.worldObj.getGameRules().getGameRuleBooleanValue("doMobLoot")) {
+ this.dropFewItems(this.recentlyHit > 0, var4);
+ this.dropEquipment(this.recentlyHit > 0, var4);
+
+ if (this.recentlyHit > 0) {
+ int var5 = this.rand.nextInt(200) - var4;
+
+ if (var5 < 5) {
+ this.dropRareDrop(var5 <= 0 ? 1 : 0);
+ }
+ }
+ }
+ }
+
+ this.worldObj.setEntityState(this, (byte) 3);
+ }
+
+ protected void dropRareDrop(int par1) {
+ }
+
+ /**
+ * Drop 0-2 items of this living's type
+ */
+ protected void dropFewItems(boolean par1, int par2) {
+ int var3 = this.getDropItemId();
+
+ if (var3 > 0) {
+ int var4 = this.rand.nextInt(3);
+
+ if (par2 > 0) {
+ var4 += this.rand.nextInt(par2 + 1);
+ }
+
+ for (int var5 = 0; var5 < var4; ++var5) {
+ this.dropItem(var3, 1);
+ }
+ }
+ }
+
+ /**
+ * Returns the item ID for the item the mob drops on death.
+ */
+ protected int getDropItemId() {
+ return 0;
+ }
+
+ /**
+ * Called when the mob is falling. Calculates and applies fall damage.
+ */
+ protected void fall(float par1) {
+ super.fall(par1);
+ int var2 = MathHelper.ceiling_float_int(par1 - 3.0F);
+
+ if (var2 > 0) {
+ if (var2 > 4) {
+ this.playSound("damage.fallbig", 1.0F, 1.0F);
+ } else {
+ this.playSound("damage.fallsmall", 1.0F, 1.0F);
+ }
+
+ this.attackEntityFrom(DamageSource.fall, var2);
+ int var3 = this.worldObj.getBlockId(MathHelper.floor_double(this.posX),
+ MathHelper.floor_double(this.posY - 0.20000000298023224D - (double) this.yOffset),
+ MathHelper.floor_double(this.posZ));
+
+ if (var3 > 0) {
+ StepSound var4 = Block.blocksList[var3].stepSound;
+ this.playSound(var4.getStepSound(), var4.getVolume() * 0.5F, var4.getPitch() * 0.75F);
+ }
+ }
+ }
+
+ /**
+ * Moves the entity based on the specified heading. Args: strafe, forward
+ */
+ public void moveEntityWithHeading(float par1, float par2) {
+ double var9;
+
+ if (this.isInWater() && (!(this instanceof EntityPlayer) || !((EntityPlayer) this).capabilities.isFlying)) {
+ var9 = this.posY;
+ this.moveFlying(par1, par2, this.isAIEnabled() ? 0.04F : 0.02F);
+ this.moveEntity(this.motionX, this.motionY, this.motionZ);
+ this.motionX *= 0.800000011920929D;
+ this.motionY *= 0.800000011920929D;
+ this.motionZ *= 0.800000011920929D;
+ this.motionY -= 0.02D;
+
+ if (this.isCollidedHorizontally && this.isOffsetPositionInLiquid(this.motionX,
+ this.motionY + 0.6000000238418579D - this.posY + var9, this.motionZ)) {
+ this.motionY = 0.30000001192092896D;
+ }
+ } else if (this.handleLavaMovement()
+ && (!(this instanceof EntityPlayer) || !((EntityPlayer) this).capabilities.isFlying)) {
+ var9 = this.posY;
+ this.moveFlying(par1, par2, 0.02F);
+ this.moveEntity(this.motionX, this.motionY, this.motionZ);
+ this.motionX *= 0.5D;
+ this.motionY *= 0.5D;
+ this.motionZ *= 0.5D;
+ this.motionY -= 0.02D;
+
+ if (this.isCollidedHorizontally && this.isOffsetPositionInLiquid(this.motionX,
+ this.motionY + 0.6000000238418579D - this.posY + var9, this.motionZ)) {
+ this.motionY = 0.30000001192092896D;
+ }
+ } else {
+ float var3 = 0.91F;
+
+ if (this.onGround) {
+ var3 = 0.54600006F;
+ int var4 = this.worldObj.getBlockId(MathHelper.floor_double(this.posX),
+ MathHelper.floor_double(this.boundingBox.minY) - 1, MathHelper.floor_double(this.posZ));
+
+ if (var4 > 0) {
+ var3 = Block.blocksList[var4].slipperiness * 0.91F;
+ }
+ }
+
+ float var8 = 0.16277136F / (var3 * var3 * var3);
+ float var5;
+
+ if (this.onGround) {
+ if (this.isAIEnabled()) {
+ var5 = this.getAIMoveSpeed();
+ } else {
+ var5 = this.landMovementFactor;
+ }
+
+ var5 *= var8;
+ } else {
+ var5 = this.jumpMovementFactor;
+ }
+
+ this.moveFlying(par1, par2, var5);
+ var3 = 0.91F;
+
+ if (this.onGround) {
+ var3 = 0.54600006F;
+ int var6 = this.worldObj.getBlockId(MathHelper.floor_double(this.posX),
+ MathHelper.floor_double(this.boundingBox.minY) - 1, MathHelper.floor_double(this.posZ));
+
+ if (var6 > 0) {
+ var3 = Block.blocksList[var6].slipperiness * 0.91F;
+ }
+ }
+
+ if (this.isOnLadder()) {
+ float var10 = 0.15F;
+
+ if (this.motionX < (double) (-var10)) {
+ this.motionX = (double) (-var10);
+ }
+
+ if (this.motionX > (double) var10) {
+ this.motionX = (double) var10;
+ }
+
+ if (this.motionZ < (double) (-var10)) {
+ this.motionZ = (double) (-var10);
+ }
+
+ if (this.motionZ > (double) var10) {
+ this.motionZ = (double) var10;
+ }
+
+ this.fallDistance = 0.0F;
+
+ if (this.motionY < -0.15D) {
+ this.motionY = -0.15D;
+ }
+
+ boolean var7 = this.isSneaking() && this instanceof EntityPlayer;
+
+ if (var7 && this.motionY < 0.0D) {
+ this.motionY = 0.0D;
+ }
+ }
+
+ this.moveEntity(this.motionX, this.motionY, this.motionZ);
+
+ if (this.isCollidedHorizontally && this.isOnLadder()) {
+ this.motionY = 0.2D;
+ }
+
+ if (this.worldObj.isRemote && (!this.worldObj.blockExists((int) this.posX, 0, (int) this.posZ)
+ || !this.worldObj.getChunkFromBlockCoords((int) this.posX, (int) this.posZ).isChunkLoaded)) {
+ if (this.posY > 0.0D) {
+ this.motionY = -0.1D;
+ } else {
+ this.motionY = 0.0D;
+ }
+ } else {
+ this.motionY -= 0.08D;
+ }
+
+ this.motionY *= 0.9800000190734863D;
+ this.motionX *= (double) var3;
+ this.motionZ *= (double) var3;
+ }
+
+ this.prevLimbYaw = this.limbYaw;
+ var9 = this.posX - this.prevPosX;
+ double var11 = this.posZ - this.prevPosZ;
+ float var12 = MathHelper.sqrt_double(var9 * var9 + var11 * var11) * 4.0F;
+
+ if (var12 > 1.0F) {
+ var12 = 1.0F;
+ }
+
+ this.limbYaw += (var12 - this.limbYaw) * 0.4F;
+ this.limbSwing += this.limbYaw;
+ }
+
+ /**
+ * returns true if this entity is by a ladder, false otherwise
+ */
+ public boolean isOnLadder() {
+ int var1 = MathHelper.floor_double(this.posX);
+ int var2 = MathHelper.floor_double(this.boundingBox.minY);
+ int var3 = MathHelper.floor_double(this.posZ);
+ int var4 = this.worldObj.getBlockId(var1, var2, var3);
+ return var4 == Block.ladder.blockID || var4 == Block.vine.blockID;
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ if (this.health < -32768) {
+ this.health = -32768;
+ }
+
+ par1NBTTagCompound.setShort("Health", (short) this.health);
+ par1NBTTagCompound.setShort("HurtTime", (short) this.hurtTime);
+ par1NBTTagCompound.setShort("DeathTime", (short) this.deathTime);
+ par1NBTTagCompound.setShort("AttackTime", (short) this.attackTime);
+ par1NBTTagCompound.setBoolean("CanPickUpLoot", this.canPickUpLoot());
+ par1NBTTagCompound.setBoolean("PersistenceRequired", this.persistenceRequired);
+ NBTTagList var2 = new NBTTagList();
+
+ for (int var3 = 0; var3 < this.equipment.length; ++var3) {
+ NBTTagCompound var4 = new NBTTagCompound();
+
+ if (this.equipment[var3] != null) {
+ this.equipment[var3].writeToNBT(var4);
+ }
+
+ var2.appendTag(var4);
+ }
+
+ par1NBTTagCompound.setTag("Equipment", var2);
+ NBTTagList var6;
+
+ if (!this.activePotionsMap.isEmpty()) {
+ var6 = new NBTTagList();
+ Iterator var7 = this.activePotionsMap.values().iterator();
+
+ while (var7.hasNext()) {
+ PotionEffect var5 = (PotionEffect) var7.next();
+ var6.appendTag(var5.writeCustomPotionEffectToNBT(new NBTTagCompound()));
+ }
+
+ par1NBTTagCompound.setTag("ActiveEffects", var6);
+ }
+
+ var6 = new NBTTagList();
+
+ for (int var8 = 0; var8 < this.equipmentDropChances.length; ++var8) {
+ var6.appendTag(new NBTTagFloat(var8 + "", this.equipmentDropChances[var8]));
+ }
+
+ par1NBTTagCompound.setTag("DropChances", var6);
+ par1NBTTagCompound.setString("CustomName", this.func_94057_bL());
+ par1NBTTagCompound.setBoolean("CustomNameVisible", this.func_94062_bN());
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ this.health = par1NBTTagCompound.getShort("Health");
+
+ if (!par1NBTTagCompound.hasKey("Health")) {
+ this.health = this.getMaxHealth();
+ }
+
+ this.hurtTime = par1NBTTagCompound.getShort("HurtTime");
+ this.deathTime = par1NBTTagCompound.getShort("DeathTime");
+ this.attackTime = par1NBTTagCompound.getShort("AttackTime");
+ this.setCanPickUpLoot(par1NBTTagCompound.getBoolean("CanPickUpLoot"));
+ this.persistenceRequired = par1NBTTagCompound.getBoolean("PersistenceRequired");
+
+ if (par1NBTTagCompound.hasKey("CustomName") && par1NBTTagCompound.getString("CustomName").length() > 0) {
+ this.func_94058_c(par1NBTTagCompound.getString("CustomName"));
+ }
+
+ this.func_94061_f(par1NBTTagCompound.getBoolean("CustomNameVisible"));
+ NBTTagList var2;
+ int var3;
+
+ if (par1NBTTagCompound.hasKey("Equipment")) {
+ var2 = par1NBTTagCompound.getTagList("Equipment");
+
+ for (var3 = 0; var3 < this.equipment.length; ++var3) {
+ this.equipment[var3] = ItemStack.loadItemStackFromNBT((NBTTagCompound) var2.tagAt(var3));
+ }
+ }
+
+ if (par1NBTTagCompound.hasKey("ActiveEffects")) {
+ var2 = par1NBTTagCompound.getTagList("ActiveEffects");
+
+ for (var3 = 0; var3 < var2.tagCount(); ++var3) {
+ NBTTagCompound var4 = (NBTTagCompound) var2.tagAt(var3);
+ PotionEffect var5 = PotionEffect.readCustomPotionEffectFromNBT(var4);
+ this.activePotionsMap.put(Integer.valueOf(var5.getPotionID()), var5);
+ }
+ }
+
+ if (par1NBTTagCompound.hasKey("DropChances")) {
+ var2 = par1NBTTagCompound.getTagList("DropChances");
+
+ for (var3 = 0; var3 < var2.tagCount(); ++var3) {
+ this.equipmentDropChances[var3] = ((NBTTagFloat) var2.tagAt(var3)).data;
+ }
+ }
+ }
+
+ /**
+ * Checks whether target entity is alive.
+ */
+ public boolean isEntityAlive() {
+ return !this.isDead && this.health > 0;
+ }
+
+ public boolean canBreatheUnderwater() {
+ return false;
+ }
+
+ public void setMoveForward(float par1) {
+ this.moveForward = par1;
+ }
+
+ public void setJumping(boolean par1) {
+ this.isJumping = par1;
+ }
+
+ /**
+ * Called frequently so the entity can update its state every tick as required.
+ * For example, zombies and skeletons use this to react to sunlight and start to
+ * burn.
+ */
+ public void onLivingUpdate() {
+ if (this.jumpTicks > 0) {
+ --this.jumpTicks;
+ }
+
+ if (this.newPosRotationIncrements > 0) {
+ double var1 = this.posX + (this.newPosX - this.posX) / (double) this.newPosRotationIncrements;
+ double var3 = this.posY + (this.newPosY - this.posY) / (double) this.newPosRotationIncrements;
+ double var5 = this.posZ + (this.newPosZ - this.posZ) / (double) this.newPosRotationIncrements;
+ double var7 = MathHelper.wrapAngleTo180_double(this.newRotationYaw - (double) this.rotationYaw);
+ this.rotationYaw = (float) ((double) this.rotationYaw + var7 / (double) this.newPosRotationIncrements);
+ this.rotationPitch = (float) ((double) this.rotationPitch
+ + (this.newRotationPitch - (double) this.rotationPitch) / (double) this.newPosRotationIncrements);
+ --this.newPosRotationIncrements;
+ this.setPosition(var1, var3, var5);
+ this.setRotation(this.rotationYaw, this.rotationPitch);
+ } else if (!this.isClientWorld()) {
+ this.motionX *= 0.98D;
+ this.motionY *= 0.98D;
+ this.motionZ *= 0.98D;
+ }
+
+ if (Math.abs(this.motionX) < 0.005D) {
+ this.motionX = 0.0D;
+ }
+
+ if (Math.abs(this.motionY) < 0.005D) {
+ this.motionY = 0.0D;
+ }
+
+ if (Math.abs(this.motionZ) < 0.005D) {
+ this.motionZ = 0.0D;
+ }
+
+ if (this.isMovementBlocked()) {
+ this.isJumping = false;
+ this.moveStrafing = 0.0F;
+ this.moveForward = 0.0F;
+ this.randomYawVelocity = 0.0F;
+ } else if (this.isClientWorld()) {
+ if (this.isAIEnabled()) {
+ this.updateAITasks();
+ } else {
+ this.updateEntityActionState();
+ this.rotationYawHead = this.rotationYaw;
+ }
+ }
+
+ if (this.isJumping) {
+ if (!this.isInWater() && !this.handleLavaMovement()) {
+ if (this.onGround && this.jumpTicks == 0) {
+ this.jump();
+ this.jumpTicks = 10;
+ }
+ } else {
+ this.motionY += 0.03999999910593033D;
+ }
+ } else {
+ this.jumpTicks = 0;
+ }
+
+ this.moveStrafing *= 0.98F;
+ this.moveForward *= 0.98F;
+ this.randomYawVelocity *= 0.9F;
+ float var11 = this.landMovementFactor;
+ this.landMovementFactor *= this.getSpeedModifier();
+ this.moveEntityWithHeading(this.moveStrafing, this.moveForward);
+ this.landMovementFactor = var11;
+
+ if (!this.worldObj.isRemote) {
+ this.func_85033_bc();
+ }
+
+ if (!this.worldObj.isRemote && this.canPickUpLoot() && !this.dead
+ && this.worldObj.getGameRules().getGameRuleBooleanValue("mobGriefing")) {
+ List var2 = this.worldObj.getEntitiesWithinAABB(EntityItem.class,
+ this.boundingBox.expand(1.0D, 0.0D, 1.0D));
+ Iterator var12 = var2.iterator();
+
+ while (var12.hasNext()) {
+ EntityItem var4 = (EntityItem) var12.next();
+
+ if (!var4.isDead && var4.getEntityItem() != null) {
+ ItemStack var13 = var4.getEntityItem();
+ int var6 = getArmorPosition(var13);
+
+ if (var6 > -1) {
+ boolean var14 = true;
+ ItemStack var8 = this.getEquipmentInSlot(var6);
+
+ if (var8 != null) {
+ if (var6 == 0) {
+ if (var13.getItem() instanceof ItemSword && !(var8.getItem() instanceof ItemSword)) {
+ var14 = true;
+ } else if (var13.getItem() instanceof ItemSword
+ && var8.getItem() instanceof ItemSword) {
+ ItemSword var9 = (ItemSword) var13.getItem();
+ ItemSword var10 = (ItemSword) var8.getItem();
+
+ if (var9.func_82803_g() == var10.func_82803_g()) {
+ var14 = var13.getItemDamage() > var8.getItemDamage()
+ || var13.hasTagCompound() && !var8.hasTagCompound();
+ } else {
+ var14 = var9.func_82803_g() > var10.func_82803_g();
+ }
+ } else {
+ var14 = false;
+ }
+ } else if (var13.getItem() instanceof ItemArmor && !(var8.getItem() instanceof ItemArmor)) {
+ var14 = true;
+ } else if (var13.getItem() instanceof ItemArmor && var8.getItem() instanceof ItemArmor) {
+ ItemArmor var15 = (ItemArmor) var13.getItem();
+ ItemArmor var16 = (ItemArmor) var8.getItem();
+
+ if (var15.damageReduceAmount == var16.damageReduceAmount) {
+ var14 = var13.getItemDamage() > var8.getItemDamage()
+ || var13.hasTagCompound() && !var8.hasTagCompound();
+ } else {
+ var14 = var15.damageReduceAmount > var16.damageReduceAmount;
+ }
+ } else {
+ var14 = false;
+ }
+ }
+
+ if (var14) {
+ if (var8 != null && this.rand.nextFloat() - 0.1F < this.equipmentDropChances[var6]) {
+ this.entityDropItem(var8, 0.0F);
+ }
+
+ this.setCurrentItemOrArmor(var6, var13);
+ this.equipmentDropChances[var6] = 2.0F;
+ this.persistenceRequired = true;
+ this.onItemPickup(var4, 1);
+ var4.setDead();
+ }
+ }
+ }
+ }
+ }
+ }
+
+ protected void func_85033_bc() {
+ List var1 = this.worldObj.getEntitiesWithinAABBExcludingEntity(this,
+ this.boundingBox.expand(0.20000000298023224D, 0.0D, 0.20000000298023224D));
+
+ if (var1 != null && !var1.isEmpty()) {
+ for (int var2 = 0; var2 < var1.size(); ++var2) {
+ Entity var3 = (Entity) var1.get(var2);
+
+ if (var3.canBePushed()) {
+ this.collideWithEntity(var3);
+ }
+ }
+ }
+ }
+
+ protected void collideWithEntity(Entity par1Entity) {
+ par1Entity.applyEntityCollision(this);
+ }
+
+ /**
+ * Returns true if the newer Entity AI code should be run
+ */
+ protected boolean isAIEnabled() {
+ return false;
+ }
+
+ /**
+ * Returns whether the entity is in a local (client) world
+ */
+ protected boolean isClientWorld() {
+ return !this.worldObj.isRemote;
+ }
+
+ /**
+ * Dead and sleeping entities cannot move
+ */
+ protected boolean isMovementBlocked() {
+ return this.health <= 0;
+ }
+
+ public boolean isBlocking() {
+ return false;
+ }
+
+ /**
+ * Causes this entity to do an upwards motion (jumping).
+ */
+ protected void jump() {
+ this.motionY = 0.41999998688697815D;
+
+ if (this.isPotionActive(Potion.jump)) {
+ this.motionY += (double) ((float) (this.getActivePotionEffect(Potion.jump).getAmplifier() + 1) * 0.1F);
+ }
+
+ if (this.isSprinting()) {
+ float var1 = this.rotationYaw * 0.017453292F;
+ this.motionX -= (double) (MathHelper.sin(var1) * 0.2F);
+ this.motionZ += (double) (MathHelper.cos(var1) * 0.2F);
+ }
+
+ this.isAirBorne = true;
+ }
+
+ /**
+ * Determines if an entity can be despawned, used on idle far away entities
+ */
+ protected boolean canDespawn() {
+ return true;
+ }
+
+ /**
+ * Makes the entity despawn if requirements are reached
+ */
+ protected void despawnEntity() {
+ if (!this.persistenceRequired) {
+ EntityPlayer var1 = this.worldObj.getClosestPlayerToEntity(this, -1.0D);
+
+ if (var1 != null) {
+ double var2 = var1.posX - this.posX;
+ double var4 = var1.posY - this.posY;
+ double var6 = var1.posZ - this.posZ;
+ double var8 = var2 * var2 + var4 * var4 + var6 * var6;
+
+ if (this.canDespawn() && var8 > 16384.0D) {
+ this.setDead();
+ }
+
+ if (this.entityAge > 600 && this.rand.nextInt(800) == 0 && var8 > 1024.0D && this.canDespawn()) {
+ this.setDead();
+ } else if (var8 < 1024.0D) {
+ this.entityAge = 0;
+ }
+ }
+ }
+ }
+
+ protected void updateAITasks() {
+ ++this.entityAge;
+ this.despawnEntity();
+ this.senses.clearSensingCache();
+ this.targetTasks.onUpdateTasks();
+ this.tasks.onUpdateTasks();
+ this.navigator.onUpdateNavigation();
+ this.updateAITick();
+ this.moveHelper.onUpdateMoveHelper();
+ this.lookHelper.onUpdateLook();
+ this.jumpHelper.doJump();
+ }
+
+ /**
+ * main AI tick function, replaces updateEntityActionState
+ */
+ protected void updateAITick() {
+ }
+
+ protected void updateEntityActionState() {
+ ++this.entityAge;
+ this.despawnEntity();
+ this.moveStrafing = 0.0F;
+ this.moveForward = 0.0F;
+ float var1 = 8.0F;
+
+ if (this.rand.nextFloat() < 0.02F) {
+ EntityPlayer var2 = this.worldObj.getClosestPlayerToEntity(this, (double) var1);
+
+ if (var2 != null) {
+ this.currentTarget = var2;
+ this.numTicksToChaseTarget = 10 + this.rand.nextInt(20);
+ } else {
+ this.randomYawVelocity = (this.rand.nextFloat() - 0.5F) * 20.0F;
+ }
+ }
+
+ if (this.currentTarget != null) {
+ this.faceEntity(this.currentTarget, 10.0F, (float) this.getVerticalFaceSpeed());
+
+ if (this.numTicksToChaseTarget-- <= 0 || this.currentTarget.isDead
+ || this.currentTarget.getDistanceSqToEntity(this) > (double) (var1 * var1)) {
+ this.currentTarget = null;
+ }
+ } else {
+ if (this.rand.nextFloat() < 0.05F) {
+ this.randomYawVelocity = (this.rand.nextFloat() - 0.5F) * 20.0F;
+ }
+
+ this.rotationYaw += this.randomYawVelocity;
+ this.rotationPitch = this.defaultPitch;
+ }
+
+ boolean var4 = this.isInWater();
+ boolean var3 = this.handleLavaMovement();
+
+ if (var4 || var3) {
+ this.isJumping = this.rand.nextFloat() < 0.8F;
+ }
+ }
+
+ /**
+ * Updates the arm swing progress counters and animation progress
+ */
+ protected void updateArmSwingProgress() {
+ int var1 = this.getArmSwingAnimationEnd();
+
+ if (this.isSwingInProgress) {
+ ++this.swingProgressInt;
+
+ if (this.swingProgressInt >= var1) {
+ this.swingProgressInt = 0;
+ this.isSwingInProgress = false;
+ }
+ } else {
+ this.swingProgressInt = 0;
+ }
+
+ this.swingProgress = (float) this.swingProgressInt / (float) var1;
+ }
+
+ /**
+ * The speed it takes to move the entityliving's rotationPitch through the
+ * faceEntity method. This is only currently use in wolves.
+ */
+ public int getVerticalFaceSpeed() {
+ return 40;
+ }
+
+ /**
+ * Changes pitch and yaw so that the entity calling the function is facing the
+ * entity provided as an argument.
+ */
+ public void faceEntity(Entity par1Entity, float par2, float par3) {
+ double var4 = par1Entity.posX - this.posX;
+ double var8 = par1Entity.posZ - this.posZ;
+ double var6;
+
+ if (par1Entity instanceof EntityLiving) {
+ EntityLiving var10 = (EntityLiving) par1Entity;
+ var6 = var10.posY + (double) var10.getEyeHeight() - (this.posY + (double) this.getEyeHeight());
+ } else {
+ var6 = (par1Entity.boundingBox.minY + par1Entity.boundingBox.maxY) / 2.0D
+ - (this.posY + (double) this.getEyeHeight());
+ }
+
+ double var14 = (double) MathHelper.sqrt_double(var4 * var4 + var8 * var8);
+ float var12 = (float) (Math.atan2(var8, var4) * 180.0D / Math.PI) - 90.0F;
+ float var13 = (float) (-(Math.atan2(var6, var14) * 180.0D / Math.PI));
+ this.rotationPitch = this.updateRotation(this.rotationPitch, var13, par3);
+ this.rotationYaw = this.updateRotation(this.rotationYaw, var12, par2);
+ }
+
+ /**
+ * Arguments: current rotation, intended rotation, max increment.
+ */
+ private float updateRotation(float par1, float par2, float par3) {
+ float var4 = MathHelper.wrapAngleTo180_float(par2 - par1);
+
+ if (var4 > par3) {
+ var4 = par3;
+ }
+
+ if (var4 < -par3) {
+ var4 = -par3;
+ }
+
+ return par1 + var4;
+ }
+
+ /**
+ * Checks if the entity's current position is a valid location to spawn this
+ * entity.
+ */
+ public boolean getCanSpawnHere() {
+ return this.worldObj.checkNoEntityCollision(this.boundingBox)
+ && this.worldObj.getCollidingBoundingBoxes(this, this.boundingBox).isEmpty()
+ && !this.worldObj.isAnyLiquid(this.boundingBox);
+ }
+
+ /**
+ * sets the dead flag. Used when you fall off the bottom of the world.
+ */
+ protected void kill() {
+ this.attackEntityFrom(DamageSource.outOfWorld, 4);
+ }
+
+ /**
+ * returns a (normalized) vector of where this entity is looking
+ */
+ public Vec3 getLookVec() {
+ return this.getLook(1.0F);
+ }
+
+ /**
+ * interpolated look vector
+ */
+ public Vec3 getLook(float par1) {
+ float var2;
+ float var3;
+ float var4;
+ float var5;
+
+ if (par1 == 1.0F) {
+ var2 = MathHelper.cos(-this.rotationYaw * 0.017453292F - (float) Math.PI);
+ var3 = MathHelper.sin(-this.rotationYaw * 0.017453292F - (float) Math.PI);
+ var4 = -MathHelper.cos(-this.rotationPitch * 0.017453292F);
+ var5 = MathHelper.sin(-this.rotationPitch * 0.017453292F);
+ return this.worldObj.getWorldVec3Pool().getVecFromPool((double) (var3 * var4), (double) var5,
+ (double) (var2 * var4));
+ } else {
+ var2 = this.prevRotationPitch + (this.rotationPitch - this.prevRotationPitch) * par1;
+ var3 = this.prevRotationYaw + (this.rotationYaw - this.prevRotationYaw) * par1;
+ var4 = MathHelper.cos(-var3 * 0.017453292F - (float) Math.PI);
+ var5 = MathHelper.sin(-var3 * 0.017453292F - (float) Math.PI);
+ float var6 = -MathHelper.cos(-var2 * 0.017453292F);
+ float var7 = MathHelper.sin(-var2 * 0.017453292F);
+ return this.worldObj.getWorldVec3Pool().getVecFromPool((double) (var5 * var6), (double) var7,
+ (double) (var4 * var6));
+ }
+ }
+
+ /**
+ * Will return how many at most can spawn in a chunk at once.
+ */
+ public int getMaxSpawnedInChunk() {
+ return 4;
+ }
+
+ /**
+ * Returns whether player is sleeping or not
+ */
+ public boolean isPlayerSleeping() {
+ return false;
+ }
+
+ protected void updatePotionEffects() {
+ Iterator var1 = this.activePotionsMap.keySet().iterator();
+
+ while (var1.hasNext()) {
+ Integer var2 = (Integer) var1.next();
+ PotionEffect var3 = (PotionEffect) this.activePotionsMap.get(var2);
+ if (!var3.onUpdate(this)) {
+ if (!this.worldObj.isRemote) {
+ var1.remove();
+ this.onFinishedPotionEffect(var3);
+ }
+ } else if (var3.getDuration() % 600 == 0) {
+ this.onChangedPotionEffect(var3);
+ }
+ }
+
+ int var12;
+
+ if (this.potionsNeedUpdate) {
+ if (!this.worldObj.isRemote) {
+ if (this.activePotionsMap.isEmpty()) {
+ this.dataWatcher.updateObject(9, Byte.valueOf((byte) 0));
+ this.dataWatcher.updateObject(8, Integer.valueOf(0));
+ this.setInvisible(false);
+ } else {
+ var12 = PotionHelper.calcPotionLiquidColor(this.activePotionsMap.values());
+ this.dataWatcher.updateObject(9,
+ Byte.valueOf((byte) (PotionHelper.func_82817_b(this.activePotionsMap.values()) ? 1 : 0)));
+ this.dataWatcher.updateObject(8, Integer.valueOf(var12));
+ this.setInvisible(this.isPotionActive(Potion.invisibility.id));
+ }
+ }
+
+ this.potionsNeedUpdate = false;
+ }
+
+ var12 = this.dataWatcher.getWatchableObjectInt(8);
+ boolean var13 = this.dataWatcher.getWatchableObjectByte(9) > 0;
+
+ if (var12 > 0) {
+ boolean var4 = false;
+
+ if (!this.isInvisible()) {
+ var4 = this.rand.nextBoolean();
+ } else {
+ var4 = this.rand.nextInt(15) == 0;
+ }
+
+ if (var13) {
+ var4 &= this.rand.nextInt(5) == 0;
+ }
+
+ if (var4 && var12 > 0) {
+ double var14 = (double) (var12 >> 16 & 255) / 255.0D;
+ double var7 = (double) (var12 >> 8 & 255) / 255.0D;
+ double var9 = (double) (var12 >> 0 & 255) / 255.0D;
+ this.worldObj.spawnParticle(var13 ? "mobSpellAmbient" : "mobSpell",
+ this.posX + (this.rand.nextDouble() - 0.5D) * (double) this.width,
+ this.posY + this.rand.nextDouble() * (double) this.height - (double) this.yOffset,
+ this.posZ + (this.rand.nextDouble() - 0.5D) * (double) this.width, var14, var7, var9);
+ }
+ }
+ }
+
+ public void clearActivePotions() {
+ Iterator var1 = this.activePotionsMap.keySet().iterator();
+
+ while (var1.hasNext()) {
+ Integer var2 = (Integer) var1.next();
+ PotionEffect var3 = (PotionEffect) this.activePotionsMap.get(var2);
+
+ if (!this.worldObj.isRemote) {
+ var1.remove();
+ this.onFinishedPotionEffect(var3);
+ }
+ }
+ }
+
+ public Collection getActivePotionEffects() {
+ return this.activePotionsMap.values();
+ }
+
+ public boolean isPotionActive(int par1) {
+ return this.activePotionsMap.containsKey(Integer.valueOf(par1));
+ }
+
+ public boolean isPotionActive(Potion par1Potion) {
+ return this.activePotionsMap.containsKey(Integer.valueOf(par1Potion.id));
+ }
+
+ /**
+ * returns the PotionEffect for the supplied Potion if it is active, null
+ * otherwise.
+ */
+ public PotionEffect getActivePotionEffect(Potion par1Potion) {
+ return (PotionEffect) this.activePotionsMap.get(Integer.valueOf(par1Potion.id));
+ }
+
+ /**
+ * adds a PotionEffect to the entity
+ */
+ public void addPotionEffect(PotionEffect par1PotionEffect) {
+ if (this.isPotionApplicable(par1PotionEffect)) {
+ if (this.activePotionsMap.containsKey(Integer.valueOf(par1PotionEffect.getPotionID()))) {
+ ((PotionEffect) this.activePotionsMap.get(Integer.valueOf(par1PotionEffect.getPotionID())))
+ .combine(par1PotionEffect);
+ this.onChangedPotionEffect(
+ (PotionEffect) this.activePotionsMap.get(Integer.valueOf(par1PotionEffect.getPotionID())));
+ } else {
+ this.activePotionsMap.put(Integer.valueOf(par1PotionEffect.getPotionID()), par1PotionEffect);
+ this.onNewPotionEffect(par1PotionEffect);
+ }
+ }
+ }
+
+ public boolean isPotionApplicable(PotionEffect par1PotionEffect) {
+ if (this.getCreatureAttribute() == EnumCreatureAttribute.UNDEAD) {
+ int var2 = par1PotionEffect.getPotionID();
+
+ if (var2 == Potion.regeneration.id || var2 == Potion.poison.id) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns true if this entity is undead.
+ */
+ public boolean isEntityUndead() {
+ return this.getCreatureAttribute() == EnumCreatureAttribute.UNDEAD;
+ }
+
+ /**
+ * Remove the specified potion effect from this entity.
+ */
+ public void removePotionEffect(int par1) {
+ PotionEffect var2 = (PotionEffect) this.activePotionsMap.remove(Integer.valueOf(par1));
+
+ if (var2 != null) {
+ this.onFinishedPotionEffect(var2);
+ }
+ }
+
+ protected void onNewPotionEffect(PotionEffect par1PotionEffect) {
+ this.potionsNeedUpdate = true;
+ }
+
+ protected void onChangedPotionEffect(PotionEffect par1PotionEffect) {
+ this.potionsNeedUpdate = true;
+ }
+
+ protected void onFinishedPotionEffect(PotionEffect par1PotionEffect) {
+ this.potionsNeedUpdate = true;
+ }
+
+ /**
+ * This method returns a value to be applied directly to entity speed, this
+ * factor is less than 1 when a slowdown potion effect is applied, more than 1
+ * when a haste potion effect is applied and 2 for fleeing entities.
+ */
+ public float getSpeedModifier() {
+ float var1 = 1.0F;
+
+ if (this.isPotionActive(Potion.moveSpeed)) {
+ var1 *= 1.0F + 0.2F * (float) (this.getActivePotionEffect(Potion.moveSpeed).getAmplifier() + 1);
+ }
+
+ if (this.isPotionActive(Potion.moveSlowdown)) {
+ var1 *= 1.0F - 0.15F * (float) (this.getActivePotionEffect(Potion.moveSlowdown).getAmplifier() + 1);
+ }
+
+ if (var1 < 0.0F) {
+ var1 = 0.0F;
+ }
+
+ return var1;
+ }
+
+ /**
+ * Sets the position of the entity and updates the 'last' variables
+ */
+ public void setPositionAndUpdate(double par1, double par3, double par5) {
+ this.setLocationAndAngles(par1, par3, par5, this.rotationYaw, this.rotationPitch);
+ }
+
+ /**
+ * If Animal, checks if the age timer is negative
+ */
+ public boolean isChild() {
+ return false;
+ }
+
+ /**
+ * Get this Entity's EnumCreatureAttribute
+ */
+ public EnumCreatureAttribute getCreatureAttribute() {
+ return EnumCreatureAttribute.UNDEFINED;
+ }
+
+ /**
+ * Renders broken item particles using the given ItemStack
+ */
+ public void renderBrokenItemStack(ItemStack par1ItemStack) {
+ this.playSound("random.break", 0.8F, 0.8F + this.worldObj.rand.nextFloat() * 0.4F);
+
+ for (int var2 = 0; var2 < 5; ++var2) {
+ Vec3 var3 = this.worldObj.getWorldVec3Pool().getVecFromPool(((double) this.rand.nextFloat() - 0.5D) * 0.1D,
+ Math.random() * 0.1D + 0.1D, 0.0D);
+ var3.rotateAroundX(-this.rotationPitch * (float) Math.PI / 180.0F);
+ var3.rotateAroundY(-this.rotationYaw * (float) Math.PI / 180.0F);
+ Vec3 var4 = this.worldObj.getWorldVec3Pool().getVecFromPool(((double) this.rand.nextFloat() - 0.5D) * 0.3D,
+ (double) (-this.rand.nextFloat()) * 0.6D - 0.3D, 0.6D);
+ var4.rotateAroundX(-this.rotationPitch * (float) Math.PI / 180.0F);
+ var4.rotateAroundY(-this.rotationYaw * (float) Math.PI / 180.0F);
+ var4 = var4.addVector(this.posX, this.posY + (double) this.getEyeHeight(), this.posZ);
+ this.worldObj.spawnParticle("iconcrack_" + par1ItemStack.getItem().itemID, var4.xCoord, var4.yCoord,
+ var4.zCoord, var3.xCoord, var3.yCoord + 0.05D, var3.zCoord);
+ }
+ }
+
+ public int func_82143_as() {
+ if (this.getAttackTarget() == null) {
+ return 3;
+ } else {
+ int var1 = (int) ((float) this.health - (float) this.getMaxHealth() * 0.33F);
+ var1 -= (3 - this.worldObj.difficultySetting) * 4;
+
+ if (var1 < 0) {
+ var1 = 0;
+ }
+
+ return var1 + 3;
+ }
+ }
+
+ /**
+ * Returns the item that this EntityLiving is holding, if any.
+ */
+ public ItemStack getHeldItem() {
+ return this.equipment[0];
+ }
+
+ /**
+ * 0: Tool in Hand; 1-4: Armor
+ */
+ public ItemStack getEquipmentInSlot(int par1) {
+ return this.equipment[par1];
+ }
+
+ public ItemStack getCurrentArmor(int par1) {
+ return this.equipment[par1 + 1];
+ }
+
+ /**
+ * Sets the held item, or an armor slot. Slot 0 is held item. Slot 1-4 is armor.
+ * Params: Item, slot
+ */
+ public void setCurrentItemOrArmor(int par1, ItemStack par2ItemStack) {
+ this.equipment[par1] = par2ItemStack;
+ }
+
+ /**
+ * returns the inventory of this entity (only used in EntityPlayerMP it seems)
+ */
+ public ItemStack[] getInventory() {
+ return this.equipment;
+ }
+
+ /**
+ * Drop the equipment for this entity.
+ */
+ protected void dropEquipment(boolean par1, int par2) {
+ for (int var3 = 0; var3 < this.getInventory().length; ++var3) {
+ ItemStack var4 = this.getEquipmentInSlot(var3);
+ boolean var5 = this.equipmentDropChances[var3] > 1.0F;
+
+ if (var4 != null && (par1 || var5)
+ && this.rand.nextFloat() - (float) par2 * 0.01F < this.equipmentDropChances[var3]) {
+ if (!var5 && var4.isItemStackDamageable()) {
+ int var6 = Math.max(var4.getMaxDamage() - 25, 1);
+ int var7 = var4.getMaxDamage() - this.rand.nextInt(this.rand.nextInt(var6) + 1);
+
+ if (var7 > var6) {
+ var7 = var6;
+ }
+
+ if (var7 < 1) {
+ var7 = 1;
+ }
+
+ var4.setItemDamage(var7);
+ }
+
+ this.entityDropItem(var4, 0.0F);
+ }
+ }
+ }
+
+ /**
+ * Makes entity wear random armor based on difficulty
+ */
+ protected void addRandomArmor() {
+ if (this.rand.nextFloat() < armorProbability[this.worldObj.difficultySetting]) {
+ int var1 = this.rand.nextInt(2);
+ float var2 = this.worldObj.difficultySetting == 3 ? 0.1F : 0.25F;
+
+ if (this.rand.nextFloat() < 0.095F) {
+ ++var1;
+ }
+
+ if (this.rand.nextFloat() < 0.095F) {
+ ++var1;
+ }
+
+ if (this.rand.nextFloat() < 0.095F) {
+ ++var1;
+ }
+
+ for (int var3 = 3; var3 >= 0; --var3) {
+ ItemStack var4 = this.getCurrentArmor(var3);
+
+ if (var3 < 3 && this.rand.nextFloat() < var2) {
+ break;
+ }
+
+ if (var4 == null) {
+ Item var5 = getArmorItemForSlot(var3 + 1, var1);
+
+ if (var5 != null) {
+ this.setCurrentItemOrArmor(var3 + 1, new ItemStack(var5));
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Called whenever an item is picked up from walking over it. Args:
+ * pickedUpEntity, stackSize
+ */
+ public void onItemPickup(Entity par1Entity, int par2) {
+ if (!par1Entity.isDead && !this.worldObj.isRemote) {
+ EntityTracker var3 = ((WorldServer) this.worldObj).getEntityTracker();
+
+ if (par1Entity instanceof EntityItem) {
+ var3.sendPacketToTrackedPlayers(par1Entity, new Packet22Collect(par1Entity.entityId, this.entityId));
+ }
+
+ if (par1Entity instanceof EntityArrow) {
+ var3.sendPacketToTrackedPlayers(par1Entity, new Packet22Collect(par1Entity.entityId, this.entityId));
+ }
+
+ if (par1Entity instanceof EntityXPOrb) {
+ var3.sendPacketToTrackedPlayers(par1Entity, new Packet22Collect(par1Entity.entityId, this.entityId));
+ }
+ }
+ }
+
+ public static int getArmorPosition(ItemStack par0ItemStack) {
+ if (par0ItemStack.itemID != Block.pumpkin.blockID && par0ItemStack.itemID != Item.skull.itemID) {
+ if (par0ItemStack.getItem() instanceof ItemArmor) {
+ switch (((ItemArmor) par0ItemStack.getItem()).armorType) {
+ case 0:
+ return 4;
+
+ case 1:
+ return 3;
+
+ case 2:
+ return 2;
+
+ case 3:
+ return 1;
+ }
+ }
+
+ return 0;
+ } else {
+ return 4;
+ }
+ }
+
+ /**
+ * Params: Armor slot, Item tier
+ */
+ public static Item getArmorItemForSlot(int par0, int par1) {
+ switch (par0) {
+ case 4:
+ if (par1 == 0) {
+ return Item.helmetLeather;
+ } else if (par1 == 1) {
+ return Item.helmetGold;
+ } else if (par1 == 2) {
+ return Item.helmetChain;
+ } else if (par1 == 3) {
+ return Item.helmetIron;
+ } else if (par1 == 4) {
+ return Item.helmetDiamond;
+ }
+
+ case 3:
+ if (par1 == 0) {
+ return Item.plateLeather;
+ } else if (par1 == 1) {
+ return Item.plateGold;
+ } else if (par1 == 2) {
+ return Item.plateChain;
+ } else if (par1 == 3) {
+ return Item.plateIron;
+ } else if (par1 == 4) {
+ return Item.plateDiamond;
+ }
+
+ case 2:
+ if (par1 == 0) {
+ return Item.legsLeather;
+ } else if (par1 == 1) {
+ return Item.legsGold;
+ } else if (par1 == 2) {
+ return Item.legsChain;
+ } else if (par1 == 3) {
+ return Item.legsIron;
+ } else if (par1 == 4) {
+ return Item.legsDiamond;
+ }
+
+ case 1:
+ if (par1 == 0) {
+ return Item.bootsLeather;
+ } else if (par1 == 1) {
+ return Item.bootsGold;
+ } else if (par1 == 2) {
+ return Item.bootsChain;
+ } else if (par1 == 3) {
+ return Item.bootsIron;
+ } else if (par1 == 4) {
+ return Item.bootsDiamond;
+ }
+
+ default:
+ return null;
+ }
+ }
+
+ protected void func_82162_bC() {
+ if (this.getHeldItem() != null
+ && this.rand.nextFloat() < enchantmentProbability[this.worldObj.difficultySetting]) {
+ EnchantmentHelper.addRandomEnchantment(this.rand, this.getHeldItem(),
+ 5 + this.worldObj.difficultySetting * this.rand.nextInt(6));
+ }
+
+ for (int var1 = 0; var1 < 4; ++var1) {
+ ItemStack var2 = this.getCurrentArmor(var1);
+
+ if (var2 != null && this.rand.nextFloat() < armorEnchantmentProbability[this.worldObj.difficultySetting]) {
+ EnchantmentHelper.addRandomEnchantment(this.rand, var2,
+ 5 + this.worldObj.difficultySetting * this.rand.nextInt(6));
+ }
+ }
+ }
+
+ /**
+ * Initialize this creature.
+ */
+ public void initCreature() {
+ }
+
+ /**
+ * Returns an integer indicating the end point of the swing animation, used by
+ * {@link #swingProgress} to provide a progress indicator. Takes dig speed
+ * enchantments into account.
+ */
+ private int getArmSwingAnimationEnd() {
+ return this.isPotionActive(Potion.digSpeed)
+ ? 6 - (1 + this.getActivePotionEffect(Potion.digSpeed).getAmplifier()) * 1
+ : (this.isPotionActive(Potion.digSlowdown)
+ ? 6 + (1 + this.getActivePotionEffect(Potion.digSlowdown).getAmplifier()) * 2
+ : 6);
+ }
+
+ /**
+ * Swings the item the player is holding.
+ */
+ public void swingItem() {
+ if (!this.isSwingInProgress || this.swingProgressInt >= this.getArmSwingAnimationEnd() / 2
+ || this.swingProgressInt < 0) {
+ this.swingProgressInt = -1;
+ this.isSwingInProgress = true;
+
+ if (this.worldObj instanceof WorldServer) {
+ ((WorldServer) this.worldObj).getEntityTracker().sendPacketToTrackedPlayers(this,
+ new Packet18Animation(this, 1));
+ }
+ }
+ }
+
+ /**
+ * returns true if all the conditions for steering the entity are met. For pigs,
+ * this is true if it is being ridden by a player and the player is holding a
+ * carrot-on-a-stick
+ */
+ public boolean canBeSteered() {
+ return false;
+ }
+
+ /**
+ * counts the amount of arrows stuck in the entity. getting hit by arrows
+ * increases this, used in rendering
+ */
+ public final int getArrowCountInEntity() {
+ return this.dataWatcher.getWatchableObjectByte(10);
+ }
+
+ /**
+ * sets the amount of arrows stuck in the entity. used for rendering those
+ */
+ public final void setArrowCountInEntity(int par1) {
+ this.dataWatcher.updateObject(10, Byte.valueOf((byte) par1));
+ }
+
+ public EntityLiving func_94060_bK() {
+ return (EntityLiving) (this.field_94063_bt.func_94550_c() != null ? this.field_94063_bt.func_94550_c()
+ : (this.attackingPlayer != null ? this.attackingPlayer
+ : (this.entityLivingToAttack != null ? this.entityLivingToAttack : null)));
+ }
+
+ /**
+ * Gets the username of the entity.
+ */
+ public String getEntityName() {
+ return this.func_94056_bM() ? this.func_94057_bL() : super.getEntityName();
+ }
+
+ public void func_94058_c(String par1Str) {
+ this.dataWatcher.updateObject(5, par1Str);
+ }
+
+ public String func_94057_bL() {
+ return this.dataWatcher.getWatchableObjectString(5);
+ }
+
+ public boolean func_94056_bM() {
+ return this.dataWatcher.getWatchableObjectString(5).length() > 0;
+ }
+
+ public void func_94061_f(boolean par1) {
+ this.dataWatcher.updateObject(6, Byte.valueOf((byte) (par1 ? 1 : 0)));
+ }
+
+ public boolean func_94062_bN() {
+ return this.dataWatcher.getWatchableObjectByte(6) == 1;
+ }
+
+ public void func_96120_a(int par1, float par2) {
+ this.equipmentDropChances[par1] = par2;
+ }
+
+ public boolean canPickUpLoot() {
+ return this.canPickUpLoot;
+ }
+
+ public void setCanPickUpLoot(boolean par1) {
+ this.canPickUpLoot = par1;
+ }
+
+ public boolean func_104002_bU() {
+ return this.persistenceRequired;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityLookHelper.java b/sp-server/src/main/java/net/minecraft/src/EntityLookHelper.java
new file mode 100644
index 0000000..3401023
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityLookHelper.java
@@ -0,0 +1,105 @@
+package net.minecraft.src;
+
+public class EntityLookHelper {
+ private EntityLiving entity;
+
+ /**
+ * The amount of change that is made each update for an entity facing a
+ * direction.
+ */
+ private float deltaLookYaw;
+
+ /**
+ * The amount of change that is made each update for an entity facing a
+ * direction.
+ */
+ private float deltaLookPitch;
+
+ /** Whether or not the entity is trying to look at something. */
+ private boolean isLooking = false;
+ private double posX;
+ private double posY;
+ private double posZ;
+
+ public EntityLookHelper(EntityLiving par1EntityLiving) {
+ this.entity = par1EntityLiving;
+ }
+
+ /**
+ * Sets position to look at using entity
+ */
+ public void setLookPositionWithEntity(Entity par1Entity, float par2, float par3) {
+ this.posX = par1Entity.posX;
+
+ if (par1Entity instanceof EntityLiving) {
+ this.posY = par1Entity.posY + (double) par1Entity.getEyeHeight();
+ } else {
+ this.posY = (par1Entity.boundingBox.minY + par1Entity.boundingBox.maxY) / 2.0D;
+ }
+
+ this.posZ = par1Entity.posZ;
+ this.deltaLookYaw = par2;
+ this.deltaLookPitch = par3;
+ this.isLooking = true;
+ }
+
+ /**
+ * Sets position to look at
+ */
+ public void setLookPosition(double par1, double par3, double par5, float par7, float par8) {
+ this.posX = par1;
+ this.posY = par3;
+ this.posZ = par5;
+ this.deltaLookYaw = par7;
+ this.deltaLookPitch = par8;
+ this.isLooking = true;
+ }
+
+ /**
+ * Updates look
+ */
+ public void onUpdateLook() {
+ this.entity.rotationPitch = 0.0F;
+
+ if (this.isLooking) {
+ this.isLooking = false;
+ double var1 = this.posX - this.entity.posX;
+ double var3 = this.posY - (this.entity.posY + (double) this.entity.getEyeHeight());
+ double var5 = this.posZ - this.entity.posZ;
+ double var7 = (double) MathHelper.sqrt_double(var1 * var1 + var5 * var5);
+ float var9 = (float) (Math.atan2(var5, var1) * 180.0D / Math.PI) - 90.0F;
+ float var10 = (float) (-(Math.atan2(var3, var7) * 180.0D / Math.PI));
+ this.entity.rotationPitch = this.updateRotation(this.entity.rotationPitch, var10, this.deltaLookPitch);
+ this.entity.rotationYawHead = this.updateRotation(this.entity.rotationYawHead, var9, this.deltaLookYaw);
+ } else {
+ this.entity.rotationYawHead = this.updateRotation(this.entity.rotationYawHead, this.entity.renderYawOffset,
+ 10.0F);
+ }
+
+ float var11 = MathHelper.wrapAngleTo180_float(this.entity.rotationYawHead - this.entity.renderYawOffset);
+
+ if (!this.entity.getNavigator().noPath()) {
+ if (var11 < -75.0F) {
+ this.entity.rotationYawHead = this.entity.renderYawOffset - 75.0F;
+ }
+
+ if (var11 > 75.0F) {
+ this.entity.rotationYawHead = this.entity.renderYawOffset + 75.0F;
+ }
+ }
+ }
+
+ private float updateRotation(float par1, float par2, float par3) {
+ float var4 = MathHelper.wrapAngleTo180_float(par2 - par1);
+
+ if (var4 > par3) {
+ var4 = par3;
+ }
+
+ if (var4 < -par3) {
+ var4 = -par3;
+ }
+
+ return par1 + var4;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityMagmaCube.java b/sp-server/src/main/java/net/minecraft/src/EntityMagmaCube.java
new file mode 100644
index 0000000..cdfd03c
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityMagmaCube.java
@@ -0,0 +1,157 @@
+package net.minecraft.src;
+
+public class EntityMagmaCube extends EntitySlime {
+ public EntityMagmaCube(World par1World) {
+ super(par1World);
+ this.texture = "/mob/lava.png";
+ this.isImmuneToFire = true;
+ this.landMovementFactor = 0.2F;
+ }
+
+ /**
+ * Checks if the entity's current position is a valid location to spawn this
+ * entity.
+ */
+ public boolean getCanSpawnHere() {
+ return this.worldObj.difficultySetting > 0 && this.worldObj.checkNoEntityCollision(this.boundingBox)
+ && this.worldObj.getCollidingBoundingBoxes(this, this.boundingBox).isEmpty()
+ && !this.worldObj.isAnyLiquid(this.boundingBox);
+ }
+
+ /**
+ * Returns the current armor value as determined by a call to
+ * InventoryPlayer.getTotalArmorValue
+ */
+ public int getTotalArmorValue() {
+ return this.getSlimeSize() * 3;
+ }
+
+ /**
+ * Gets how bright this entity is.
+ */
+ public float getBrightness(float par1) {
+ return 1.0F;
+ }
+
+ /**
+ * Returns the name of a particle effect that may be randomly created by
+ * EntitySlime.onUpdate()
+ */
+ protected String getSlimeParticle() {
+ return "flame";
+ }
+
+ protected EntitySlime createInstance() {
+ return new EntityMagmaCube(this.worldObj);
+ }
+
+ /**
+ * Returns the item ID for the item the mob drops on death.
+ */
+ protected int getDropItemId() {
+ return Item.magmaCream.itemID;
+ }
+
+ /**
+ * Drop 0-2 items of this living's type
+ */
+ protected void dropFewItems(boolean par1, int par2) {
+ int var3 = this.getDropItemId();
+
+ if (var3 > 0 && this.getSlimeSize() > 1) {
+ int var4 = this.rand.nextInt(4) - 2;
+
+ if (par2 > 0) {
+ var4 += this.rand.nextInt(par2 + 1);
+ }
+
+ for (int var5 = 0; var5 < var4; ++var5) {
+ this.dropItem(var3, 1);
+ }
+ }
+ }
+
+ /**
+ * Returns true if the entity is on fire. Used by render to add the fire effect
+ * on rendering.
+ */
+ public boolean isBurning() {
+ return false;
+ }
+
+ /**
+ * Gets the amount of time the slime needs to wait between jumps.
+ */
+ protected int getJumpDelay() {
+ return super.getJumpDelay() * 4;
+ }
+
+ protected void func_70808_l() {
+ this.field_70813_a *= 0.9F;
+ }
+
+ /**
+ * Causes this entity to do an upwards motion (jumping).
+ */
+ protected void jump() {
+ this.motionY = (double) (0.42F + (float) this.getSlimeSize() * 0.1F);
+ this.isAirBorne = true;
+ }
+
+ /**
+ * Called when the mob is falling. Calculates and applies fall damage.
+ */
+ protected void fall(float par1) {
+ }
+
+ /**
+ * Indicates weather the slime is able to damage the player (based upon the
+ * slime's size)
+ */
+ protected boolean canDamagePlayer() {
+ return true;
+ }
+
+ /**
+ * Gets the amount of damage dealt to the player when "attacked" by the slime.
+ */
+ protected int getAttackStrength() {
+ return super.getAttackStrength() + 2;
+ }
+
+ /**
+ * Returns the sound this mob makes when it is hurt.
+ */
+ protected String getHurtSound() {
+ return "mob.slime." + (this.getSlimeSize() > 1 ? "big" : "small");
+ }
+
+ /**
+ * Returns the sound this mob makes on death.
+ */
+ protected String getDeathSound() {
+ return "mob.slime." + (this.getSlimeSize() > 1 ? "big" : "small");
+ }
+
+ /**
+ * Returns the name of the sound played when the slime jumps.
+ */
+ protected String getJumpSound() {
+ return this.getSlimeSize() > 1 ? "mob.magmacube.big" : "mob.magmacube.small";
+ }
+
+ /**
+ * Whether or not the current entity is in lava
+ */
+ public boolean handleLavaMovement() {
+ return false;
+ }
+
+ /**
+ * Returns true if the slime makes a sound when it lands after a jump (based
+ * upon the slime's size)
+ */
+ protected boolean makesSoundOnLand() {
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityMinecart.java b/sp-server/src/main/java/net/minecraft/src/EntityMinecart.java
new file mode 100644
index 0000000..44391df
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityMinecart.java
@@ -0,0 +1,886 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.minecraft.server.MinecraftServer;
+
+public abstract class EntityMinecart extends Entity {
+ private boolean isInReverse;
+ private final IUpdatePlayerListBox field_82344_g;
+ private String entityName;
+
+ /** Minecart rotational logic matrix */
+ private static final int[][][] matrix = new int[][][] { { { 0, 0, -1 }, { 0, 0, 1 } },
+ { { -1, 0, 0 }, { 1, 0, 0 } }, { { -1, -1, 0 }, { 1, 0, 0 } }, { { -1, 0, 0 }, { 1, -1, 0 } },
+ { { 0, 0, -1 }, { 0, -1, 1 } }, { { 0, -1, -1 }, { 0, 0, 1 } }, { { 0, 0, 1 }, { 1, 0, 0 } },
+ { { 0, 0, 1 }, { -1, 0, 0 } }, { { 0, 0, -1 }, { -1, 0, 0 } }, { { 0, 0, -1 }, { 1, 0, 0 } } };
+
+ /** appears to be the progress of the turn */
+ private int turnProgress;
+ private double minecartX;
+ private double minecartY;
+ private double minecartZ;
+ private double minecartYaw;
+ private double minecartPitch;
+
+ public EntityMinecart(World par1World) {
+ super(par1World);
+ this.isInReverse = false;
+ this.preventEntitySpawning = true;
+ this.setSize(0.98F, 0.7F);
+ this.yOffset = this.height / 2.0F;
+ this.field_82344_g = par1World != null ? par1World.func_82735_a(this) : null;
+ }
+
+ /**
+ * Creates a new minecart of the specified type in the specified location in the
+ * given world. par0World - world to create the minecart in, double
+ * par1,par3,par5 represent x,y,z respectively. int par7 specifies the type: 1
+ * for MinecartChest, 2 for MinecartFurnace, 3 for MinecartTNT, 4 for
+ * MinecartMobSpawner, 5 for MinecartHopper and 0 for a standard empty minecart
+ */
+ public static EntityMinecart createMinecart(World par0World, double par1, double par3, double par5, int par7) {
+ switch (par7) {
+ case 1:
+ return new EntityMinecartChest(par0World, par1, par3, par5);
+
+ case 2:
+ return new EntityMinecartFurnace(par0World, par1, par3, par5);
+
+ case 3:
+ return new EntityMinecartTNT(par0World, par1, par3, par5);
+
+ case 4:
+ return new EntityMinecartMobSpawner(par0World, par1, par3, par5);
+
+ case 5:
+ return new EntityMinecartHopper(par0World, par1, par3, par5);
+
+ default:
+ return new EntityMinecartEmpty(par0World, par1, par3, par5);
+ }
+ }
+
+ /**
+ * returns if this entity triggers Block.onEntityWalking on the blocks they walk
+ * on. used for spiders and wolves to prevent them from trampling crops
+ */
+ protected boolean canTriggerWalking() {
+ return false;
+ }
+
+ protected void entityInit() {
+ this.dataWatcher.addObject(17, Integer.valueOf(0));
+ this.dataWatcher.addObject(18, Integer.valueOf(1));
+ this.dataWatcher.addObject(19, Integer.valueOf(0));
+ this.dataWatcher.addObject(20, Integer.valueOf(0));
+ this.dataWatcher.addObject(21, Integer.valueOf(6));
+ this.dataWatcher.addObject(22, Byte.valueOf((byte) 0));
+ }
+
+ /**
+ * Returns a boundingBox used to collide the entity with other entities and
+ * blocks. This enables the entity to be pushable on contact, like boats or
+ * minecarts.
+ */
+ public AxisAlignedBB getCollisionBox(Entity par1Entity) {
+ return par1Entity.canBePushed() ? par1Entity.boundingBox : null;
+ }
+
+ /**
+ * returns the bounding box for this entity
+ */
+ public AxisAlignedBB getBoundingBox() {
+ return null;
+ }
+
+ /**
+ * Returns true if this entity should push and be pushed by other entities when
+ * colliding.
+ */
+ public boolean canBePushed() {
+ return true;
+ }
+
+ public EntityMinecart(World par1World, double par2, double par4, double par6) {
+ this(par1World);
+ this.setPosition(par2, par4 + (double) this.yOffset, par6);
+ this.motionX = 0.0D;
+ this.motionY = 0.0D;
+ this.motionZ = 0.0D;
+ this.prevPosX = par2;
+ this.prevPosY = par4;
+ this.prevPosZ = par6;
+ }
+
+ /**
+ * Returns the Y offset from the entity's position for any entity riding this
+ * one.
+ */
+ public double getMountedYOffset() {
+ return (double) this.height * 0.0D - 0.30000001192092896D;
+ }
+
+ /**
+ * Called when the entity is attacked.
+ */
+ public boolean attackEntityFrom(DamageSource par1DamageSource, int par2) {
+ if (!this.worldObj.isRemote && !this.isDead) {
+ if (this.isEntityInvulnerable()) {
+ return false;
+ } else {
+ this.setRollingDirection(-this.getRollingDirection());
+ this.setRollingAmplitude(10);
+ this.setBeenAttacked();
+ this.setDamage(this.getDamage() + par2 * 10);
+ boolean var3 = par1DamageSource.getEntity() instanceof EntityPlayer
+ && ((EntityPlayer) par1DamageSource.getEntity()).capabilities.isCreativeMode;
+
+ if (var3 || this.getDamage() > 40) {
+ if (this.riddenByEntity != null) {
+ this.riddenByEntity.mountEntity(this);
+ }
+
+ if (var3 && !this.isInvNameLocalized()) {
+ this.setDead();
+ } else {
+ this.killMinecart(par1DamageSource);
+ }
+ }
+
+ return true;
+ }
+ } else {
+ return true;
+ }
+ }
+
+ public void killMinecart(DamageSource par1DamageSource) {
+ this.setDead();
+ ItemStack var2 = new ItemStack(Item.minecartEmpty, 1);
+
+ if (this.entityName != null) {
+ var2.setItemName(this.entityName);
+ }
+
+ this.entityDropItem(var2, 0.0F);
+ }
+
+ /**
+ * Returns true if other Entities should be prevented from moving through this
+ * Entity.
+ */
+ public boolean canBeCollidedWith() {
+ return !this.isDead;
+ }
+
+ /**
+ * Will get destroyed next tick.
+ */
+ public void setDead() {
+ super.setDead();
+
+ if (this.field_82344_g != null) {
+ this.field_82344_g.update();
+ }
+ }
+
+ /**
+ * Called to update the entity's position/logic.
+ */
+ public void onUpdate() {
+ if (this.field_82344_g != null) {
+ this.field_82344_g.update();
+ }
+
+ if (this.getRollingAmplitude() > 0) {
+ this.setRollingAmplitude(this.getRollingAmplitude() - 1);
+ }
+
+ if (this.getDamage() > 0) {
+ this.setDamage(this.getDamage() - 1);
+ }
+
+ if (this.posY < -64.0D) {
+ this.kill();
+ }
+
+ int var2;
+
+ if (!this.worldObj.isRemote && this.worldObj instanceof WorldServer) {
+ MinecraftServer var1 = ((WorldServer) this.worldObj).getMinecraftServer();
+ var2 = this.getMaxInPortalTime();
+
+ if (this.inPortal) {
+ if (var1.getAllowNether()) {
+ if (this.ridingEntity == null && this.timeInPortal++ >= var2) {
+ this.timeInPortal = var2;
+ this.timeUntilPortal = this.getPortalCooldown();
+ byte var3;
+
+ if (this.worldObj.provider.dimensionId == -1) {
+ var3 = 0;
+ } else {
+ var3 = -1;
+ }
+
+ this.travelToTheEnd(var3);
+ }
+
+ this.inPortal = false;
+ }
+ } else {
+ if (this.timeInPortal > 0) {
+ this.timeInPortal -= 4;
+ }
+
+ if (this.timeInPortal < 0) {
+ this.timeInPortal = 0;
+ }
+ }
+
+ if (this.timeUntilPortal > 0) {
+ --this.timeUntilPortal;
+ }
+ }
+
+ if (this.worldObj.isRemote) {
+ if (this.turnProgress > 0) {
+ double var19 = this.posX + (this.minecartX - this.posX) / (double) this.turnProgress;
+ double var21 = this.posY + (this.minecartY - this.posY) / (double) this.turnProgress;
+ double var5 = this.posZ + (this.minecartZ - this.posZ) / (double) this.turnProgress;
+ double var7 = MathHelper.wrapAngleTo180_double(this.minecartYaw - (double) this.rotationYaw);
+ this.rotationYaw = (float) ((double) this.rotationYaw + var7 / (double) this.turnProgress);
+ this.rotationPitch = (float) ((double) this.rotationPitch
+ + (this.minecartPitch - (double) this.rotationPitch) / (double) this.turnProgress);
+ --this.turnProgress;
+ this.setPosition(var19, var21, var5);
+ this.setRotation(this.rotationYaw, this.rotationPitch);
+ } else {
+ this.setPosition(this.posX, this.posY, this.posZ);
+ this.setRotation(this.rotationYaw, this.rotationPitch);
+ }
+ } else {
+ this.prevPosX = this.posX;
+ this.prevPosY = this.posY;
+ this.prevPosZ = this.posZ;
+ this.motionY -= 0.03999999910593033D;
+ int var18 = MathHelper.floor_double(this.posX);
+ var2 = MathHelper.floor_double(this.posY);
+ int var20 = MathHelper.floor_double(this.posZ);
+
+ if (BlockRailBase.isRailBlockAt(this.worldObj, var18, var2 - 1, var20)) {
+ --var2;
+ }
+
+ double var4 = 0.4D;
+ double var6 = 0.0078125D;
+ int var8 = this.worldObj.getBlockId(var18, var2, var20);
+
+ if (BlockRailBase.isRailBlock(var8)) {
+ int var9 = this.worldObj.getBlockMetadata(var18, var2, var20);
+ this.updateOnTrack(var18, var2, var20, var4, var6, var8, var9);
+
+ if (var8 == Block.railActivator.blockID) {
+ this.onActivatorRailPass(var18, var2, var20, (var9 & 8) != 0);
+ }
+ } else {
+ this.func_94088_b(var4);
+ }
+
+ this.doBlockCollisions();
+ this.rotationPitch = 0.0F;
+ double var22 = this.prevPosX - this.posX;
+ double var11 = this.prevPosZ - this.posZ;
+
+ if (var22 * var22 + var11 * var11 > 0.001D) {
+ this.rotationYaw = (float) (Math.atan2(var11, var22) * 180.0D / Math.PI);
+
+ if (this.isInReverse) {
+ this.rotationYaw += 180.0F;
+ }
+ }
+
+ double var13 = (double) MathHelper.wrapAngleTo180_float(this.rotationYaw - this.prevRotationYaw);
+
+ if (var13 < -170.0D || var13 >= 170.0D) {
+ this.rotationYaw += 180.0F;
+ this.isInReverse = !this.isInReverse;
+ }
+
+ this.setRotation(this.rotationYaw, this.rotationPitch);
+ List var15 = this.worldObj.getEntitiesWithinAABBExcludingEntity(this,
+ this.boundingBox.expand(0.20000000298023224D, 0.0D, 0.20000000298023224D));
+
+ if (var15 != null && !var15.isEmpty()) {
+ for (int var16 = 0; var16 < var15.size(); ++var16) {
+ Entity var17 = (Entity) var15.get(var16);
+
+ if (var17 != this.riddenByEntity && var17.canBePushed() && var17 instanceof EntityMinecart) {
+ var17.applyEntityCollision(this);
+ }
+ }
+ }
+
+ if (this.riddenByEntity != null && this.riddenByEntity.isDead) {
+ if (this.riddenByEntity.ridingEntity == this) {
+ this.riddenByEntity.ridingEntity = null;
+ }
+
+ this.riddenByEntity = null;
+ }
+ }
+ }
+
+ /**
+ * Called every tick the minecart is on an activator rail. Args: x, y, z, is the
+ * rail receiving power
+ */
+ public void onActivatorRailPass(int par1, int par2, int par3, boolean par4) {
+ }
+
+ protected void func_94088_b(double par1) {
+ if (this.motionX < -par1) {
+ this.motionX = -par1;
+ }
+
+ if (this.motionX > par1) {
+ this.motionX = par1;
+ }
+
+ if (this.motionZ < -par1) {
+ this.motionZ = -par1;
+ }
+
+ if (this.motionZ > par1) {
+ this.motionZ = par1;
+ }
+
+ if (this.onGround) {
+ this.motionX *= 0.5D;
+ this.motionY *= 0.5D;
+ this.motionZ *= 0.5D;
+ }
+
+ this.moveEntity(this.motionX, this.motionY, this.motionZ);
+
+ if (!this.onGround) {
+ this.motionX *= 0.949999988079071D;
+ this.motionY *= 0.949999988079071D;
+ this.motionZ *= 0.949999988079071D;
+ }
+ }
+
+ protected void updateOnTrack(int par1, int par2, int par3, double par4, double par6, int par8, int par9) {
+ this.fallDistance = 0.0F;
+ Vec3 var10 = this.func_70489_a(this.posX, this.posY, this.posZ);
+ this.posY = (double) par2;
+ boolean var11 = false;
+ boolean var12 = false;
+
+ if (par8 == Block.railPowered.blockID) {
+ var11 = (par9 & 8) != 0;
+ var12 = !var11;
+ }
+
+ if (((BlockRailBase) Block.blocksList[par8]).isPowered()) {
+ par9 &= 7;
+ }
+
+ if (par9 >= 2 && par9 <= 5) {
+ this.posY = (double) (par2 + 1);
+ }
+
+ if (par9 == 2) {
+ this.motionX -= par6;
+ }
+
+ if (par9 == 3) {
+ this.motionX += par6;
+ }
+
+ if (par9 == 4) {
+ this.motionZ += par6;
+ }
+
+ if (par9 == 5) {
+ this.motionZ -= par6;
+ }
+
+ int[][] var13 = matrix[par9];
+ double var14 = (double) (var13[1][0] - var13[0][0]);
+ double var16 = (double) (var13[1][2] - var13[0][2]);
+ double var18 = Math.sqrt(var14 * var14 + var16 * var16);
+ double var20 = this.motionX * var14 + this.motionZ * var16;
+
+ if (var20 < 0.0D) {
+ var14 = -var14;
+ var16 = -var16;
+ }
+
+ double var22 = Math.sqrt(this.motionX * this.motionX + this.motionZ * this.motionZ);
+
+ if (var22 > 2.0D) {
+ var22 = 2.0D;
+ }
+
+ this.motionX = var22 * var14 / var18;
+ this.motionZ = var22 * var16 / var18;
+ double var24;
+ double var26;
+
+ if (this.riddenByEntity != null) {
+ var24 = this.riddenByEntity.motionX * this.riddenByEntity.motionX
+ + this.riddenByEntity.motionZ * this.riddenByEntity.motionZ;
+ var26 = this.motionX * this.motionX + this.motionZ * this.motionZ;
+
+ if (var24 > 1.0E-4D && var26 < 0.01D) {
+ this.motionX += this.riddenByEntity.motionX * 0.1D;
+ this.motionZ += this.riddenByEntity.motionZ * 0.1D;
+ var12 = false;
+ }
+ }
+
+ if (var12) {
+ var24 = Math.sqrt(this.motionX * this.motionX + this.motionZ * this.motionZ);
+
+ if (var24 < 0.03D) {
+ this.motionX *= 0.0D;
+ this.motionY *= 0.0D;
+ this.motionZ *= 0.0D;
+ } else {
+ this.motionX *= 0.5D;
+ this.motionY *= 0.0D;
+ this.motionZ *= 0.5D;
+ }
+ }
+
+ var24 = 0.0D;
+ var26 = (double) par1 + 0.5D + (double) var13[0][0] * 0.5D;
+ double var28 = (double) par3 + 0.5D + (double) var13[0][2] * 0.5D;
+ double var30 = (double) par1 + 0.5D + (double) var13[1][0] * 0.5D;
+ double var32 = (double) par3 + 0.5D + (double) var13[1][2] * 0.5D;
+ var14 = var30 - var26;
+ var16 = var32 - var28;
+ double var34;
+ double var36;
+
+ if (var14 == 0.0D) {
+ this.posX = (double) par1 + 0.5D;
+ var24 = this.posZ - (double) par3;
+ } else if (var16 == 0.0D) {
+ this.posZ = (double) par3 + 0.5D;
+ var24 = this.posX - (double) par1;
+ } else {
+ var34 = this.posX - var26;
+ var36 = this.posZ - var28;
+ var24 = (var34 * var14 + var36 * var16) * 2.0D;
+ }
+
+ this.posX = var26 + var14 * var24;
+ this.posZ = var28 + var16 * var24;
+ this.setPosition(this.posX, this.posY + (double) this.yOffset, this.posZ);
+ var34 = this.motionX;
+ var36 = this.motionZ;
+
+ if (this.riddenByEntity != null) {
+ var34 *= 0.75D;
+ var36 *= 0.75D;
+ }
+
+ if (var34 < -par4) {
+ var34 = -par4;
+ }
+
+ if (var34 > par4) {
+ var34 = par4;
+ }
+
+ if (var36 < -par4) {
+ var36 = -par4;
+ }
+
+ if (var36 > par4) {
+ var36 = par4;
+ }
+
+ this.moveEntity(var34, 0.0D, var36);
+
+ if (var13[0][1] != 0 && MathHelper.floor_double(this.posX) - par1 == var13[0][0]
+ && MathHelper.floor_double(this.posZ) - par3 == var13[0][2]) {
+ this.setPosition(this.posX, this.posY + (double) var13[0][1], this.posZ);
+ } else if (var13[1][1] != 0 && MathHelper.floor_double(this.posX) - par1 == var13[1][0]
+ && MathHelper.floor_double(this.posZ) - par3 == var13[1][2]) {
+ this.setPosition(this.posX, this.posY + (double) var13[1][1], this.posZ);
+ }
+
+ this.applyDrag();
+ Vec3 var38 = this.func_70489_a(this.posX, this.posY, this.posZ);
+
+ if (var38 != null && var10 != null) {
+ double var39 = (var10.yCoord - var38.yCoord) * 0.05D;
+ var22 = Math.sqrt(this.motionX * this.motionX + this.motionZ * this.motionZ);
+
+ if (var22 > 0.0D) {
+ this.motionX = this.motionX / var22 * (var22 + var39);
+ this.motionZ = this.motionZ / var22 * (var22 + var39);
+ }
+
+ this.setPosition(this.posX, var38.yCoord, this.posZ);
+ }
+
+ int var45 = MathHelper.floor_double(this.posX);
+ int var40 = MathHelper.floor_double(this.posZ);
+
+ if (var45 != par1 || var40 != par3) {
+ var22 = Math.sqrt(this.motionX * this.motionX + this.motionZ * this.motionZ);
+ this.motionX = var22 * (double) (var45 - par1);
+ this.motionZ = var22 * (double) (var40 - par3);
+ }
+
+ if (var11) {
+ double var41 = Math.sqrt(this.motionX * this.motionX + this.motionZ * this.motionZ);
+
+ if (var41 > 0.01D) {
+ double var43 = 0.06D;
+ this.motionX += this.motionX / var41 * var43;
+ this.motionZ += this.motionZ / var41 * var43;
+ } else if (par9 == 1) {
+ if (this.worldObj.isBlockNormalCube(par1 - 1, par2, par3)) {
+ this.motionX = 0.02D;
+ } else if (this.worldObj.isBlockNormalCube(par1 + 1, par2, par3)) {
+ this.motionX = -0.02D;
+ }
+ } else if (par9 == 0) {
+ if (this.worldObj.isBlockNormalCube(par1, par2, par3 - 1)) {
+ this.motionZ = 0.02D;
+ } else if (this.worldObj.isBlockNormalCube(par1, par2, par3 + 1)) {
+ this.motionZ = -0.02D;
+ }
+ }
+ }
+ }
+
+ protected void applyDrag() {
+ if (this.riddenByEntity != null) {
+ this.motionX *= 0.996999979019165D;
+ this.motionY *= 0.0D;
+ this.motionZ *= 0.996999979019165D;
+ } else {
+ this.motionX *= 0.9599999785423279D;
+ this.motionY *= 0.0D;
+ this.motionZ *= 0.9599999785423279D;
+ }
+ }
+
+ public Vec3 func_70489_a(double par1, double par3, double par5) {
+ int var7 = MathHelper.floor_double(par1);
+ int var8 = MathHelper.floor_double(par3);
+ int var9 = MathHelper.floor_double(par5);
+
+ if (BlockRailBase.isRailBlockAt(this.worldObj, var7, var8 - 1, var9)) {
+ --var8;
+ }
+
+ int var10 = this.worldObj.getBlockId(var7, var8, var9);
+
+ if (BlockRailBase.isRailBlock(var10)) {
+ int var11 = this.worldObj.getBlockMetadata(var7, var8, var9);
+ par3 = (double) var8;
+
+ if (((BlockRailBase) Block.blocksList[var10]).isPowered()) {
+ var11 &= 7;
+ }
+
+ if (var11 >= 2 && var11 <= 5) {
+ par3 = (double) (var8 + 1);
+ }
+
+ int[][] var12 = matrix[var11];
+ double var13 = 0.0D;
+ double var15 = (double) var7 + 0.5D + (double) var12[0][0] * 0.5D;
+ double var17 = (double) var8 + 0.5D + (double) var12[0][1] * 0.5D;
+ double var19 = (double) var9 + 0.5D + (double) var12[0][2] * 0.5D;
+ double var21 = (double) var7 + 0.5D + (double) var12[1][0] * 0.5D;
+ double var23 = (double) var8 + 0.5D + (double) var12[1][1] * 0.5D;
+ double var25 = (double) var9 + 0.5D + (double) var12[1][2] * 0.5D;
+ double var27 = var21 - var15;
+ double var29 = (var23 - var17) * 2.0D;
+ double var31 = var25 - var19;
+
+ if (var27 == 0.0D) {
+ par1 = (double) var7 + 0.5D;
+ var13 = par5 - (double) var9;
+ } else if (var31 == 0.0D) {
+ par5 = (double) var9 + 0.5D;
+ var13 = par1 - (double) var7;
+ } else {
+ double var33 = par1 - var15;
+ double var35 = par5 - var19;
+ var13 = (var33 * var27 + var35 * var31) * 2.0D;
+ }
+
+ par1 = var15 + var27 * var13;
+ par3 = var17 + var29 * var13;
+ par5 = var19 + var31 * var13;
+
+ if (var29 < 0.0D) {
+ ++par3;
+ }
+
+ if (var29 > 0.0D) {
+ par3 += 0.5D;
+ }
+
+ return this.worldObj.getWorldVec3Pool().getVecFromPool(par1, par3, par5);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ protected void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ if (par1NBTTagCompound.getBoolean("CustomDisplayTile")) {
+ this.setDisplayTile(par1NBTTagCompound.getInteger("DisplayTile"));
+ this.setDisplayTileData(par1NBTTagCompound.getInteger("DisplayData"));
+ this.setDisplayTileOffset(par1NBTTagCompound.getInteger("DisplayOffset"));
+ }
+
+ if (par1NBTTagCompound.hasKey("CustomName") && par1NBTTagCompound.getString("CustomName").length() > 0) {
+ this.entityName = par1NBTTagCompound.getString("CustomName");
+ }
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ protected void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ if (this.hasDisplayTile()) {
+ par1NBTTagCompound.setBoolean("CustomDisplayTile", true);
+ par1NBTTagCompound.setInteger("DisplayTile",
+ this.getDisplayTile() == null ? 0 : this.getDisplayTile().blockID);
+ par1NBTTagCompound.setInteger("DisplayData", this.getDisplayTileData());
+ par1NBTTagCompound.setInteger("DisplayOffset", this.getDisplayTileOffset());
+ }
+
+ if (this.entityName != null && this.entityName.length() > 0) {
+ par1NBTTagCompound.setString("CustomName", this.entityName);
+ }
+ }
+
+ /**
+ * Applies a velocity to each of the entities pushing them away from each other.
+ * Args: entity
+ */
+ public void applyEntityCollision(Entity par1Entity) {
+ if (!this.worldObj.isRemote) {
+ if (par1Entity != this.riddenByEntity) {
+ if (par1Entity instanceof EntityLiving && !(par1Entity instanceof EntityPlayer)
+ && !(par1Entity instanceof EntityIronGolem) && this.getMinecartType() == 0
+ && this.motionX * this.motionX + this.motionZ * this.motionZ > 0.01D
+ && this.riddenByEntity == null && par1Entity.ridingEntity == null) {
+ par1Entity.mountEntity(this);
+ }
+
+ double var2 = par1Entity.posX - this.posX;
+ double var4 = par1Entity.posZ - this.posZ;
+ double var6 = var2 * var2 + var4 * var4;
+
+ if (var6 >= 9.999999747378752E-5D) {
+ var6 = (double) MathHelper.sqrt_double(var6);
+ var2 /= var6;
+ var4 /= var6;
+ double var8 = 1.0D / var6;
+
+ if (var8 > 1.0D) {
+ var8 = 1.0D;
+ }
+
+ var2 *= var8;
+ var4 *= var8;
+ var2 *= 0.10000000149011612D;
+ var4 *= 0.10000000149011612D;
+ var2 *= (double) (1.0F - this.entityCollisionReduction);
+ var4 *= (double) (1.0F - this.entityCollisionReduction);
+ var2 *= 0.5D;
+ var4 *= 0.5D;
+
+ if (par1Entity instanceof EntityMinecart) {
+ double var10 = par1Entity.posX - this.posX;
+ double var12 = par1Entity.posZ - this.posZ;
+ Vec3 var14 = this.worldObj.getWorldVec3Pool().getVecFromPool(var10, 0.0D, var12).normalize();
+ Vec3 var15 = this.worldObj.getWorldVec3Pool()
+ .getVecFromPool((double) MathHelper.cos(this.rotationYaw * (float) Math.PI / 180.0F),
+ 0.0D, (double) MathHelper.sin(this.rotationYaw * (float) Math.PI / 180.0F))
+ .normalize();
+ double var16 = Math.abs(var14.dotProduct(var15));
+
+ if (var16 < 0.800000011920929D) {
+ return;
+ }
+
+ double var18 = par1Entity.motionX + this.motionX;
+ double var20 = par1Entity.motionZ + this.motionZ;
+
+ if (((EntityMinecart) par1Entity).getMinecartType() == 2 && this.getMinecartType() != 2) {
+ this.motionX *= 0.20000000298023224D;
+ this.motionZ *= 0.20000000298023224D;
+ this.addVelocity(par1Entity.motionX - var2, 0.0D, par1Entity.motionZ - var4);
+ par1Entity.motionX *= 0.949999988079071D;
+ par1Entity.motionZ *= 0.949999988079071D;
+ } else if (((EntityMinecart) par1Entity).getMinecartType() != 2
+ && this.getMinecartType() == 2) {
+ par1Entity.motionX *= 0.20000000298023224D;
+ par1Entity.motionZ *= 0.20000000298023224D;
+ par1Entity.addVelocity(this.motionX + var2, 0.0D, this.motionZ + var4);
+ this.motionX *= 0.949999988079071D;
+ this.motionZ *= 0.949999988079071D;
+ } else {
+ var18 /= 2.0D;
+ var20 /= 2.0D;
+ this.motionX *= 0.20000000298023224D;
+ this.motionZ *= 0.20000000298023224D;
+ this.addVelocity(var18 - var2, 0.0D, var20 - var4);
+ par1Entity.motionX *= 0.20000000298023224D;
+ par1Entity.motionZ *= 0.20000000298023224D;
+ par1Entity.addVelocity(var18 + var2, 0.0D, var20 + var4);
+ }
+ } else {
+ this.addVelocity(-var2, 0.0D, -var4);
+ par1Entity.addVelocity(var2 / 4.0D, 0.0D, var4 / 4.0D);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Sets the current amount of damage the minecart has taken. Decreases over
+ * time. The cart breaks when this is over 40.
+ */
+ public void setDamage(int par1) {
+ this.dataWatcher.updateObject(19, Integer.valueOf(par1));
+ }
+
+ /**
+ * Gets the current amount of damage the minecart has taken. Decreases over
+ * time. The cart breaks when this is over 40.
+ */
+ public int getDamage() {
+ return this.dataWatcher.getWatchableObjectInt(19);
+ }
+
+ /**
+ * Sets the rolling amplitude the cart rolls while being attacked.
+ */
+ public void setRollingAmplitude(int par1) {
+ this.dataWatcher.updateObject(17, Integer.valueOf(par1));
+ }
+
+ /**
+ * Gets the rolling amplitude the cart rolls while being attacked.
+ */
+ public int getRollingAmplitude() {
+ return this.dataWatcher.getWatchableObjectInt(17);
+ }
+
+ /**
+ * Sets the rolling direction the cart rolls while being attacked. Can be 1 or
+ * -1.
+ */
+ public void setRollingDirection(int par1) {
+ this.dataWatcher.updateObject(18, Integer.valueOf(par1));
+ }
+
+ /**
+ * Gets the rolling direction the cart rolls while being attacked. Can be 1 or
+ * -1.
+ */
+ public int getRollingDirection() {
+ return this.dataWatcher.getWatchableObjectInt(18);
+ }
+
+ public abstract int getMinecartType();
+
+ public Block getDisplayTile() {
+ if (!this.hasDisplayTile()) {
+ return this.getDefaultDisplayTile();
+ } else {
+ int var1 = this.getDataWatcher().getWatchableObjectInt(20) & 65535;
+ return var1 > 0 && var1 < Block.blocksList.length ? Block.blocksList[var1] : null;
+ }
+ }
+
+ public Block getDefaultDisplayTile() {
+ return null;
+ }
+
+ public int getDisplayTileData() {
+ return !this.hasDisplayTile() ? this.getDefaultDisplayTileData()
+ : this.getDataWatcher().getWatchableObjectInt(20) >> 16;
+ }
+
+ public int getDefaultDisplayTileData() {
+ return 0;
+ }
+
+ public int getDisplayTileOffset() {
+ return !this.hasDisplayTile() ? this.getDefaultDisplayTileOffset()
+ : this.getDataWatcher().getWatchableObjectInt(21);
+ }
+
+ public int getDefaultDisplayTileOffset() {
+ return 6;
+ }
+
+ public void setDisplayTile(int par1) {
+ this.getDataWatcher().updateObject(20, Integer.valueOf(par1 & 65535 | this.getDisplayTileData() << 16));
+ this.setHasDisplayTile(true);
+ }
+
+ public void setDisplayTileData(int par1) {
+ Block var2 = this.getDisplayTile();
+ int var3 = var2 == null ? 0 : var2.blockID;
+ this.getDataWatcher().updateObject(20, Integer.valueOf(var3 & 65535 | par1 << 16));
+ this.setHasDisplayTile(true);
+ }
+
+ public void setDisplayTileOffset(int par1) {
+ this.getDataWatcher().updateObject(21, Integer.valueOf(par1));
+ this.setHasDisplayTile(true);
+ }
+
+ public boolean hasDisplayTile() {
+ return this.getDataWatcher().getWatchableObjectByte(22) == 1;
+ }
+
+ public void setHasDisplayTile(boolean par1) {
+ this.getDataWatcher().updateObject(22, Byte.valueOf((byte) (par1 ? 1 : 0)));
+ }
+
+ public void func_96094_a(String par1Str) {
+ this.entityName = par1Str;
+ }
+
+ /**
+ * Gets the username of the entity.
+ */
+ public String getEntityName() {
+ return this.entityName != null ? this.entityName : super.getEntityName();
+ }
+
+ /**
+ * If this returns false, the inventory name will be used as an unlocalized
+ * name, and translated into the player's language. Otherwise it will be used
+ * directly.
+ */
+ public boolean isInvNameLocalized() {
+ return this.entityName != null;
+ }
+
+ public String func_95999_t() {
+ return this.entityName;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityMinecartChest.java b/sp-server/src/main/java/net/minecraft/src/EntityMinecartChest.java
new file mode 100644
index 0000000..caf61c6
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityMinecartChest.java
@@ -0,0 +1,35 @@
+package net.minecraft.src;
+
+public class EntityMinecartChest extends EntityMinecartContainer {
+ public EntityMinecartChest(World par1World) {
+ super(par1World);
+ }
+
+ public EntityMinecartChest(World par1, double par2, double par4, double par6) {
+ super(par1, par2, par4, par6);
+ }
+
+ public void killMinecart(DamageSource par1DamageSource) {
+ super.killMinecart(par1DamageSource);
+ this.dropItemWithOffset(Block.chest.blockID, 1, 0.0F);
+ }
+
+ /**
+ * Returns the number of slots in the inventory.
+ */
+ public int getSizeInventory() {
+ return 27;
+ }
+
+ public int getMinecartType() {
+ return 1;
+ }
+
+ public Block getDefaultDisplayTile() {
+ return Block.chest;
+ }
+
+ public int getDefaultDisplayTileOffset() {
+ return 8;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityMinecartContainer.java b/sp-server/src/main/java/net/minecraft/src/EntityMinecartContainer.java
new file mode 100644
index 0000000..35bbda1
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityMinecartContainer.java
@@ -0,0 +1,256 @@
+package net.minecraft.src;
+
+public abstract class EntityMinecartContainer extends EntityMinecart implements IInventory {
+ private ItemStack[] minecartContainerItems = new ItemStack[36];
+
+ /**
+ * Whether the minecart should not drop its content when flagged as dead.
+ */
+ private boolean preventContentDropping = true;
+
+ public EntityMinecartContainer(World par1World) {
+ super(par1World);
+ }
+
+ public EntityMinecartContainer(World par1World, double par2, double par4, double par6) {
+ super(par1World, par2, par4, par6);
+ }
+
+ public void killMinecart(DamageSource par1DamageSource) {
+ super.killMinecart(par1DamageSource);
+
+ for (int var2 = 0; var2 < this.getSizeInventory(); ++var2) {
+ ItemStack var3 = this.getStackInSlot(var2);
+
+ if (var3 != null) {
+ float var4 = this.rand.nextFloat() * 0.8F + 0.1F;
+ float var5 = this.rand.nextFloat() * 0.8F + 0.1F;
+ float var6 = this.rand.nextFloat() * 0.8F + 0.1F;
+
+ while (var3.stackSize > 0) {
+ int var7 = this.rand.nextInt(21) + 10;
+
+ if (var7 > var3.stackSize) {
+ var7 = var3.stackSize;
+ }
+
+ var3.stackSize -= var7;
+ EntityItem var8 = new EntityItem(this.worldObj, this.posX + (double) var4,
+ this.posY + (double) var5, this.posZ + (double) var6,
+ new ItemStack(var3.itemID, var7, var3.getItemDamage()));
+ float var9 = 0.05F;
+ var8.motionX = (double) ((float) this.rand.nextGaussian() * var9);
+ var8.motionY = (double) ((float) this.rand.nextGaussian() * var9 + 0.2F);
+ var8.motionZ = (double) ((float) this.rand.nextGaussian() * var9);
+ this.worldObj.spawnEntityInWorld(var8);
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the stack in slot i
+ */
+ public ItemStack getStackInSlot(int par1) {
+ return this.minecartContainerItems[par1];
+ }
+
+ /**
+ * Removes from an inventory slot (first arg) up to a specified number (second
+ * arg) of items and returns them in a new stack.
+ */
+ public ItemStack decrStackSize(int par1, int par2) {
+ if (this.minecartContainerItems[par1] != null) {
+ ItemStack var3;
+
+ if (this.minecartContainerItems[par1].stackSize <= par2) {
+ var3 = this.minecartContainerItems[par1];
+ this.minecartContainerItems[par1] = null;
+ return var3;
+ } else {
+ var3 = this.minecartContainerItems[par1].splitStack(par2);
+
+ if (this.minecartContainerItems[par1].stackSize == 0) {
+ this.minecartContainerItems[par1] = null;
+ }
+
+ return var3;
+ }
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * When some containers are closed they call this on each slot, then drop
+ * whatever it returns as an EntityItem - like when you close a workbench GUI.
+ */
+ public ItemStack getStackInSlotOnClosing(int par1) {
+ if (this.minecartContainerItems[par1] != null) {
+ ItemStack var2 = this.minecartContainerItems[par1];
+ this.minecartContainerItems[par1] = null;
+ return var2;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Sets the given item stack to the specified slot in the inventory (can be
+ * crafting or armor sections).
+ */
+ public void setInventorySlotContents(int par1, ItemStack par2ItemStack) {
+ this.minecartContainerItems[par1] = par2ItemStack;
+
+ if (par2ItemStack != null && par2ItemStack.stackSize > this.getInventoryStackLimit()) {
+ par2ItemStack.stackSize = this.getInventoryStackLimit();
+ }
+ }
+
+ /**
+ * Called when an the contents of an Inventory change, usually
+ */
+ public void onInventoryChanged() {
+ }
+
+ /**
+ * Do not make give this method the name canInteractWith because it clashes with
+ * Container
+ */
+ public boolean isUseableByPlayer(EntityPlayer par1EntityPlayer) {
+ return this.isDead ? false : par1EntityPlayer.getDistanceSqToEntity(this) <= 64.0D;
+ }
+
+ public void openChest() {
+ }
+
+ public void closeChest() {
+ }
+
+ /**
+ * Returns true if automation is allowed to insert the given stack (ignoring
+ * stack size) into the given slot.
+ */
+ public boolean isStackValidForSlot(int par1, ItemStack par2ItemStack) {
+ return true;
+ }
+
+ /**
+ * Returns the name of the inventory.
+ */
+ public String getInvName() {
+ return this.isInvNameLocalized() ? this.func_95999_t() : "container.minecart";
+ }
+
+ /**
+ * Returns the maximum stack size for a inventory slot. Seems to always be 64,
+ * possibly will be extended. *Isn't this more of a set than a get?*
+ */
+ public int getInventoryStackLimit() {
+ return 64;
+ }
+
+ public void travelToTheEnd(int par1) {
+ this.preventContentDropping = false;
+ super.travelToTheEnd(par1);
+ }
+
+ /**
+ * Will get destroyed next tick.
+ */
+ public void setDead() {
+ if (this.preventContentDropping) {
+ for (int var1 = 0; var1 < this.getSizeInventory(); ++var1) {
+ ItemStack var2 = this.getStackInSlot(var1);
+
+ if (var2 != null) {
+ float var3 = this.rand.nextFloat() * 0.8F + 0.1F;
+ float var4 = this.rand.nextFloat() * 0.8F + 0.1F;
+ float var5 = this.rand.nextFloat() * 0.8F + 0.1F;
+
+ while (var2.stackSize > 0) {
+ int var6 = this.rand.nextInt(21) + 10;
+
+ if (var6 > var2.stackSize) {
+ var6 = var2.stackSize;
+ }
+
+ var2.stackSize -= var6;
+ EntityItem var7 = new EntityItem(this.worldObj, this.posX + (double) var3,
+ this.posY + (double) var4, this.posZ + (double) var5,
+ new ItemStack(var2.itemID, var6, var2.getItemDamage()));
+
+ if (var2.hasTagCompound()) {
+ var7.getEntityItem().setTagCompound((NBTTagCompound) var2.getTagCompound().copy());
+ }
+
+ float var8 = 0.05F;
+ var7.motionX = (double) ((float) this.rand.nextGaussian() * var8);
+ var7.motionY = (double) ((float) this.rand.nextGaussian() * var8 + 0.2F);
+ var7.motionZ = (double) ((float) this.rand.nextGaussian() * var8);
+ this.worldObj.spawnEntityInWorld(var7);
+ }
+ }
+ }
+ }
+
+ super.setDead();
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ protected void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ super.writeEntityToNBT(par1NBTTagCompound);
+ NBTTagList var2 = new NBTTagList();
+
+ for (int var3 = 0; var3 < this.minecartContainerItems.length; ++var3) {
+ if (this.minecartContainerItems[var3] != null) {
+ NBTTagCompound var4 = new NBTTagCompound();
+ var4.setByte("Slot", (byte) var3);
+ this.minecartContainerItems[var3].writeToNBT(var4);
+ var2.appendTag(var4);
+ }
+ }
+
+ par1NBTTagCompound.setTag("Items", var2);
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ protected void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ super.readEntityFromNBT(par1NBTTagCompound);
+ NBTTagList var2 = par1NBTTagCompound.getTagList("Items");
+ this.minecartContainerItems = new ItemStack[this.getSizeInventory()];
+
+ for (int var3 = 0; var3 < var2.tagCount(); ++var3) {
+ NBTTagCompound var4 = (NBTTagCompound) var2.tagAt(var3);
+ int var5 = var4.getByte("Slot") & 255;
+
+ if (var5 >= 0 && var5 < this.minecartContainerItems.length) {
+ this.minecartContainerItems[var5] = ItemStack.loadItemStackFromNBT(var4);
+ }
+ }
+ }
+
+ /**
+ * Called when a player interacts with a mob. e.g. gets milk from a cow, gets
+ * into the saddle on a pig.
+ */
+ public boolean interact(EntityPlayer par1EntityPlayer) {
+ if (!this.worldObj.isRemote) {
+ par1EntityPlayer.displayGUIChest(this);
+ }
+
+ return true;
+ }
+
+ protected void applyDrag() {
+ int var1 = 15 - Container.calcRedstoneFromInventory(this);
+ float var2 = 0.98F + (float) var1 * 0.001F;
+ this.motionX *= (double) var2;
+ this.motionY *= 0.0D;
+ this.motionZ *= (double) var2;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityMinecartEmpty.java b/sp-server/src/main/java/net/minecraft/src/EntityMinecartEmpty.java
new file mode 100644
index 0000000..575208f
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityMinecartEmpty.java
@@ -0,0 +1,34 @@
+package net.minecraft.src;
+
+public class EntityMinecartEmpty extends EntityMinecart {
+ public EntityMinecartEmpty(World par1World) {
+ super(par1World);
+ }
+
+ public EntityMinecartEmpty(World par1, double par2, double par4, double par6) {
+ super(par1, par2, par4, par6);
+ }
+
+ /**
+ * Called when a player interacts with a mob. e.g. gets milk from a cow, gets
+ * into the saddle on a pig.
+ */
+ public boolean interact(EntityPlayer par1EntityPlayer) {
+ if (this.riddenByEntity != null && this.riddenByEntity instanceof EntityPlayer
+ && this.riddenByEntity != par1EntityPlayer) {
+ return true;
+ } else if (this.riddenByEntity != null && this.riddenByEntity != par1EntityPlayer) {
+ return false;
+ } else {
+ if (!this.worldObj.isRemote) {
+ par1EntityPlayer.mountEntity(this);
+ }
+
+ return true;
+ }
+ }
+
+ public int getMinecartType() {
+ return 0;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityMinecartFurnace.java b/sp-server/src/main/java/net/minecraft/src/EntityMinecartFurnace.java
new file mode 100644
index 0000000..db8d4e1
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityMinecartFurnace.java
@@ -0,0 +1,155 @@
+package net.minecraft.src;
+
+public class EntityMinecartFurnace extends EntityMinecart {
+ private int fuel = 0;
+ public double pushX;
+ public double pushZ;
+
+ public EntityMinecartFurnace(World par1World) {
+ super(par1World);
+ }
+
+ public EntityMinecartFurnace(World par1World, double par2, double par4, double par6) {
+ super(par1World, par2, par4, par6);
+ }
+
+ public int getMinecartType() {
+ return 2;
+ }
+
+ protected void entityInit() {
+ super.entityInit();
+ this.dataWatcher.addObject(16, Byte.valueOf((byte) 0));
+ }
+
+ /**
+ * Called to update the entity's position/logic.
+ */
+ public void onUpdate() {
+ super.onUpdate();
+
+ if (this.fuel > 0) {
+ --this.fuel;
+ }
+
+ if (this.fuel <= 0) {
+ this.pushX = this.pushZ = 0.0D;
+ }
+
+ this.setMinecartPowered(this.fuel > 0);
+
+ if (this.isMinecartPowered() && this.rand.nextInt(4) == 0) {
+ this.worldObj.spawnParticle("largesmoke", this.posX, this.posY + 0.8D, this.posZ, 0.0D, 0.0D, 0.0D);
+ }
+ }
+
+ public void killMinecart(DamageSource par1DamageSource) {
+ super.killMinecart(par1DamageSource);
+
+ if (!par1DamageSource.isExplosion()) {
+ this.entityDropItem(new ItemStack(Block.furnaceIdle, 1), 0.0F);
+ }
+ }
+
+ protected void updateOnTrack(int par1, int par2, int par3, double par4, double par6, int par8, int par9) {
+ super.updateOnTrack(par1, par2, par3, par4, par6, par8, par9);
+ double var10 = this.pushX * this.pushX + this.pushZ * this.pushZ;
+
+ if (var10 > 1.0E-4D && this.motionX * this.motionX + this.motionZ * this.motionZ > 0.001D) {
+ var10 = (double) MathHelper.sqrt_double(var10);
+ this.pushX /= var10;
+ this.pushZ /= var10;
+
+ if (this.pushX * this.motionX + this.pushZ * this.motionZ < 0.0D) {
+ this.pushX = 0.0D;
+ this.pushZ = 0.0D;
+ } else {
+ this.pushX = this.motionX;
+ this.pushZ = this.motionZ;
+ }
+ }
+ }
+
+ protected void applyDrag() {
+ double var1 = this.pushX * this.pushX + this.pushZ * this.pushZ;
+
+ if (var1 > 1.0E-4D) {
+ var1 = (double) MathHelper.sqrt_double(var1);
+ this.pushX /= var1;
+ this.pushZ /= var1;
+ double var3 = 0.05D;
+ this.motionX *= 0.800000011920929D;
+ this.motionY *= 0.0D;
+ this.motionZ *= 0.800000011920929D;
+ this.motionX += this.pushX * var3;
+ this.motionZ += this.pushZ * var3;
+ } else {
+ this.motionX *= 0.9800000190734863D;
+ this.motionY *= 0.0D;
+ this.motionZ *= 0.9800000190734863D;
+ }
+
+ super.applyDrag();
+ }
+
+ /**
+ * Called when a player interacts with a mob. e.g. gets milk from a cow, gets
+ * into the saddle on a pig.
+ */
+ public boolean interact(EntityPlayer par1EntityPlayer) {
+ ItemStack var2 = par1EntityPlayer.inventory.getCurrentItem();
+
+ if (var2 != null && var2.itemID == Item.coal.itemID) {
+ if (--var2.stackSize == 0) {
+ par1EntityPlayer.inventory.setInventorySlotContents(par1EntityPlayer.inventory.currentItem,
+ (ItemStack) null);
+ }
+
+ this.fuel += 3600;
+ }
+
+ this.pushX = this.posX - par1EntityPlayer.posX;
+ this.pushZ = this.posZ - par1EntityPlayer.posZ;
+ return true;
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ protected void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ super.writeEntityToNBT(par1NBTTagCompound);
+ par1NBTTagCompound.setDouble("PushX", this.pushX);
+ par1NBTTagCompound.setDouble("PushZ", this.pushZ);
+ par1NBTTagCompound.setShort("Fuel", (short) this.fuel);
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ protected void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ super.readEntityFromNBT(par1NBTTagCompound);
+ this.pushX = par1NBTTagCompound.getDouble("PushX");
+ this.pushZ = par1NBTTagCompound.getDouble("PushZ");
+ this.fuel = par1NBTTagCompound.getShort("Fuel");
+ }
+
+ protected boolean isMinecartPowered() {
+ return (this.dataWatcher.getWatchableObjectByte(16) & 1) != 0;
+ }
+
+ protected void setMinecartPowered(boolean par1) {
+ if (par1) {
+ this.dataWatcher.updateObject(16, Byte.valueOf((byte) (this.dataWatcher.getWatchableObjectByte(16) | 1)));
+ } else {
+ this.dataWatcher.updateObject(16, Byte.valueOf((byte) (this.dataWatcher.getWatchableObjectByte(16) & -2)));
+ }
+ }
+
+ public Block getDefaultDisplayTile() {
+ return Block.furnaceBurning;
+ }
+
+ public int getDefaultDisplayTileData() {
+ return 2;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityMinecartHopper.java b/sp-server/src/main/java/net/minecraft/src/EntityMinecartHopper.java
new file mode 100644
index 0000000..592044a
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityMinecartHopper.java
@@ -0,0 +1,172 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+public class EntityMinecartHopper extends EntityMinecartContainer implements Hopper {
+ /** Whether this hopper minecart is being blocked by an activator rail. */
+ private boolean isBlocked = true;
+ private int transferTicker = -1;
+
+ public EntityMinecartHopper(World par1World) {
+ super(par1World);
+ }
+
+ public EntityMinecartHopper(World par1World, double par2, double par4, double par6) {
+ super(par1World, par2, par4, par6);
+ }
+
+ public int getMinecartType() {
+ return 5;
+ }
+
+ public Block getDefaultDisplayTile() {
+ return Block.hopperBlock;
+ }
+
+ public int getDefaultDisplayTileOffset() {
+ return 1;
+ }
+
+ /**
+ * Returns the number of slots in the inventory.
+ */
+ public int getSizeInventory() {
+ return 5;
+ }
+
+ /**
+ * Called when a player interacts with a mob. e.g. gets milk from a cow, gets
+ * into the saddle on a pig.
+ */
+ public boolean interact(EntityPlayer par1EntityPlayer) {
+ if (!this.worldObj.isRemote) {
+ par1EntityPlayer.displayGUIHopperMinecart(this);
+ }
+
+ return true;
+ }
+
+ /**
+ * Called every tick the minecart is on an activator rail. Args: x, y, z, is the
+ * rail receiving power
+ */
+ public void onActivatorRailPass(int par1, int par2, int par3, boolean par4) {
+ boolean var5 = !par4;
+
+ if (var5 != this.getBlocked()) {
+ this.setBlocked(var5);
+ }
+ }
+
+ /**
+ * Get whether this hopper minecart is being blocked by an activator rail.
+ */
+ public boolean getBlocked() {
+ return this.isBlocked;
+ }
+
+ /**
+ * Set whether this hopper minecart is being blocked by an activator rail.
+ */
+ public void setBlocked(boolean par1) {
+ this.isBlocked = par1;
+ }
+
+ /**
+ * Returns the worldObj for this tileEntity.
+ */
+ public World getWorldObj() {
+ return this.worldObj;
+ }
+
+ /**
+ * Gets the world X position for this hopper entity.
+ */
+ public double getXPos() {
+ return this.posX;
+ }
+
+ /**
+ * Gets the world Y position for this hopper entity.
+ */
+ public double getYPos() {
+ return this.posY;
+ }
+
+ /**
+ * Gets the world Z position for this hopper entity.
+ */
+ public double getZPos() {
+ return this.posZ;
+ }
+
+ /**
+ * Called to update the entity's position/logic.
+ */
+ public void onUpdate() {
+ super.onUpdate();
+
+ if (!this.worldObj.isRemote && this.isEntityAlive() && this.getBlocked()) {
+ --this.transferTicker;
+
+ if (!this.canTransfer()) {
+ this.setTransferTicker(0);
+
+ if (this.func_96112_aD()) {
+ this.setTransferTicker(4);
+ this.onInventoryChanged();
+ }
+ }
+ }
+ }
+
+ public boolean func_96112_aD() {
+ if (TileEntityHopper.suckItemsIntoHopper(this)) {
+ return true;
+ } else {
+ List var1 = this.worldObj.selectEntitiesWithinAABB(EntityItem.class,
+ this.boundingBox.expand(0.25D, 0.0D, 0.25D), IEntitySelector.selectAnything);
+
+ if (var1.size() > 0) {
+ TileEntityHopper.func_96114_a(this, (EntityItem) var1.get(0));
+ }
+
+ return false;
+ }
+ }
+
+ public void killMinecart(DamageSource par1DamageSource) {
+ super.killMinecart(par1DamageSource);
+ this.dropItemWithOffset(Block.hopperBlock.blockID, 1, 0.0F);
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ protected void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ super.writeEntityToNBT(par1NBTTagCompound);
+ par1NBTTagCompound.setInteger("TransferCooldown", this.transferTicker);
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ protected void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ super.readEntityFromNBT(par1NBTTagCompound);
+ this.transferTicker = par1NBTTagCompound.getInteger("TransferCooldown");
+ }
+
+ /**
+ * Sets the transfer ticker, used to determine the delay between transfers.
+ */
+ public void setTransferTicker(int par1) {
+ this.transferTicker = par1;
+ }
+
+ /**
+ * Returns whether the hopper cart can currently transfer an item.
+ */
+ public boolean canTransfer() {
+ return this.transferTicker > 0;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityMinecartMobSpawner.java b/sp-server/src/main/java/net/minecraft/src/EntityMinecartMobSpawner.java
new file mode 100644
index 0000000..8276dcb
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityMinecartMobSpawner.java
@@ -0,0 +1,46 @@
+package net.minecraft.src;
+
+public class EntityMinecartMobSpawner extends EntityMinecart {
+ /** Mob spawner logic for this spawner minecart. */
+ private final MobSpawnerBaseLogic mobSpawnerLogic = new EntityMinecartMobSpawnerLogic(this);
+
+ public EntityMinecartMobSpawner(World par1World) {
+ super(par1World);
+ }
+
+ public EntityMinecartMobSpawner(World par1World, double par2, double par4, double par6) {
+ super(par1World, par2, par4, par6);
+ }
+
+ public int getMinecartType() {
+ return 4;
+ }
+
+ public Block getDefaultDisplayTile() {
+ return Block.mobSpawner;
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ protected void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ super.readEntityFromNBT(par1NBTTagCompound);
+ this.mobSpawnerLogic.readFromNBT(par1NBTTagCompound);
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ protected void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ super.writeEntityToNBT(par1NBTTagCompound);
+ this.mobSpawnerLogic.writeToNBT(par1NBTTagCompound);
+ }
+
+ /**
+ * Called to update the entity's position/logic.
+ */
+ public void onUpdate() {
+ super.onUpdate();
+ this.mobSpawnerLogic.updateSpawner();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityMinecartMobSpawnerLogic.java b/sp-server/src/main/java/net/minecraft/src/EntityMinecartMobSpawnerLogic.java
new file mode 100644
index 0000000..ff71e7e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityMinecartMobSpawnerLogic.java
@@ -0,0 +1,30 @@
+package net.minecraft.src;
+
+class EntityMinecartMobSpawnerLogic extends MobSpawnerBaseLogic {
+ /** The spawner minecart using this mob spawner logic. */
+ final EntityMinecartMobSpawner spawnerMinecart;
+
+ EntityMinecartMobSpawnerLogic(EntityMinecartMobSpawner par1EntityMinecartMobSpawner) {
+ this.spawnerMinecart = par1EntityMinecartMobSpawner;
+ }
+
+ public void func_98267_a(int par1) {
+ this.spawnerMinecart.worldObj.setEntityState(this.spawnerMinecart, (byte) par1);
+ }
+
+ public World getSpawnerWorld() {
+ return this.spawnerMinecart.worldObj;
+ }
+
+ public int getSpawnerX() {
+ return MathHelper.floor_double(this.spawnerMinecart.posX);
+ }
+
+ public int getSpawnerY() {
+ return MathHelper.floor_double(this.spawnerMinecart.posY);
+ }
+
+ public int getSpawnerZ() {
+ return MathHelper.floor_double(this.spawnerMinecart.posZ);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityMinecartTNT.java b/sp-server/src/main/java/net/minecraft/src/EntityMinecartTNT.java
new file mode 100644
index 0000000..bc35bf2
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityMinecartTNT.java
@@ -0,0 +1,147 @@
+package net.minecraft.src;
+
+public class EntityMinecartTNT extends EntityMinecart {
+ private int minecartTNTFuse = -1;
+
+ public EntityMinecartTNT(World par1) {
+ super(par1);
+ }
+
+ public EntityMinecartTNT(World par1, double par2, double par4, double par6) {
+ super(par1, par2, par4, par6);
+ }
+
+ public int getMinecartType() {
+ return 3;
+ }
+
+ public Block getDefaultDisplayTile() {
+ return Block.tnt;
+ }
+
+ /**
+ * Called to update the entity's position/logic.
+ */
+ public void onUpdate() {
+ super.onUpdate();
+
+ if (this.minecartTNTFuse > 0) {
+ --this.minecartTNTFuse;
+ this.worldObj.spawnParticle("smoke", this.posX, this.posY + 0.5D, this.posZ, 0.0D, 0.0D, 0.0D);
+ } else if (this.minecartTNTFuse == 0) {
+ this.explodeCart(this.motionX * this.motionX + this.motionZ * this.motionZ);
+ }
+
+ if (this.isCollidedHorizontally) {
+ double var1 = this.motionX * this.motionX + this.motionZ * this.motionZ;
+
+ if (var1 >= 0.009999999776482582D) {
+ this.explodeCart(var1);
+ }
+ }
+ }
+
+ public void killMinecart(DamageSource par1DamageSource) {
+ super.killMinecart(par1DamageSource);
+ double var2 = this.motionX * this.motionX + this.motionZ * this.motionZ;
+
+ if (!par1DamageSource.isExplosion()) {
+ this.entityDropItem(new ItemStack(Block.tnt, 1), 0.0F);
+ }
+
+ if (par1DamageSource.isFireDamage() || par1DamageSource.isExplosion() || var2 >= 0.009999999776482582D) {
+ this.explodeCart(var2);
+ }
+ }
+
+ /**
+ * Makes the minecart explode.
+ */
+ protected void explodeCart(double par1) {
+ if (!this.worldObj.isRemote) {
+ double var3 = Math.sqrt(par1);
+
+ if (var3 > 5.0D) {
+ var3 = 5.0D;
+ }
+
+ this.worldObj.createExplosion(this, this.posX, this.posY, this.posZ,
+ (float) (4.0D + this.rand.nextDouble() * 1.5D * var3), true);
+ this.setDead();
+ }
+ }
+
+ /**
+ * Called when the mob is falling. Calculates and applies fall damage.
+ */
+ protected void fall(float par1) {
+ if (par1 >= 3.0F) {
+ float var2 = par1 / 10.0F;
+ this.explodeCart((double) (var2 * var2));
+ }
+
+ super.fall(par1);
+ }
+
+ /**
+ * Called every tick the minecart is on an activator rail. Args: x, y, z, is the
+ * rail receiving power
+ */
+ public void onActivatorRailPass(int par1, int par2, int par3, boolean par4) {
+ if (par4 && this.minecartTNTFuse < 0) {
+ this.ignite();
+ }
+ }
+
+ /**
+ * Ignites this TNT cart.
+ */
+ public void ignite() {
+ this.minecartTNTFuse = 80;
+
+ if (!this.worldObj.isRemote) {
+ this.worldObj.setEntityState(this, (byte) 10);
+ this.worldObj.playSoundAtEntity(this, "random.fuse", 1.0F, 1.0F);
+ }
+ }
+
+ /**
+ * Returns true if the TNT minecart is ignited.
+ */
+ public boolean isIgnited() {
+ return this.minecartTNTFuse > -1;
+ }
+
+ public float func_82146_a(Explosion par1Explosion, World par2World, int par3, int par4, int par5, Block par6Block) {
+ return this.isIgnited() && (BlockRailBase.isRailBlock(par6Block.blockID)
+ || BlockRailBase.isRailBlockAt(par2World, par3, par4 + 1, par5)) ? 0.0F
+ : super.func_82146_a(par1Explosion, par2World, par3, par4, par5, par6Block);
+ }
+
+ public boolean func_96091_a(Explosion par1Explosion, World par2World, int par3, int par4, int par5, int par6,
+ float par7) {
+ return this.isIgnited()
+ && (BlockRailBase.isRailBlock(par6) || BlockRailBase.isRailBlockAt(par2World, par3, par4 + 1, par5))
+ ? false
+ : super.func_96091_a(par1Explosion, par2World, par3, par4, par5, par6, par7);
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ protected void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ super.readEntityFromNBT(par1NBTTagCompound);
+
+ if (par1NBTTagCompound.hasKey("TNTFuse")) {
+ this.minecartTNTFuse = par1NBTTagCompound.getInteger("TNTFuse");
+ }
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ protected void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ super.writeEntityToNBT(par1NBTTagCompound);
+ par1NBTTagCompound.setInteger("TNTFuse", this.minecartTNTFuse);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityMob.java b/sp-server/src/main/java/net/minecraft/src/EntityMob.java
new file mode 100644
index 0000000..25b3a46
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityMob.java
@@ -0,0 +1,170 @@
+package net.minecraft.src;
+
+public abstract class EntityMob extends EntityCreature implements IMob {
+ public EntityMob(World par1World) {
+ super(par1World);
+ this.experienceValue = 5;
+ }
+
+ /**
+ * Called frequently so the entity can update its state every tick as required.
+ * For example, zombies and skeletons use this to react to sunlight and start to
+ * burn.
+ */
+ public void onLivingUpdate() {
+ this.updateArmSwingProgress();
+ float var1 = this.getBrightness(1.0F);
+
+ if (var1 > 0.5F) {
+ this.entityAge += 2;
+ }
+
+ super.onLivingUpdate();
+ }
+
+ /**
+ * Called to update the entity's position/logic.
+ */
+ public void onUpdate() {
+ super.onUpdate();
+
+ if (!this.worldObj.isRemote && this.worldObj.difficultySetting == 0) {
+ this.setDead();
+ }
+ }
+
+ /**
+ * Finds the closest player within 16 blocks to attack, or null if this Entity
+ * isn't interested in attacking (Animals, Spiders at day, peaceful PigZombies).
+ */
+ protected Entity findPlayerToAttack() {
+ EntityPlayer var1 = this.worldObj.getClosestVulnerablePlayerToEntity(this, 16.0D);
+ return var1 != null && this.canEntityBeSeen(var1) ? var1 : null;
+ }
+
+ /**
+ * Called when the entity is attacked.
+ */
+ public boolean attackEntityFrom(DamageSource par1DamageSource, int par2) {
+ if (this.isEntityInvulnerable()) {
+ return false;
+ } else if (super.attackEntityFrom(par1DamageSource, par2)) {
+ Entity var3 = par1DamageSource.getEntity();
+
+ if (this.riddenByEntity != var3 && this.ridingEntity != var3) {
+ if (var3 != this) {
+ this.entityToAttack = var3;
+ }
+
+ return true;
+ } else {
+ return true;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ public boolean attackEntityAsMob(Entity par1Entity) {
+ int var2 = this.getAttackStrength(par1Entity);
+
+ if (this.isPotionActive(Potion.damageBoost)) {
+ var2 += 3 << this.getActivePotionEffect(Potion.damageBoost).getAmplifier();
+ }
+
+ if (this.isPotionActive(Potion.weakness)) {
+ var2 -= 2 << this.getActivePotionEffect(Potion.weakness).getAmplifier();
+ }
+
+ int var3 = 0;
+
+ if (par1Entity instanceof EntityLiving) {
+ var2 += EnchantmentHelper.getEnchantmentModifierLiving(this, (EntityLiving) par1Entity);
+ var3 += EnchantmentHelper.getKnockbackModifier(this, (EntityLiving) par1Entity);
+ }
+
+ boolean var4 = par1Entity.attackEntityFrom(DamageSource.causeMobDamage(this), var2);
+
+ if (var4) {
+ if (var3 > 0) {
+ par1Entity.addVelocity(
+ (double) (-MathHelper.sin(this.rotationYaw * (float) Math.PI / 180.0F) * (float) var3 * 0.5F),
+ 0.1D,
+ (double) (MathHelper.cos(this.rotationYaw * (float) Math.PI / 180.0F) * (float) var3 * 0.5F));
+ this.motionX *= 0.6D;
+ this.motionZ *= 0.6D;
+ }
+
+ int var5 = EnchantmentHelper.getFireAspectModifier(this);
+
+ if (var5 > 0) {
+ par1Entity.setFire(var5 * 4);
+ }
+
+ if (par1Entity instanceof EntityLiving) {
+ EnchantmentThorns.func_92096_a(this, (EntityLiving) par1Entity, this.rand);
+ }
+ }
+
+ return var4;
+ }
+
+ /**
+ * Basic mob attack. Default to touch of death in EntityCreature. Overridden by
+ * each mob to define their attack.
+ */
+ protected void attackEntity(Entity par1Entity, float par2) {
+ if (this.attackTime <= 0 && par2 < 2.0F && par1Entity.boundingBox.maxY > this.boundingBox.minY
+ && par1Entity.boundingBox.minY < this.boundingBox.maxY) {
+ this.attackTime = 20;
+ this.attackEntityAsMob(par1Entity);
+ }
+ }
+
+ /**
+ * Takes a coordinate in and returns a weight to determine how likely this
+ * creature will try to path to the block. Args: x, y, z
+ */
+ public float getBlockPathWeight(int par1, int par2, int par3) {
+ return 0.5F - this.worldObj.getLightBrightness(par1, par2, par3);
+ }
+
+ /**
+ * Checks to make sure the light is not too bright where the mob is spawning
+ */
+ protected boolean isValidLightLevel() {
+ int var1 = MathHelper.floor_double(this.posX);
+ int var2 = MathHelper.floor_double(this.boundingBox.minY);
+ int var3 = MathHelper.floor_double(this.posZ);
+
+ if (this.worldObj.getSavedLightValue(EnumSkyBlock.Sky, var1, var2, var3) > this.rand.nextInt(32)) {
+ return false;
+ } else {
+ int var4 = this.worldObj.getBlockLightValue(var1, var2, var3);
+
+ if (this.worldObj.isThundering()) {
+ int var5 = this.worldObj.skylightSubtracted;
+ this.worldObj.skylightSubtracted = 10;
+ var4 = this.worldObj.getBlockLightValue(var1, var2, var3);
+ this.worldObj.skylightSubtracted = var5;
+ }
+
+ return var4 <= this.rand.nextInt(8);
+ }
+ }
+
+ /**
+ * Checks if the entity's current position is a valid location to spawn this
+ * entity.
+ */
+ public boolean getCanSpawnHere() {
+ return this.isValidLightLevel() && super.getCanSpawnHere();
+ }
+
+ /**
+ * Returns the amount of damage a mob should deal.
+ */
+ public int getAttackStrength(Entity par1Entity) {
+ return 2;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityMooshroom.java b/sp-server/src/main/java/net/minecraft/src/EntityMooshroom.java
new file mode 100644
index 0000000..55d9552
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityMooshroom.java
@@ -0,0 +1,70 @@
+package net.minecraft.src;
+
+public class EntityMooshroom extends EntityCow {
+ public EntityMooshroom(World par1World) {
+ super(par1World);
+ this.texture = "/mob/redcow.png";
+ this.setSize(0.9F, 1.3F);
+ }
+
+ /**
+ * Called when a player interacts with a mob. e.g. gets milk from a cow, gets
+ * into the saddle on a pig.
+ */
+ public boolean interact(EntityPlayer par1EntityPlayer) {
+ ItemStack var2 = par1EntityPlayer.inventory.getCurrentItem();
+
+ if (var2 != null && var2.itemID == Item.bowlEmpty.itemID && this.getGrowingAge() >= 0) {
+ if (var2.stackSize == 1) {
+ par1EntityPlayer.inventory.setInventorySlotContents(par1EntityPlayer.inventory.currentItem,
+ new ItemStack(Item.bowlSoup));
+ return true;
+ }
+
+ if (par1EntityPlayer.inventory.addItemStackToInventory(new ItemStack(Item.bowlSoup))
+ && !par1EntityPlayer.capabilities.isCreativeMode) {
+ par1EntityPlayer.inventory.decrStackSize(par1EntityPlayer.inventory.currentItem, 1);
+ return true;
+ }
+ }
+
+ if (var2 != null && var2.itemID == Item.shears.itemID && this.getGrowingAge() >= 0) {
+ this.setDead();
+ this.worldObj.spawnParticle("largeexplode", this.posX, this.posY + (double) (this.height / 2.0F), this.posZ,
+ 0.0D, 0.0D, 0.0D);
+
+ if (!this.worldObj.isRemote) {
+ EntityCow var3 = new EntityCow(this.worldObj);
+ var3.setLocationAndAngles(this.posX, this.posY, this.posZ, this.rotationYaw, this.rotationPitch);
+ var3.setEntityHealth(this.getHealth());
+ var3.renderYawOffset = this.renderYawOffset;
+ this.worldObj.spawnEntityInWorld(var3);
+
+ for (int var4 = 0; var4 < 5; ++var4) {
+ this.worldObj.spawnEntityInWorld(new EntityItem(this.worldObj, this.posX,
+ this.posY + (double) this.height, this.posZ, new ItemStack(Block.mushroomRed)));
+ }
+ }
+
+ return true;
+ } else {
+ return super.interact(par1EntityPlayer);
+ }
+ }
+
+ public EntityMooshroom func_94900_c(EntityAgeable par1EntityAgeable) {
+ return new EntityMooshroom(this.worldObj);
+ }
+
+ /**
+ * This function is used when two same-species animals in 'love mode' breed to
+ * generate the new baby animal.
+ */
+ public EntityCow spawnBabyAnimal(EntityAgeable par1EntityAgeable) {
+ return this.func_94900_c(par1EntityAgeable);
+ }
+
+ public EntityAgeable createChild(EntityAgeable par1EntityAgeable) {
+ return this.func_94900_c(par1EntityAgeable);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityMoveHelper.java b/sp-server/src/main/java/net/minecraft/src/EntityMoveHelper.java
new file mode 100644
index 0000000..64fec06
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityMoveHelper.java
@@ -0,0 +1,79 @@
+package net.minecraft.src;
+
+public class EntityMoveHelper {
+ /** The EntityLiving that is being moved */
+ private EntityLiving entity;
+ private double posX;
+ private double posY;
+ private double posZ;
+
+ /** The speed at which the entity should move */
+ private float speed;
+ private boolean update = false;
+
+ public EntityMoveHelper(EntityLiving par1EntityLiving) {
+ this.entity = par1EntityLiving;
+ this.posX = par1EntityLiving.posX;
+ this.posY = par1EntityLiving.posY;
+ this.posZ = par1EntityLiving.posZ;
+ }
+
+ public boolean isUpdating() {
+ return this.update;
+ }
+
+ public float getSpeed() {
+ return this.speed;
+ }
+
+ /**
+ * Sets the speed and location to move to
+ */
+ public void setMoveTo(double par1, double par3, double par5, float par7) {
+ this.posX = par1;
+ this.posY = par3;
+ this.posZ = par5;
+ this.speed = par7;
+ this.update = true;
+ }
+
+ public void onUpdateMoveHelper() {
+ this.entity.setMoveForward(0.0F);
+
+ if (this.update) {
+ this.update = false;
+ int var1 = MathHelper.floor_double(this.entity.boundingBox.minY + 0.5D);
+ double var2 = this.posX - this.entity.posX;
+ double var4 = this.posZ - this.entity.posZ;
+ double var6 = this.posY - (double) var1;
+ double var8 = var2 * var2 + var6 * var6 + var4 * var4;
+
+ if (var8 >= 2.500000277905201E-7D) {
+ float var10 = (float) (Math.atan2(var4, var2) * 180.0D / Math.PI) - 90.0F;
+ this.entity.rotationYaw = this.limitAngle(this.entity.rotationYaw, var10, 30.0F);
+ this.entity.setAIMoveSpeed(this.speed * this.entity.getSpeedModifier());
+
+ if (var6 > 0.0D && var2 * var2 + var4 * var4 < 1.0D) {
+ this.entity.getJumpHelper().setJumping();
+ }
+ }
+ }
+ }
+
+ /**
+ * Limits the given angle to a upper and lower limit.
+ */
+ private float limitAngle(float par1, float par2, float par3) {
+ float var4 = MathHelper.wrapAngleTo180_float(par2 - par1);
+
+ if (var4 > par3) {
+ var4 = par3;
+ }
+
+ if (var4 < -par3) {
+ var4 = -par3;
+ }
+
+ return par1 + var4;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityOcelot.java b/sp-server/src/main/java/net/minecraft/src/EntityOcelot.java
new file mode 100644
index 0000000..e7ed760
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityOcelot.java
@@ -0,0 +1,301 @@
+package net.minecraft.src;
+
+public class EntityOcelot extends EntityTameable {
+ /**
+ * The tempt AI task for this mob, used to prevent taming while it is fleeing.
+ */
+ private EntityAITempt aiTempt;
+
+ public EntityOcelot(World par1World) {
+ super(par1World);
+ this.texture = "/mob/ozelot.png";
+ this.setSize(0.6F, 0.8F);
+ this.getNavigator().setAvoidsWater(true);
+ this.tasks.addTask(1, new EntityAISwimming(this));
+ this.tasks.addTask(2, this.aiSit);
+ this.tasks.addTask(3, this.aiTempt = new EntityAITempt(this, 0.18F, Item.fishRaw.itemID, true));
+ this.tasks.addTask(4, new EntityAIAvoidEntity(this, EntityPlayer.class, 16.0F, 0.23F, 0.4F));
+ this.tasks.addTask(5, new EntityAIFollowOwner(this, 0.3F, 10.0F, 5.0F));
+ this.tasks.addTask(6, new EntityAIOcelotSit(this, 0.4F));
+ this.tasks.addTask(7, new EntityAILeapAtTarget(this, 0.3F));
+ this.tasks.addTask(8, new EntityAIOcelotAttack(this));
+ this.tasks.addTask(9, new EntityAIMate(this, 0.23F));
+ this.tasks.addTask(10, new EntityAIWander(this, 0.23F));
+ this.tasks.addTask(11, new EntityAIWatchClosest(this, EntityPlayer.class, 10.0F));
+ this.targetTasks.addTask(1, new EntityAITargetNonTamed(this, EntityChicken.class, 14.0F, 750, false));
+ }
+
+ protected void entityInit() {
+ super.entityInit();
+ this.dataWatcher.addObject(18, Byte.valueOf((byte) 0));
+ }
+
+ /**
+ * main AI tick function, replaces updateEntityActionState
+ */
+ public void updateAITick() {
+ if (this.getMoveHelper().isUpdating()) {
+ float var1 = this.getMoveHelper().getSpeed();
+
+ if (var1 == 0.18F) {
+ this.setSneaking(true);
+ this.setSprinting(false);
+ } else if (var1 == 0.4F) {
+ this.setSneaking(false);
+ this.setSprinting(true);
+ } else {
+ this.setSneaking(false);
+ this.setSprinting(false);
+ }
+ } else {
+ this.setSneaking(false);
+ this.setSprinting(false);
+ }
+ }
+
+ /**
+ * Determines if an entity can be despawned, used on idle far away entities
+ */
+ protected boolean canDespawn() {
+ return !this.isTamed();
+ }
+
+ /**
+ * Returns true if the newer Entity AI code should be run
+ */
+ public boolean isAIEnabled() {
+ return true;
+ }
+
+ public int getMaxHealth() {
+ return 10;
+ }
+
+ /**
+ * Called when the mob is falling. Calculates and applies fall damage.
+ */
+ protected void fall(float par1) {
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ super.writeEntityToNBT(par1NBTTagCompound);
+ par1NBTTagCompound.setInteger("CatType", this.getTameSkin());
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ super.readEntityFromNBT(par1NBTTagCompound);
+ this.setTameSkin(par1NBTTagCompound.getInteger("CatType"));
+ }
+
+ /**
+ * Returns the sound this mob makes while it's alive.
+ */
+ protected String getLivingSound() {
+ return this.isTamed()
+ ? (this.isInLove() ? "mob.cat.purr" : (this.rand.nextInt(4) == 0 ? "mob.cat.purreow" : "mob.cat.meow"))
+ : "";
+ }
+
+ /**
+ * Returns the sound this mob makes when it is hurt.
+ */
+ protected String getHurtSound() {
+ return "mob.cat.hitt";
+ }
+
+ /**
+ * Returns the sound this mob makes on death.
+ */
+ protected String getDeathSound() {
+ return "mob.cat.hitt";
+ }
+
+ /**
+ * Returns the volume for the sounds this mob makes.
+ */
+ protected float getSoundVolume() {
+ return 0.4F;
+ }
+
+ /**
+ * Returns the item ID for the item the mob drops on death.
+ */
+ protected int getDropItemId() {
+ return Item.leather.itemID;
+ }
+
+ public boolean attackEntityAsMob(Entity par1Entity) {
+ return par1Entity.attackEntityFrom(DamageSource.causeMobDamage(this), 3);
+ }
+
+ /**
+ * Called when the entity is attacked.
+ */
+ public boolean attackEntityFrom(DamageSource par1DamageSource, int par2) {
+ if (this.isEntityInvulnerable()) {
+ return false;
+ } else {
+ this.aiSit.setSitting(false);
+ return super.attackEntityFrom(par1DamageSource, par2);
+ }
+ }
+
+ /**
+ * Drop 0-2 items of this living's type
+ */
+ protected void dropFewItems(boolean par1, int par2) {
+ }
+
+ /**
+ * Called when a player interacts with a mob. e.g. gets milk from a cow, gets
+ * into the saddle on a pig.
+ */
+ public boolean interact(EntityPlayer par1EntityPlayer) {
+ ItemStack var2 = par1EntityPlayer.inventory.getCurrentItem();
+
+ if (this.isTamed()) {
+ if (par1EntityPlayer.username.equalsIgnoreCase(this.getOwnerName()) && !this.worldObj.isRemote
+ && !this.isBreedingItem(var2)) {
+ this.aiSit.setSitting(!this.isSitting());
+ }
+ } else if (this.aiTempt.func_75277_f() && var2 != null && var2.itemID == Item.fishRaw.itemID
+ && par1EntityPlayer.getDistanceSqToEntity(this) < 9.0D) {
+ if (!par1EntityPlayer.capabilities.isCreativeMode) {
+ --var2.stackSize;
+ }
+
+ if (var2.stackSize <= 0) {
+ par1EntityPlayer.inventory.setInventorySlotContents(par1EntityPlayer.inventory.currentItem,
+ (ItemStack) null);
+ }
+
+ if (!this.worldObj.isRemote) {
+ if (this.rand.nextInt(3) == 0) {
+ this.setTamed(true);
+ this.setTameSkin(1 + this.worldObj.rand.nextInt(3));
+ this.setOwner(par1EntityPlayer.username);
+ this.playTameEffect(true);
+ this.aiSit.setSitting(true);
+ this.worldObj.setEntityState(this, (byte) 7);
+ } else {
+ this.playTameEffect(false);
+ this.worldObj.setEntityState(this, (byte) 6);
+ }
+ }
+
+ return true;
+ }
+
+ return super.interact(par1EntityPlayer);
+ }
+
+ /**
+ * This function is used when two same-species animals in 'love mode' breed to
+ * generate the new baby animal.
+ */
+ public EntityOcelot spawnBabyAnimal(EntityAgeable par1EntityAgeable) {
+ EntityOcelot var2 = new EntityOcelot(this.worldObj);
+
+ if (this.isTamed()) {
+ var2.setOwner(this.getOwnerName());
+ var2.setTamed(true);
+ var2.setTameSkin(this.getTameSkin());
+ }
+
+ return var2;
+ }
+
+ /**
+ * Checks if the parameter is an item which this animal can be fed to breed it
+ * (wheat, carrots or seeds depending on the animal type)
+ */
+ public boolean isBreedingItem(ItemStack par1ItemStack) {
+ return par1ItemStack != null && par1ItemStack.itemID == Item.fishRaw.itemID;
+ }
+
+ /**
+ * Returns true if the mob is currently able to mate with the specified mob.
+ */
+ public boolean canMateWith(EntityAnimal par1EntityAnimal) {
+ if (par1EntityAnimal == this) {
+ return false;
+ } else if (!this.isTamed()) {
+ return false;
+ } else if (!(par1EntityAnimal instanceof EntityOcelot)) {
+ return false;
+ } else {
+ EntityOcelot var2 = (EntityOcelot) par1EntityAnimal;
+ return !var2.isTamed() ? false : this.isInLove() && var2.isInLove();
+ }
+ }
+
+ public int getTameSkin() {
+ return this.dataWatcher.getWatchableObjectByte(18);
+ }
+
+ public void setTameSkin(int par1) {
+ this.dataWatcher.updateObject(18, Byte.valueOf((byte) par1));
+ }
+
+ /**
+ * Checks if the entity's current position is a valid location to spawn this
+ * entity.
+ */
+ public boolean getCanSpawnHere() {
+ if (this.worldObj.rand.nextInt(3) == 0) {
+ return false;
+ } else {
+ if (this.worldObj.checkNoEntityCollision(this.boundingBox)
+ && this.worldObj.getCollidingBoundingBoxes(this, this.boundingBox).isEmpty()
+ && !this.worldObj.isAnyLiquid(this.boundingBox)) {
+ int var1 = MathHelper.floor_double(this.posX);
+ int var2 = MathHelper.floor_double(this.boundingBox.minY);
+ int var3 = MathHelper.floor_double(this.posZ);
+
+ if (var2 < 63) {
+ return false;
+ }
+
+ int var4 = this.worldObj.getBlockId(var1, var2 - 1, var3);
+
+ if (var4 == Block.grass.blockID || var4 == Block.leaves.blockID) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+ }
+
+ /**
+ * Gets the username of the entity.
+ */
+ public String getEntityName() {
+ return this.func_94056_bM() ? this.func_94057_bL()
+ : (this.isTamed() ? "entity.Cat.name" : super.getEntityName());
+ }
+
+ /**
+ * Initialize this creature.
+ */
+ public void initCreature() {
+ if (this.worldObj.rand.nextInt(7) == 0) {
+ for (int var1 = 0; var1 < 2; ++var1) {
+ EntityOcelot var2 = new EntityOcelot(this.worldObj);
+ var2.setLocationAndAngles(this.posX, this.posY, this.posZ, this.rotationYaw, 0.0F);
+ var2.setGrowingAge(-24000);
+ this.worldObj.spawnEntityInWorld(var2);
+ }
+ }
+ }
+
+ public EntityAgeable createChild(EntityAgeable par1EntityAgeable) {
+ return this.spawnBabyAnimal(par1EntityAgeable);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityPainting.java b/sp-server/src/main/java/net/minecraft/src/EntityPainting.java
new file mode 100644
index 0000000..879ab62
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityPainting.java
@@ -0,0 +1,80 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+
+public class EntityPainting extends EntityHanging {
+ public EnumArt art;
+
+ public EntityPainting(World par1World) {
+ super(par1World);
+ }
+
+ public EntityPainting(World par1World, int par2, int par3, int par4, int par5) {
+ super(par1World, par2, par3, par4, par5);
+ ArrayList var6 = new ArrayList();
+ EnumArt[] var7 = EnumArt.values();
+ int var8 = var7.length;
+
+ for (int var9 = 0; var9 < var8; ++var9) {
+ EnumArt var10 = var7[var9];
+ this.art = var10;
+ this.setDirection(par5);
+
+ if (this.onValidSurface()) {
+ var6.add(var10);
+ }
+ }
+
+ if (!var6.isEmpty()) {
+ this.art = (EnumArt) var6.get(this.rand.nextInt(var6.size()));
+ }
+
+ this.setDirection(par5);
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ par1NBTTagCompound.setString("Motive", this.art.title);
+ super.writeEntityToNBT(par1NBTTagCompound);
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ String var2 = par1NBTTagCompound.getString("Motive");
+ EnumArt[] var3 = EnumArt.values();
+ int var4 = var3.length;
+
+ for (int var5 = 0; var5 < var4; ++var5) {
+ EnumArt var6 = var3[var5];
+
+ if (var6.title.equals(var2)) {
+ this.art = var6;
+ }
+ }
+
+ if (this.art == null) {
+ this.art = EnumArt.Kebab;
+ }
+
+ super.readEntityFromNBT(par1NBTTagCompound);
+ }
+
+ public int func_82329_d() {
+ return this.art.sizeX;
+ }
+
+ public int func_82330_g() {
+ return this.art.sizeY;
+ }
+
+ /**
+ * Drop the item currently on this item frame.
+ */
+ public void dropItemStack() {
+ this.entityDropItem(new ItemStack(Item.painting), 0.0F);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityPig.java b/sp-server/src/main/java/net/minecraft/src/EntityPig.java
new file mode 100644
index 0000000..6f35887
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityPig.java
@@ -0,0 +1,208 @@
+package net.minecraft.src;
+
+public class EntityPig extends EntityAnimal {
+ /** AI task for player control. */
+ private final EntityAIControlledByPlayer aiControlledByPlayer;
+
+ public EntityPig(World par1World) {
+ super(par1World);
+ this.texture = "/mob/pig.png";
+ this.setSize(0.9F, 0.9F);
+ this.getNavigator().setAvoidsWater(true);
+ float var2 = 0.25F;
+ this.tasks.addTask(0, new EntityAISwimming(this));
+ this.tasks.addTask(1, new EntityAIPanic(this, 0.38F));
+ this.tasks.addTask(2, this.aiControlledByPlayer = new EntityAIControlledByPlayer(this, 0.34F));
+ this.tasks.addTask(3, new EntityAIMate(this, var2));
+ this.tasks.addTask(4, new EntityAITempt(this, 0.3F, Item.carrotOnAStick.itemID, false));
+ this.tasks.addTask(4, new EntityAITempt(this, 0.3F, Item.carrot.itemID, false));
+ this.tasks.addTask(5, new EntityAIFollowParent(this, 0.28F));
+ this.tasks.addTask(6, new EntityAIWander(this, var2));
+ this.tasks.addTask(7, new EntityAIWatchClosest(this, EntityPlayer.class, 6.0F));
+ this.tasks.addTask(8, new EntityAILookIdle(this));
+ }
+
+ /**
+ * Returns true if the newer Entity AI code should be run
+ */
+ public boolean isAIEnabled() {
+ return true;
+ }
+
+ public int getMaxHealth() {
+ return 10;
+ }
+
+ protected void updateAITasks() {
+ super.updateAITasks();
+ }
+
+ /**
+ * returns true if all the conditions for steering the entity are met. For pigs,
+ * this is true if it is being ridden by a player and the player is holding a
+ * carrot-on-a-stick
+ */
+ public boolean canBeSteered() {
+ ItemStack var1 = ((EntityPlayer) this.riddenByEntity).getHeldItem();
+ return var1 != null && var1.itemID == Item.carrotOnAStick.itemID;
+ }
+
+ protected void entityInit() {
+ super.entityInit();
+ this.dataWatcher.addObject(16, Byte.valueOf((byte) 0));
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ super.writeEntityToNBT(par1NBTTagCompound);
+ par1NBTTagCompound.setBoolean("Saddle", this.getSaddled());
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ super.readEntityFromNBT(par1NBTTagCompound);
+ this.setSaddled(par1NBTTagCompound.getBoolean("Saddle"));
+ }
+
+ /**
+ * Returns the sound this mob makes while it's alive.
+ */
+ protected String getLivingSound() {
+ return "mob.pig.say";
+ }
+
+ /**
+ * Returns the sound this mob makes when it is hurt.
+ */
+ protected String getHurtSound() {
+ return "mob.pig.say";
+ }
+
+ /**
+ * Returns the sound this mob makes on death.
+ */
+ protected String getDeathSound() {
+ return "mob.pig.death";
+ }
+
+ /**
+ * Plays step sound at given x, y, z for the entity
+ */
+ protected void playStepSound(int par1, int par2, int par3, int par4) {
+ this.playSound("mob.pig.step", 0.15F, 1.0F);
+ }
+
+ /**
+ * Called when a player interacts with a mob. e.g. gets milk from a cow, gets
+ * into the saddle on a pig.
+ */
+ public boolean interact(EntityPlayer par1EntityPlayer) {
+ if (super.interact(par1EntityPlayer)) {
+ return true;
+ } else if (this.getSaddled() && !this.worldObj.isRemote
+ && (this.riddenByEntity == null || this.riddenByEntity == par1EntityPlayer)) {
+ par1EntityPlayer.mountEntity(this);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Returns the item ID for the item the mob drops on death.
+ */
+ protected int getDropItemId() {
+ return this.isBurning() ? Item.porkCooked.itemID : Item.porkRaw.itemID;
+ }
+
+ /**
+ * Drop 0-2 items of this living's type
+ */
+ protected void dropFewItems(boolean par1, int par2) {
+ int var3 = this.rand.nextInt(3) + 1 + this.rand.nextInt(1 + par2);
+
+ for (int var4 = 0; var4 < var3; ++var4) {
+ if (this.isBurning()) {
+ this.dropItem(Item.porkCooked.itemID, 1);
+ } else {
+ this.dropItem(Item.porkRaw.itemID, 1);
+ }
+ }
+
+ if (this.getSaddled()) {
+ this.dropItem(Item.saddle.itemID, 1);
+ }
+ }
+
+ /**
+ * Returns true if the pig is saddled.
+ */
+ public boolean getSaddled() {
+ return (this.dataWatcher.getWatchableObjectByte(16) & 1) != 0;
+ }
+
+ /**
+ * Set or remove the saddle of the pig.
+ */
+ public void setSaddled(boolean par1) {
+ if (par1) {
+ this.dataWatcher.updateObject(16, Byte.valueOf((byte) 1));
+ } else {
+ this.dataWatcher.updateObject(16, Byte.valueOf((byte) 0));
+ }
+ }
+
+ /**
+ * Called when a lightning bolt hits the entity.
+ */
+ public void onStruckByLightning(EntityLightningBolt par1EntityLightningBolt) {
+ if (!this.worldObj.isRemote) {
+ EntityPigZombie var2 = new EntityPigZombie(this.worldObj);
+ var2.setLocationAndAngles(this.posX, this.posY, this.posZ, this.rotationYaw, this.rotationPitch);
+ this.worldObj.spawnEntityInWorld(var2);
+ this.setDead();
+ }
+ }
+
+ /**
+ * Called when the mob is falling. Calculates and applies fall damage.
+ */
+ protected void fall(float par1) {
+ super.fall(par1);
+
+ if (par1 > 5.0F && this.riddenByEntity instanceof EntityPlayer) {
+ ((EntityPlayer) this.riddenByEntity).triggerAchievement(AchievementList.flyPig);
+ }
+ }
+
+ /**
+ * This function is used when two same-species animals in 'love mode' breed to
+ * generate the new baby animal.
+ */
+ public EntityPig spawnBabyAnimal(EntityAgeable par1EntityAgeable) {
+ return new EntityPig(this.worldObj);
+ }
+
+ /**
+ * Checks if the parameter is an item which this animal can be fed to breed it
+ * (wheat, carrots or seeds depending on the animal type)
+ */
+ public boolean isBreedingItem(ItemStack par1ItemStack) {
+ return par1ItemStack != null && par1ItemStack.itemID == Item.carrot.itemID;
+ }
+
+ /**
+ * Return the AI task for player control.
+ */
+ public EntityAIControlledByPlayer getAIControlledByPlayer() {
+ return this.aiControlledByPlayer;
+ }
+
+ public EntityAgeable createChild(EntityAgeable par1EntityAgeable) {
+ return this.spawnBabyAnimal(par1EntityAgeable);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityPigZombie.java b/sp-server/src/main/java/net/minecraft/src/EntityPigZombie.java
new file mode 100644
index 0000000..d1574a0
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityPigZombie.java
@@ -0,0 +1,199 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+public class EntityPigZombie extends EntityZombie {
+ /** Above zero if this PigZombie is Angry. */
+ private int angerLevel = 0;
+
+ /** A random delay until this PigZombie next makes a sound. */
+ private int randomSoundDelay = 0;
+
+ public EntityPigZombie(World par1World) {
+ super(par1World);
+ this.texture = "/mob/pigzombie.png";
+ this.moveSpeed = 0.5F;
+ this.isImmuneToFire = true;
+ }
+
+ /**
+ * Returns true if the newer Entity AI code should be run
+ */
+ protected boolean isAIEnabled() {
+ return false;
+ }
+
+ /**
+ * Called to update the entity's position/logic.
+ */
+ public void onUpdate() {
+ this.moveSpeed = this.entityToAttack != null ? 0.95F : 0.5F;
+
+ if (this.randomSoundDelay > 0 && --this.randomSoundDelay == 0) {
+ this.playSound("mob.zombiepig.zpigangry", this.getSoundVolume() * 2.0F,
+ ((this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F + 1.0F) * 1.8F);
+ }
+
+ super.onUpdate();
+ }
+
+ /**
+ * Checks if the entity's current position is a valid location to spawn this
+ * entity.
+ */
+ public boolean getCanSpawnHere() {
+ return this.worldObj.difficultySetting > 0 && this.worldObj.checkNoEntityCollision(this.boundingBox)
+ && this.worldObj.getCollidingBoundingBoxes(this, this.boundingBox).isEmpty()
+ && !this.worldObj.isAnyLiquid(this.boundingBox);
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ super.writeEntityToNBT(par1NBTTagCompound);
+ par1NBTTagCompound.setShort("Anger", (short) this.angerLevel);
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ super.readEntityFromNBT(par1NBTTagCompound);
+ this.angerLevel = par1NBTTagCompound.getShort("Anger");
+ }
+
+ /**
+ * Finds the closest player within 16 blocks to attack, or null if this Entity
+ * isn't interested in attacking (Animals, Spiders at day, peaceful PigZombies).
+ */
+ protected Entity findPlayerToAttack() {
+ return this.angerLevel == 0 ? null : super.findPlayerToAttack();
+ }
+
+ /**
+ * Called when the entity is attacked.
+ */
+ public boolean attackEntityFrom(DamageSource par1DamageSource, int par2) {
+ if (this.isEntityInvulnerable()) {
+ return false;
+ } else {
+ Entity var3 = par1DamageSource.getEntity();
+
+ if (var3 instanceof EntityPlayer) {
+ List var4 = this.worldObj.getEntitiesWithinAABBExcludingEntity(this,
+ this.boundingBox.expand(32.0D, 32.0D, 32.0D));
+
+ for (int var5 = 0; var5 < var4.size(); ++var5) {
+ Entity var6 = (Entity) var4.get(var5);
+
+ if (var6 instanceof EntityPigZombie) {
+ EntityPigZombie var7 = (EntityPigZombie) var6;
+ var7.becomeAngryAt(var3);
+ }
+ }
+
+ this.becomeAngryAt(var3);
+ }
+
+ return super.attackEntityFrom(par1DamageSource, par2);
+ }
+ }
+
+ /**
+ * Causes this PigZombie to become angry at the supplied Entity (which will be a
+ * player).
+ */
+ private void becomeAngryAt(Entity par1Entity) {
+ this.entityToAttack = par1Entity;
+ this.angerLevel = 400 + this.rand.nextInt(400);
+ this.randomSoundDelay = this.rand.nextInt(40);
+ }
+
+ /**
+ * Returns the sound this mob makes while it's alive.
+ */
+ protected String getLivingSound() {
+ return "mob.zombiepig.zpig";
+ }
+
+ /**
+ * Returns the sound this mob makes when it is hurt.
+ */
+ protected String getHurtSound() {
+ return "mob.zombiepig.zpighurt";
+ }
+
+ /**
+ * Returns the sound this mob makes on death.
+ */
+ protected String getDeathSound() {
+ return "mob.zombiepig.zpigdeath";
+ }
+
+ /**
+ * Drop 0-2 items of this living's type
+ */
+ protected void dropFewItems(boolean par1, int par2) {
+ int var3 = this.rand.nextInt(2 + par2);
+ int var4;
+
+ for (var4 = 0; var4 < var3; ++var4) {
+ this.dropItem(Item.rottenFlesh.itemID, 1);
+ }
+
+ var3 = this.rand.nextInt(2 + par2);
+
+ for (var4 = 0; var4 < var3; ++var4) {
+ this.dropItem(Item.goldNugget.itemID, 1);
+ }
+ }
+
+ /**
+ * Called when a player interacts with a mob. e.g. gets milk from a cow, gets
+ * into the saddle on a pig.
+ */
+ public boolean interact(EntityPlayer par1EntityPlayer) {
+ return false;
+ }
+
+ protected void dropRareDrop(int par1) {
+ this.dropItem(Item.ingotGold.itemID, 1);
+ }
+
+ /**
+ * Returns the item ID for the item the mob drops on death.
+ */
+ protected int getDropItemId() {
+ return Item.rottenFlesh.itemID;
+ }
+
+ /**
+ * Makes entity wear random armor based on difficulty
+ */
+ protected void addRandomArmor() {
+ this.setCurrentItemOrArmor(0, new ItemStack(Item.swordGold));
+ }
+
+ /**
+ * Initialize this creature.
+ */
+ public void initCreature() {
+ super.initCreature();
+ this.setVillager(false);
+ }
+
+ /**
+ * Returns the amount of damage a mob should deal.
+ */
+ public int getAttackStrength(Entity par1Entity) {
+ ItemStack var2 = this.getHeldItem();
+ int var3 = 5;
+
+ if (var2 != null) {
+ var3 += var2.getDamageVsEntity(this);
+ }
+
+ return var3;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityPlayer.java b/sp-server/src/main/java/net/minecraft/src/EntityPlayer.java
new file mode 100644
index 0000000..7270da9
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityPlayer.java
@@ -0,0 +1,1798 @@
+package net.minecraft.src;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+public abstract class EntityPlayer extends EntityLiving implements ICommandSender {
+ /** Inventory of the player */
+ public InventoryPlayer inventory = new InventoryPlayer(this);
+ private InventoryEnderChest theInventoryEnderChest = new InventoryEnderChest();
+
+ /**
+ * The Container for the player's inventory (which opens when they press E)
+ */
+ public Container inventoryContainer;
+
+ /** The Container the player has open. */
+ public Container openContainer;
+
+ /** The food object of the player, the general hunger logic. */
+ protected FoodStats foodStats = new FoodStats();
+
+ /**
+ * Used to tell if the player pressed jump twice. If this is at 0 and it's
+ * pressed (And they are allowed to fly, as defined in the player's
+ * movementInput) it sets this to 7. If it's pressed and it's greater than 0
+ * enable fly.
+ */
+ protected int flyToggleTimer = 0;
+ public byte field_71098_bD = 0;
+ public float prevCameraYaw;
+ public float cameraYaw;
+ public String username;
+
+ /**
+ * Used by EntityPlayer to prevent too many xp orbs from getting absorbed at
+ * once.
+ */
+ public int xpCooldown = 0;
+ public double field_71091_bM;
+ public double field_71096_bN;
+ public double field_71097_bO;
+ public double field_71094_bP;
+ public double field_71095_bQ;
+ public double field_71085_bR;
+
+ /** Boolean value indicating weather a player is sleeping or not */
+ protected boolean sleeping;
+
+ /** the current location of the player */
+ public ChunkCoordinates playerLocation;
+ private int sleepTimer;
+ public float field_71079_bU;
+ public float field_71089_bV;
+
+ /** holds the spawn chunk of the player */
+ private ChunkCoordinates spawnChunk;
+
+ /**
+ * Whether this player's spawn point is forced, preventing execution of bed
+ * checks.
+ */
+ private boolean spawnForced;
+
+ /** Holds the coordinate of the player when enter a minecraft to ride. */
+ private ChunkCoordinates startMinecartRidingCoordinate;
+
+ /** The player's capabilities. (See class PlayerCapabilities) */
+ public PlayerCapabilities capabilities = new PlayerCapabilities();
+
+ /** The current experience level the player is on. */
+ public int experienceLevel;
+
+ /**
+ * The total amount of experience the player has. This also includes the amount
+ * of experience within their Experience Bar.
+ */
+ public int experienceTotal;
+
+ /**
+ * The current amount of experience the player has within their Experience Bar.
+ */
+ public float experience;
+
+ /**
+ * This is the item that is in use when the player is holding down the
+ * useItemButton (e.g., bow, food, sword)
+ */
+ private ItemStack itemInUse;
+
+ /**
+ * This field starts off equal to getMaxItemUseDuration and is decremented on
+ * each tick
+ */
+ private int itemInUseCount;
+ protected float speedOnGround = 0.1F;
+ protected float speedInAir = 0.02F;
+ private int field_82249_h = 0;
+
+ /**
+ * An instance of a fishing rod's hook. If this isn't null, the icon image of
+ * the fishing rod is slightly different
+ */
+ public EntityFishHook fishEntity = null;
+
+ public EntityPlayer(World par1World) {
+ super(par1World);
+ this.inventoryContainer = new ContainerPlayer(this.inventory, !par1World.isRemote, this);
+ this.openContainer = this.inventoryContainer;
+ this.yOffset = 1.62F;
+ ChunkCoordinates var2 = par1World.getSpawnPoint();
+ this.setLocationAndAngles((double) var2.posX + 0.5D, (double) (var2.posY + 1), (double) var2.posZ + 0.5D, 0.0F,
+ 0.0F);
+ this.entityType = "humanoid";
+ this.field_70741_aB = 180.0F;
+ this.fireResistance = 20;
+ this.texture = "/mob/char.png";
+ }
+
+ public int getMaxHealth() {
+ return 20;
+ }
+
+ protected void entityInit() {
+ super.entityInit();
+ this.dataWatcher.addObject(16, Byte.valueOf((byte) 0));
+ this.dataWatcher.addObject(17, Byte.valueOf((byte) 0));
+ this.dataWatcher.addObject(18, Integer.valueOf(0));
+ }
+
+ /**
+ * Checks if the entity is currently using an item (e.g., bow, food, sword) by
+ * holding down the useItemButton
+ */
+ public boolean isUsingItem() {
+ return this.itemInUse != null;
+ }
+
+ public void stopUsingItem() {
+ if (this.itemInUse != null) {
+ this.itemInUse.onPlayerStoppedUsing(this.worldObj, this, this.itemInUseCount);
+ }
+
+ this.clearItemInUse();
+ }
+
+ public void clearItemInUse() {
+ this.itemInUse = null;
+ this.itemInUseCount = 0;
+
+ if (!this.worldObj.isRemote) {
+ this.setEating(false);
+ }
+ }
+
+ public boolean isBlocking() {
+ return this.isUsingItem()
+ && Item.itemsList[this.itemInUse.itemID].getItemUseAction(this.itemInUse) == EnumAction.block;
+ }
+
+ /**
+ * Called to update the entity's position/logic.
+ */
+ public void onUpdate() {
+ if (this.itemInUse != null) {
+ ItemStack var1 = this.inventory.getCurrentItem();
+
+ if (var1 == this.itemInUse) {
+ if (this.itemInUseCount <= 25 && this.itemInUseCount % 4 == 0) {
+ this.updateItemUse(var1, 5);
+ }
+
+ if (--this.itemInUseCount == 0 && !this.worldObj.isRemote) {
+ this.onItemUseFinish();
+ }
+ } else {
+ this.clearItemInUse();
+ }
+ }
+
+ if (this.xpCooldown > 0) {
+ --this.xpCooldown;
+ }
+
+ if (this.isPlayerSleeping()) {
+ ++this.sleepTimer;
+
+ if (this.sleepTimer > 100) {
+ this.sleepTimer = 100;
+ }
+
+ if (!this.worldObj.isRemote) {
+ if (!this.isInBed()) {
+ this.wakeUpPlayer(true, true, false);
+ } else if (this.worldObj.isDaytime()) {
+ this.wakeUpPlayer(false, true, true);
+ }
+ }
+ } else if (this.sleepTimer > 0) {
+ ++this.sleepTimer;
+
+ if (this.sleepTimer >= 110) {
+ this.sleepTimer = 0;
+ }
+ }
+
+ super.onUpdate();
+
+ if (!this.worldObj.isRemote && this.openContainer != null && !this.openContainer.canInteractWith(this)) {
+ this.closeScreen();
+ this.openContainer = this.inventoryContainer;
+ }
+
+ if (this.isBurning() && this.capabilities.disableDamage) {
+ this.extinguish();
+ }
+
+ this.field_71091_bM = this.field_71094_bP;
+ this.field_71096_bN = this.field_71095_bQ;
+ this.field_71097_bO = this.field_71085_bR;
+ double var9 = this.posX - this.field_71094_bP;
+ double var3 = this.posY - this.field_71095_bQ;
+ double var5 = this.posZ - this.field_71085_bR;
+ double var7 = 10.0D;
+
+ if (var9 > var7) {
+ this.field_71091_bM = this.field_71094_bP = this.posX;
+ }
+
+ if (var5 > var7) {
+ this.field_71097_bO = this.field_71085_bR = this.posZ;
+ }
+
+ if (var3 > var7) {
+ this.field_71096_bN = this.field_71095_bQ = this.posY;
+ }
+
+ if (var9 < -var7) {
+ this.field_71091_bM = this.field_71094_bP = this.posX;
+ }
+
+ if (var5 < -var7) {
+ this.field_71097_bO = this.field_71085_bR = this.posZ;
+ }
+
+ if (var3 < -var7) {
+ this.field_71096_bN = this.field_71095_bQ = this.posY;
+ }
+
+ this.field_71094_bP += var9 * 0.25D;
+ this.field_71085_bR += var5 * 0.25D;
+ this.field_71095_bQ += var3 * 0.25D;
+ this.addStat(StatList.minutesPlayedStat, 1);
+
+ if (this.ridingEntity == null) {
+ this.startMinecartRidingCoordinate = null;
+ }
+
+ if (!this.worldObj.isRemote) {
+ this.foodStats.onUpdate(this);
+ }
+ }
+
+ /**
+ * Return the amount of time this entity should stay in a portal before being
+ * transported.
+ */
+ public int getMaxInPortalTime() {
+ return this.capabilities.disableDamage ? 0 : 80;
+ }
+
+ /**
+ * Return the amount of cooldown before this entity can use a portal again.
+ */
+ public int getPortalCooldown() {
+ return 10;
+ }
+
+ public void playSound(String par1Str, float par2, float par3) {
+ this.worldObj.playSoundToNearExcept(this, par1Str, par2, par3);
+ }
+
+ /**
+ * Plays sounds and makes particles for item in use state
+ */
+ protected void updateItemUse(ItemStack par1ItemStack, int par2) {
+ if (par1ItemStack.getItemUseAction() == EnumAction.drink) {
+ this.playSound("random.drink", 0.5F, this.worldObj.rand.nextFloat() * 0.1F + 0.9F);
+ }
+
+ if (par1ItemStack.getItemUseAction() == EnumAction.eat) {
+ for (int var3 = 0; var3 < par2; ++var3) {
+ Vec3 var4 = this.worldObj.getWorldVec3Pool().getVecFromPool(
+ ((double) this.rand.nextFloat() - 0.5D) * 0.1D, Math.random() * 0.1D + 0.1D, 0.0D);
+ var4.rotateAroundX(-this.rotationPitch * (float) Math.PI / 180.0F);
+ var4.rotateAroundY(-this.rotationYaw * (float) Math.PI / 180.0F);
+ Vec3 var5 = this.worldObj.getWorldVec3Pool().getVecFromPool(
+ ((double) this.rand.nextFloat() - 0.5D) * 0.3D, (double) (-this.rand.nextFloat()) * 0.6D - 0.3D,
+ 0.6D);
+ var5.rotateAroundX(-this.rotationPitch * (float) Math.PI / 180.0F);
+ var5.rotateAroundY(-this.rotationYaw * (float) Math.PI / 180.0F);
+ var5 = var5.addVector(this.posX, this.posY + (double) this.getEyeHeight(), this.posZ);
+ this.worldObj.spawnParticle("iconcrack_" + par1ItemStack.getItem().itemID, var5.xCoord, var5.yCoord,
+ var5.zCoord, var4.xCoord, var4.yCoord + 0.05D, var4.zCoord);
+ }
+
+ this.playSound("random.eat", 0.5F + 0.5F * (float) this.rand.nextInt(2),
+ (this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F + 1.0F);
+ }
+ }
+
+ /**
+ * Used for when item use count runs out, ie: eating completed
+ */
+ protected void onItemUseFinish() {
+ if (this.itemInUse != null) {
+ this.updateItemUse(this.itemInUse, 16);
+ int var1 = this.itemInUse.stackSize;
+ ItemStack var2 = this.itemInUse.onFoodEaten(this.worldObj, this);
+
+ if (var2 != this.itemInUse || var2 != null && var2.stackSize != var1) {
+ this.inventory.mainInventory[this.inventory.currentItem] = var2;
+
+ if (var2.stackSize == 0) {
+ this.inventory.mainInventory[this.inventory.currentItem] = null;
+ }
+ }
+
+ this.clearItemInUse();
+ }
+ }
+
+ /**
+ * Dead and sleeping entities cannot move
+ */
+ protected boolean isMovementBlocked() {
+ return this.getHealth() <= 0 || this.isPlayerSleeping();
+ }
+
+ /**
+ * set current crafting inventory back to the 2x2 square
+ */
+ protected void closeScreen() {
+ this.openContainer = this.inventoryContainer;
+ }
+
+ /**
+ * Called when a player mounts an entity. e.g. mounts a pig, mounts a boat.
+ */
+ public void mountEntity(Entity par1Entity) {
+ if (this.ridingEntity == par1Entity) {
+ this.unmountEntity(par1Entity);
+
+ if (this.ridingEntity != null) {
+ this.ridingEntity.riddenByEntity = null;
+ }
+
+ this.ridingEntity = null;
+ } else {
+ super.mountEntity(par1Entity);
+ }
+ }
+
+ /**
+ * Handles updating while being ridden by an entity
+ */
+ public void updateRidden() {
+ double var1 = this.posX;
+ double var3 = this.posY;
+ double var5 = this.posZ;
+ float var7 = this.rotationYaw;
+ float var8 = this.rotationPitch;
+ super.updateRidden();
+ this.prevCameraYaw = this.cameraYaw;
+ this.cameraYaw = 0.0F;
+ this.addMountedMovementStat(this.posX - var1, this.posY - var3, this.posZ - var5);
+
+ if (this.ridingEntity instanceof EntityPig) {
+ this.rotationPitch = var8;
+ this.rotationYaw = var7;
+ this.renderYawOffset = ((EntityPig) this.ridingEntity).renderYawOffset;
+ }
+ }
+
+ protected void updateEntityActionState() {
+ this.updateArmSwingProgress();
+ }
+
+ /**
+ * Called frequently so the entity can update its state every tick as required.
+ * For example, zombies and skeletons use this to react to sunlight and start to
+ * burn.
+ */
+ public void onLivingUpdate() {
+ if (this.flyToggleTimer > 0) {
+ --this.flyToggleTimer;
+ }
+
+ if (this.worldObj.difficultySetting == 0 && this.getHealth() < this.getMaxHealth()
+ && this.ticksExisted % 20 * 12 == 0) {
+ this.heal(1);
+ }
+
+ this.inventory.decrementAnimations();
+ this.prevCameraYaw = this.cameraYaw;
+ super.onLivingUpdate();
+ this.landMovementFactor = this.capabilities.getWalkSpeed();
+ this.jumpMovementFactor = this.speedInAir;
+
+ if (this.isSprinting()) {
+ this.landMovementFactor = (float) ((double) this.landMovementFactor
+ + (double) this.capabilities.getWalkSpeed() * 0.3D);
+ this.jumpMovementFactor = (float) ((double) this.jumpMovementFactor + (double) this.speedInAir * 0.3D);
+ }
+
+ float var1 = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ);
+ float var2 = (float) Math.atan(-this.motionY * 0.20000000298023224D) * 15.0F;
+
+ if (var1 > 0.1F) {
+ var1 = 0.1F;
+ }
+
+ if (!this.onGround || this.getHealth() <= 0) {
+ var1 = 0.0F;
+ }
+
+ if (this.onGround || this.getHealth() <= 0) {
+ var2 = 0.0F;
+ }
+
+ this.cameraYaw += (var1 - this.cameraYaw) * 0.4F;
+ this.cameraPitch += (var2 - this.cameraPitch) * 0.8F;
+
+ if (this.getHealth() > 0) {
+ List var3 = this.worldObj.getEntitiesWithinAABBExcludingEntity(this,
+ this.boundingBox.expand(1.0D, 0.5D, 1.0D));
+
+ if (var3 != null) {
+ for (int var4 = 0; var4 < var3.size(); ++var4) {
+ Entity var5 = (Entity) var3.get(var4);
+
+ if (!var5.isDead) {
+ this.collideWithPlayer(var5);
+ }
+ }
+ }
+ }
+ }
+
+ private void collideWithPlayer(Entity par1Entity) {
+ par1Entity.onCollideWithPlayer(this);
+ }
+
+ public int getScore() {
+ return this.dataWatcher.getWatchableObjectInt(18);
+ }
+
+ /**
+ * Set player's score
+ */
+ public void setScore(int par1) {
+ this.dataWatcher.updateObject(18, Integer.valueOf(par1));
+ }
+
+ /**
+ * Add to player's score
+ */
+ public void addScore(int par1) {
+ int var2 = this.getScore();
+ this.dataWatcher.updateObject(18, Integer.valueOf(var2 + par1));
+ }
+
+ /**
+ * Called when the mob's health reaches 0.
+ */
+ public void onDeath(DamageSource par1DamageSource) {
+ super.onDeath(par1DamageSource);
+ this.setSize(0.2F, 0.2F);
+ this.setPosition(this.posX, this.posY, this.posZ);
+ this.motionY = 0.10000000149011612D;
+
+ if (this.username.equals("Notch")) {
+ this.dropPlayerItemWithRandomChoice(new ItemStack(Item.appleRed, 1), true);
+ }
+
+ if (!this.worldObj.getGameRules().getGameRuleBooleanValue("keepInventory")) {
+ this.inventory.dropAllItems();
+ }
+
+ if (par1DamageSource != null) {
+ this.motionX = (double) (-MathHelper.cos((this.attackedAtYaw + this.rotationYaw) * (float) Math.PI / 180.0F)
+ * 0.1F);
+ this.motionZ = (double) (-MathHelper.sin((this.attackedAtYaw + this.rotationYaw) * (float) Math.PI / 180.0F)
+ * 0.1F);
+ } else {
+ this.motionX = this.motionZ = 0.0D;
+ }
+
+ this.yOffset = 0.1F;
+ this.addStat(StatList.deathsStat, 1);
+ }
+
+ /**
+ * Adds a value to the player score. Currently not actually used and the entity
+ * passed in does nothing. Args: entity, scoreToAdd
+ */
+ public void addToPlayerScore(Entity par1Entity, int par2) {
+ this.addScore(par2);
+ Collection var3 = this.getWorldScoreboard().func_96520_a(ScoreObjectiveCriteria.field_96640_e);
+
+ if (par1Entity instanceof EntityPlayer) {
+ this.addStat(StatList.playerKillsStat, 1);
+ var3.addAll(this.getWorldScoreboard().func_96520_a(ScoreObjectiveCriteria.field_96639_d));
+ } else {
+ this.addStat(StatList.mobKillsStat, 1);
+ }
+
+ Iterator var4 = var3.iterator();
+
+ while (var4.hasNext()) {
+ ScoreObjective var5 = (ScoreObjective) var4.next();
+ Score var6 = this.getWorldScoreboard().func_96529_a(this.getEntityName(), var5);
+ var6.func_96648_a();
+ }
+ }
+
+ /**
+ * Called when player presses the drop item key
+ */
+ public EntityItem dropOneItem(boolean par1) {
+ return this.dropPlayerItemWithRandomChoice(this.inventory.decrStackSize(this.inventory.currentItem,
+ par1 && this.inventory.getCurrentItem() != null ? this.inventory.getCurrentItem().stackSize : 1),
+ false);
+ }
+
+ /**
+ * Args: itemstack - called when player drops an item stack that's not in his
+ * inventory (like items still placed in a workbench while the workbench'es GUI
+ * gets closed)
+ */
+ public EntityItem dropPlayerItem(ItemStack par1ItemStack) {
+ return this.dropPlayerItemWithRandomChoice(par1ItemStack, false);
+ }
+
+ /**
+ * Args: itemstack, flag
+ */
+ public EntityItem dropPlayerItemWithRandomChoice(ItemStack par1ItemStack, boolean par2) {
+ if (par1ItemStack == null) {
+ return null;
+ } else {
+ EntityItem var3 = new EntityItem(this.worldObj, this.posX,
+ this.posY - 0.30000001192092896D + (double) this.getEyeHeight(), this.posZ, par1ItemStack);
+ var3.delayBeforeCanPickup = 40;
+ float var4 = 0.1F;
+ float var5;
+
+ if (par2) {
+ var5 = this.rand.nextFloat() * 0.5F;
+ float var6 = this.rand.nextFloat() * (float) Math.PI * 2.0F;
+ var3.motionX = (double) (-MathHelper.sin(var6) * var5);
+ var3.motionZ = (double) (MathHelper.cos(var6) * var5);
+ var3.motionY = 0.20000000298023224D;
+ } else {
+ var4 = 0.3F;
+ var3.motionX = (double) (-MathHelper.sin(this.rotationYaw / 180.0F * (float) Math.PI)
+ * MathHelper.cos(this.rotationPitch / 180.0F * (float) Math.PI) * var4);
+ var3.motionZ = (double) (MathHelper.cos(this.rotationYaw / 180.0F * (float) Math.PI)
+ * MathHelper.cos(this.rotationPitch / 180.0F * (float) Math.PI) * var4);
+ var3.motionY = (double) (-MathHelper.sin(this.rotationPitch / 180.0F * (float) Math.PI) * var4 + 0.1F);
+ var4 = 0.02F;
+ var5 = this.rand.nextFloat() * (float) Math.PI * 2.0F;
+ var4 *= this.rand.nextFloat();
+ var3.motionX += Math.cos((double) var5) * (double) var4;
+ var3.motionY += (double) ((this.rand.nextFloat() - this.rand.nextFloat()) * 0.1F);
+ var3.motionZ += Math.sin((double) var5) * (double) var4;
+ }
+
+ this.joinEntityItemWithWorld(var3);
+ this.addStat(StatList.dropStat, 1);
+ return var3;
+ }
+ }
+
+ /**
+ * Joins the passed in entity item with the world. Args: entityItem
+ */
+ protected void joinEntityItemWithWorld(EntityItem par1EntityItem) {
+ this.worldObj.spawnEntityInWorld(par1EntityItem);
+ }
+
+ /**
+ * Returns how strong the player is against the specified block at this moment
+ */
+ public float getCurrentPlayerStrVsBlock(Block par1Block, boolean par2) {
+ float var3 = this.inventory.getStrVsBlock(par1Block);
+
+ if (var3 > 1.0F) {
+ int var4 = EnchantmentHelper.getEfficiencyModifier(this);
+ ItemStack var5 = this.inventory.getCurrentItem();
+
+ if (var4 > 0 && var5 != null) {
+ float var6 = (float) (var4 * var4 + 1);
+
+ if (!var5.canHarvestBlock(par1Block) && var3 <= 1.0F) {
+ var3 += var6 * 0.08F;
+ } else {
+ var3 += var6;
+ }
+ }
+ }
+
+ if (this.isPotionActive(Potion.digSpeed)) {
+ var3 *= 1.0F + (float) (this.getActivePotionEffect(Potion.digSpeed).getAmplifier() + 1) * 0.2F;
+ }
+
+ if (this.isPotionActive(Potion.digSlowdown)) {
+ var3 *= 1.0F - (float) (this.getActivePotionEffect(Potion.digSlowdown).getAmplifier() + 1) * 0.2F;
+ }
+
+ if (this.isInsideOfMaterial(Material.water) && !EnchantmentHelper.getAquaAffinityModifier(this)) {
+ var3 /= 5.0F;
+ }
+
+ if (!this.onGround) {
+ var3 /= 5.0F;
+ }
+
+ return var3;
+ }
+
+ /**
+ * Checks if the player has the ability to harvest a block (checks current
+ * inventory item for a tool if necessary)
+ */
+ public boolean canHarvestBlock(Block par1Block) {
+ return this.inventory.canHarvestBlock(par1Block);
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ super.readEntityFromNBT(par1NBTTagCompound);
+ NBTTagList var2 = par1NBTTagCompound.getTagList("Inventory");
+ this.inventory.readFromNBT(var2);
+ this.inventory.currentItem = par1NBTTagCompound.getInteger("SelectedItemSlot");
+ this.sleeping = par1NBTTagCompound.getBoolean("Sleeping");
+ this.sleepTimer = par1NBTTagCompound.getShort("SleepTimer");
+ this.experience = par1NBTTagCompound.getFloat("XpP");
+ this.experienceLevel = par1NBTTagCompound.getInteger("XpLevel");
+ this.experienceTotal = par1NBTTagCompound.getInteger("XpTotal");
+ this.setScore(par1NBTTagCompound.getInteger("Score"));
+
+ if (this.sleeping) {
+ this.playerLocation = new ChunkCoordinates(MathHelper.floor_double(this.posX),
+ MathHelper.floor_double(this.posY), MathHelper.floor_double(this.posZ));
+ this.wakeUpPlayer(true, true, false);
+ }
+
+ if (par1NBTTagCompound.hasKey("SpawnX") && par1NBTTagCompound.hasKey("SpawnY")
+ && par1NBTTagCompound.hasKey("SpawnZ")) {
+ this.spawnChunk = new ChunkCoordinates(par1NBTTagCompound.getInteger("SpawnX"),
+ par1NBTTagCompound.getInteger("SpawnY"), par1NBTTagCompound.getInteger("SpawnZ"));
+ this.spawnForced = par1NBTTagCompound.getBoolean("SpawnForced");
+ }
+
+ this.foodStats.readNBT(par1NBTTagCompound);
+ this.capabilities.readCapabilitiesFromNBT(par1NBTTagCompound);
+
+ if (par1NBTTagCompound.hasKey("EnderItems")) {
+ NBTTagList var3 = par1NBTTagCompound.getTagList("EnderItems");
+ this.theInventoryEnderChest.loadInventoryFromNBT(var3);
+ }
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ super.writeEntityToNBT(par1NBTTagCompound);
+ par1NBTTagCompound.setTag("Inventory", this.inventory.writeToNBT(new NBTTagList()));
+ par1NBTTagCompound.setInteger("SelectedItemSlot", this.inventory.currentItem);
+ par1NBTTagCompound.setBoolean("Sleeping", this.sleeping);
+ par1NBTTagCompound.setShort("SleepTimer", (short) this.sleepTimer);
+ par1NBTTagCompound.setFloat("XpP", this.experience);
+ par1NBTTagCompound.setInteger("XpLevel", this.experienceLevel);
+ par1NBTTagCompound.setInteger("XpTotal", this.experienceTotal);
+ par1NBTTagCompound.setInteger("Score", this.getScore());
+
+ if (this.spawnChunk != null) {
+ par1NBTTagCompound.setInteger("SpawnX", this.spawnChunk.posX);
+ par1NBTTagCompound.setInteger("SpawnY", this.spawnChunk.posY);
+ par1NBTTagCompound.setInteger("SpawnZ", this.spawnChunk.posZ);
+ par1NBTTagCompound.setBoolean("SpawnForced", this.spawnForced);
+ }
+
+ this.foodStats.writeNBT(par1NBTTagCompound);
+ this.capabilities.writeCapabilitiesToNBT(par1NBTTagCompound);
+ par1NBTTagCompound.setTag("EnderItems", this.theInventoryEnderChest.saveInventoryToNBT());
+ }
+
+ /**
+ * Displays the GUI for interacting with a chest inventory. Args: chestInventory
+ */
+ public void displayGUIChest(IInventory par1IInventory) {
+ }
+
+ public void displayGUIHopper(TileEntityHopper par1TileEntityHopper) {
+ }
+
+ public void displayGUIHopperMinecart(EntityMinecartHopper par1EntityMinecartHopper) {
+ }
+
+ public void displayGUIEnchantment(int par1, int par2, int par3, String par4Str) {
+ }
+
+ /**
+ * Displays the GUI for interacting with an anvil.
+ */
+ public void displayGUIAnvil(int par1, int par2, int par3) {
+ }
+
+ /**
+ * Displays the crafting GUI for a workbench.
+ */
+ public void displayGUIWorkbench(int par1, int par2, int par3) {
+ }
+
+ public float getEyeHeight() {
+ return 0.12F;
+ }
+
+ /**
+ * sets the players height back to normal after doing things like sleeping and
+ * dieing
+ */
+ protected void resetHeight() {
+ this.yOffset = 1.62F;
+ }
+
+ /**
+ * Called when the entity is attacked.
+ */
+ public boolean attackEntityFrom(DamageSource par1DamageSource, int par2) {
+ if (this.isEntityInvulnerable()) {
+ return false;
+ } else if (this.capabilities.disableDamage && !par1DamageSource.canHarmInCreative()) {
+ return false;
+ } else {
+ this.entityAge = 0;
+
+ if (this.getHealth() <= 0) {
+ return false;
+ } else {
+ if (this.isPlayerSleeping() && !this.worldObj.isRemote) {
+ this.wakeUpPlayer(true, true, false);
+ }
+
+ if (par1DamageSource.isDifficultyScaled()) {
+ if (this.worldObj.difficultySetting == 0) {
+ par2 = 0;
+ }
+
+ if (this.worldObj.difficultySetting == 1) {
+ par2 = par2 / 2 + 1;
+ }
+
+ if (this.worldObj.difficultySetting == 3) {
+ par2 = par2 * 3 / 2;
+ }
+ }
+
+ if (par2 == 0) {
+ return false;
+ } else {
+ Entity var3 = par1DamageSource.getEntity();
+
+ if (var3 instanceof EntityArrow && ((EntityArrow) var3).shootingEntity != null) {
+ var3 = ((EntityArrow) var3).shootingEntity;
+ }
+
+ if (var3 instanceof EntityLiving) {
+ this.alertWolves((EntityLiving) var3, false);
+ }
+
+ this.addStat(StatList.damageTakenStat, par2);
+ return super.attackEntityFrom(par1DamageSource, par2);
+ }
+ }
+ }
+ }
+
+ public boolean func_96122_a(EntityPlayer par1EntityPlayer) {
+ ScorePlayerTeam var2 = this.getTeam();
+ ScorePlayerTeam var3 = par1EntityPlayer.getTeam();
+ return var2 != var3 ? true : (var2 != null ? var2.func_96665_g() : true);
+ }
+
+ /**
+ * Called when the player attack or gets attacked, it's alert all wolves in the
+ * area that are owned by the player to join the attack or defend the player.
+ */
+ protected void alertWolves(EntityLiving par1EntityLiving, boolean par2) {
+ if (!(par1EntityLiving instanceof EntityCreeper) && !(par1EntityLiving instanceof EntityGhast)) {
+ if (par1EntityLiving instanceof EntityWolf) {
+ EntityWolf var3 = (EntityWolf) par1EntityLiving;
+
+ if (var3.isTamed() && this.username.equals(var3.getOwnerName())) {
+ return;
+ }
+ }
+
+ if (!(par1EntityLiving instanceof EntityPlayer) || this.func_96122_a((EntityPlayer) par1EntityLiving)) {
+ List var6 = this.worldObj.getEntitiesWithinAABB(EntityWolf.class, AxisAlignedBB.getAABBPool()
+ .getAABB(this.posX, this.posY, this.posZ, this.posX + 1.0D, this.posY + 1.0D, this.posZ + 1.0D)
+ .expand(16.0D, 4.0D, 16.0D));
+ Iterator var4 = var6.iterator();
+
+ while (var4.hasNext()) {
+ EntityWolf var5 = (EntityWolf) var4.next();
+
+ if (var5.isTamed() && var5.getEntityToAttack() == null && this.username.equals(var5.getOwnerName())
+ && (!par2 || !var5.isSitting())) {
+ var5.setSitting(false);
+ var5.setTarget(par1EntityLiving);
+ }
+ }
+ }
+ }
+ }
+
+ protected void damageArmor(int par1) {
+ this.inventory.damageArmor(par1);
+ }
+
+ /**
+ * Returns the current armor value as determined by a call to
+ * InventoryPlayer.getTotalArmorValue
+ */
+ public int getTotalArmorValue() {
+ return this.inventory.getTotalArmorValue();
+ }
+
+ public float func_82243_bO() {
+ int var1 = 0;
+ ItemStack[] var2 = this.inventory.armorInventory;
+ int var3 = var2.length;
+
+ for (int var4 = 0; var4 < var3; ++var4) {
+ ItemStack var5 = var2[var4];
+
+ if (var5 != null) {
+ ++var1;
+ }
+ }
+
+ return (float) var1 / (float) this.inventory.armorInventory.length;
+ }
+
+ /**
+ * Deals damage to the entity. If its a EntityPlayer then will take damage from
+ * the armor first and then health second with the reduced value. Args:
+ * damageAmount
+ */
+ protected void damageEntity(DamageSource par1DamageSource, int par2) {
+ if (!this.isEntityInvulnerable()) {
+ if (!par1DamageSource.isUnblockable() && this.isBlocking()) {
+ par2 = 1 + par2 >> 1;
+ }
+
+ par2 = this.applyArmorCalculations(par1DamageSource, par2);
+ par2 = this.applyPotionDamageCalculations(par1DamageSource, par2);
+ this.addExhaustion(par1DamageSource.getHungerDamage());
+ int var3 = this.getHealth();
+ this.setEntityHealth(this.getHealth() - par2);
+ this.field_94063_bt.func_94547_a(par1DamageSource, var3, par2);
+ }
+ }
+
+ /**
+ * Displays the furnace GUI for the passed in furnace entity. Args:
+ * tileEntityFurnace
+ */
+ public void displayGUIFurnace(TileEntityFurnace par1TileEntityFurnace) {
+ }
+
+ /**
+ * Displays the dipsenser GUI for the passed in dispenser entity. Args:
+ * TileEntityDispenser
+ */
+ public void displayGUIDispenser(TileEntityDispenser par1TileEntityDispenser) {
+ }
+
+ /**
+ * Displays the GUI for editing a sign. Args: tileEntitySign
+ */
+ public void displayGUIEditSign(TileEntity par1TileEntity) {
+ }
+
+ /**
+ * Displays the GUI for interacting with a brewing stand.
+ */
+ public void displayGUIBrewingStand(TileEntityBrewingStand par1TileEntityBrewingStand) {
+ }
+
+ /**
+ * Displays the GUI for interacting with a beacon.
+ */
+ public void displayGUIBeacon(TileEntityBeacon par1TileEntityBeacon) {
+ }
+
+ public void displayGUIMerchant(IMerchant par1IMerchant, String par2Str) {
+ }
+
+ /**
+ * Displays the GUI for interacting with a book.
+ */
+ public void displayGUIBook(ItemStack par1ItemStack) {
+ }
+
+ public boolean interactWith(Entity par1Entity) {
+ if (par1Entity.interact(this)) {
+ return true;
+ } else {
+ ItemStack var2 = this.getCurrentEquippedItem();
+
+ if (var2 != null && par1Entity instanceof EntityLiving) {
+ if (this.capabilities.isCreativeMode) {
+ var2 = var2.copy();
+ }
+
+ if (var2.interactWith((EntityLiving) par1Entity)) {
+ if (var2.stackSize <= 0 && !this.capabilities.isCreativeMode) {
+ this.destroyCurrentEquippedItem();
+ }
+
+ return true;
+ }
+ }
+
+ return false;
+ }
+ }
+
+ /**
+ * Returns the currently being used item by the player.
+ */
+ public ItemStack getCurrentEquippedItem() {
+ return this.inventory.getCurrentItem();
+ }
+
+ /**
+ * Destroys the currently equipped item from the player's inventory.
+ */
+ public void destroyCurrentEquippedItem() {
+ this.inventory.setInventorySlotContents(this.inventory.currentItem, (ItemStack) null);
+ }
+
+ /**
+ * Returns the Y Offset of this entity.
+ */
+ public double getYOffset() {
+ return (double) (this.yOffset - 0.5F);
+ }
+
+ /**
+ * Attacks for the player the targeted entity with the currently equipped item.
+ * The equipped item has hitEntity called on it. Args: targetEntity
+ */
+ public void attackTargetEntityWithCurrentItem(Entity par1Entity) {
+ if (par1Entity.canAttackWithItem()) {
+ if (!par1Entity.func_85031_j(this)) {
+ int var2 = this.inventory.getDamageVsEntity(par1Entity);
+
+ if (this.isPotionActive(Potion.damageBoost)) {
+ var2 += 3 << this.getActivePotionEffect(Potion.damageBoost).getAmplifier();
+ }
+
+ if (this.isPotionActive(Potion.weakness)) {
+ var2 -= 2 << this.getActivePotionEffect(Potion.weakness).getAmplifier();
+ }
+
+ int var3 = 0;
+ int var4 = 0;
+
+ if (par1Entity instanceof EntityLiving) {
+ var4 = EnchantmentHelper.getEnchantmentModifierLiving(this, (EntityLiving) par1Entity);
+ var3 += EnchantmentHelper.getKnockbackModifier(this, (EntityLiving) par1Entity);
+ }
+
+ if (this.isSprinting()) {
+ ++var3;
+ }
+
+ if (var2 > 0 || var4 > 0) {
+ boolean var5 = this.fallDistance > 0.0F && !this.onGround && !this.isOnLadder() && !this.isInWater()
+ && !this.isPotionActive(Potion.blindness) && this.ridingEntity == null
+ && par1Entity instanceof EntityLiving;
+
+ if (var5 && var2 > 0) {
+ var2 += this.rand.nextInt(var2 / 2 + 2);
+ }
+
+ var2 += var4;
+ boolean var6 = false;
+ int var7 = EnchantmentHelper.getFireAspectModifier(this);
+
+ if (par1Entity instanceof EntityLiving && var7 > 0 && !par1Entity.isBurning()) {
+ var6 = true;
+ par1Entity.setFire(1);
+ }
+
+ boolean var8 = par1Entity.attackEntityFrom(DamageSource.causePlayerDamage(this), var2);
+
+ if (var8) {
+ if (var3 > 0) {
+ par1Entity.addVelocity(
+ (double) (-MathHelper.sin(this.rotationYaw * (float) Math.PI / 180.0F)
+ * (float) var3 * 0.5F),
+ 0.1D, (double) (MathHelper.cos(this.rotationYaw * (float) Math.PI / 180.0F)
+ * (float) var3 * 0.5F));
+ this.motionX *= 0.6D;
+ this.motionZ *= 0.6D;
+ this.setSprinting(false);
+ }
+
+ if (var5) {
+ this.onCriticalHit(par1Entity);
+ }
+
+ if (var4 > 0) {
+ this.onEnchantmentCritical(par1Entity);
+ }
+
+ if (var2 >= 18) {
+ this.triggerAchievement(AchievementList.overkill);
+ }
+
+ this.setLastAttackingEntity(par1Entity);
+
+ if (par1Entity instanceof EntityLiving) {
+ EnchantmentThorns.func_92096_a(this, (EntityLiving) par1Entity, this.rand);
+ }
+ }
+
+ ItemStack var9 = this.getCurrentEquippedItem();
+ Object var10 = par1Entity;
+
+ if (par1Entity instanceof EntityDragonPart) {
+ IEntityMultiPart var11 = ((EntityDragonPart) par1Entity).entityDragonObj;
+
+ if (var11 != null && var11 instanceof EntityLiving) {
+ var10 = (EntityLiving) var11;
+ }
+ }
+
+ if (var9 != null && var10 instanceof EntityLiving) {
+ var9.hitEntity((EntityLiving) var10, this);
+
+ if (var9.stackSize <= 0) {
+ this.destroyCurrentEquippedItem();
+ }
+ }
+
+ if (par1Entity instanceof EntityLiving) {
+ if (par1Entity.isEntityAlive()) {
+ this.alertWolves((EntityLiving) par1Entity, true);
+ }
+
+ this.addStat(StatList.damageDealtStat, var2);
+
+ if (var7 > 0 && var8) {
+ par1Entity.setFire(var7 * 4);
+ } else if (var6) {
+ par1Entity.extinguish();
+ }
+ }
+
+ this.addExhaustion(0.3F);
+ }
+ }
+ }
+ }
+
+ /**
+ * Called when the player performs a critical hit on the Entity. Args: entity
+ * that was hit critically
+ */
+ public void onCriticalHit(Entity par1Entity) {
+ }
+
+ public void onEnchantmentCritical(Entity par1Entity) {
+ }
+
+ /**
+ * Will get destroyed next tick.
+ */
+ public void setDead() {
+ super.setDead();
+ this.inventoryContainer.onCraftGuiClosed(this);
+
+ if (this.openContainer != null) {
+ this.openContainer.onCraftGuiClosed(this);
+ }
+ }
+
+ /**
+ * Checks if this entity is inside of an opaque block
+ */
+ public boolean isEntityInsideOpaqueBlock() {
+ return !this.sleeping && super.isEntityInsideOpaqueBlock();
+ }
+
+ public boolean func_71066_bF() {
+ return false;
+ }
+
+ /**
+ * puts player to sleep on specified bed if possible
+ */
+ public EnumStatus sleepInBedAt(int par1, int par2, int par3) {
+ if (!this.worldObj.isRemote) {
+ if (this.isPlayerSleeping() || !this.isEntityAlive()) {
+ return EnumStatus.OTHER_PROBLEM;
+ }
+
+ if (!this.worldObj.provider.isSurfaceWorld()) {
+ return EnumStatus.NOT_POSSIBLE_HERE;
+ }
+
+ if (this.worldObj.isDaytime()) {
+ return EnumStatus.NOT_POSSIBLE_NOW;
+ }
+
+ if (Math.abs(this.posX - (double) par1) > 3.0D || Math.abs(this.posY - (double) par2) > 2.0D
+ || Math.abs(this.posZ - (double) par3) > 3.0D) {
+ return EnumStatus.TOO_FAR_AWAY;
+ }
+
+ double var4 = 8.0D;
+ double var6 = 5.0D;
+ List var8 = this.worldObj.getEntitiesWithinAABB(EntityMob.class,
+ AxisAlignedBB.getAABBPool().getAABB((double) par1 - var4, (double) par2 - var6,
+ (double) par3 - var4, (double) par1 + var4, (double) par2 + var6, (double) par3 + var4));
+
+ if (!var8.isEmpty()) {
+ return EnumStatus.NOT_SAFE;
+ }
+ }
+
+ this.setSize(0.2F, 0.2F);
+ this.yOffset = 0.2F;
+
+ if (this.worldObj.blockExists(par1, par2, par3)) {
+ int var9 = this.worldObj.getBlockMetadata(par1, par2, par3);
+ int var5 = BlockBed.getDirection(var9);
+ float var10 = 0.5F;
+ float var7 = 0.5F;
+
+ switch (var5) {
+ case 0:
+ var7 = 0.9F;
+ break;
+
+ case 1:
+ var10 = 0.1F;
+ break;
+
+ case 2:
+ var7 = 0.1F;
+ break;
+
+ case 3:
+ var10 = 0.9F;
+ }
+
+ this.func_71013_b(var5);
+ this.setPosition((double) ((float) par1 + var10), (double) ((float) par2 + 0.9375F),
+ (double) ((float) par3 + var7));
+ } else {
+ this.setPosition((double) ((float) par1 + 0.5F), (double) ((float) par2 + 0.9375F),
+ (double) ((float) par3 + 0.5F));
+ }
+
+ this.sleeping = true;
+ this.sleepTimer = 0;
+ this.playerLocation = new ChunkCoordinates(par1, par2, par3);
+ this.motionX = this.motionZ = this.motionY = 0.0D;
+
+ if (!this.worldObj.isRemote) {
+ this.worldObj.updateAllPlayersSleepingFlag();
+ }
+
+ return EnumStatus.OK;
+ }
+
+ private void func_71013_b(int par1) {
+ this.field_71079_bU = 0.0F;
+ this.field_71089_bV = 0.0F;
+
+ switch (par1) {
+ case 0:
+ this.field_71089_bV = -1.8F;
+ break;
+
+ case 1:
+ this.field_71079_bU = 1.8F;
+ break;
+
+ case 2:
+ this.field_71089_bV = 1.8F;
+ break;
+
+ case 3:
+ this.field_71079_bU = -1.8F;
+ }
+ }
+
+ /**
+ * Wake up the player if they're sleeping.
+ */
+ public void wakeUpPlayer(boolean par1, boolean par2, boolean par3) {
+ this.setSize(0.6F, 1.8F);
+ this.resetHeight();
+ ChunkCoordinates var4 = this.playerLocation;
+ ChunkCoordinates var5 = this.playerLocation;
+
+ if (var4 != null && this.worldObj.getBlockId(var4.posX, var4.posY, var4.posZ) == Block.bed.blockID) {
+ BlockBed.setBedOccupied(this.worldObj, var4.posX, var4.posY, var4.posZ, false);
+ var5 = BlockBed.getNearestEmptyChunkCoordinates(this.worldObj, var4.posX, var4.posY, var4.posZ, 0);
+
+ if (var5 == null) {
+ var5 = new ChunkCoordinates(var4.posX, var4.posY + 1, var4.posZ);
+ }
+
+ this.setPosition((double) ((float) var5.posX + 0.5F), (double) ((float) var5.posY + this.yOffset + 0.1F),
+ (double) ((float) var5.posZ + 0.5F));
+ }
+
+ this.sleeping = false;
+
+ if (!this.worldObj.isRemote && par2) {
+ this.worldObj.updateAllPlayersSleepingFlag();
+ }
+
+ if (par1) {
+ this.sleepTimer = 0;
+ } else {
+ this.sleepTimer = 100;
+ }
+
+ if (par3) {
+ this.setSpawnChunk(this.playerLocation, false);
+ }
+ }
+
+ /**
+ * Checks if the player is currently in a bed
+ */
+ private boolean isInBed() {
+ return this.worldObj.getBlockId(this.playerLocation.posX, this.playerLocation.posY,
+ this.playerLocation.posZ) == Block.bed.blockID;
+ }
+
+ /**
+ * Ensure that a block enabling respawning exists at the specified coordinates
+ * and find an empty space nearby to spawn.
+ */
+ public static ChunkCoordinates verifyRespawnCoordinates(World par0World, ChunkCoordinates par1ChunkCoordinates,
+ boolean par2) {
+ IChunkProvider var3 = par0World.getChunkProvider();
+ var3.loadChunk(par1ChunkCoordinates.posX - 3 >> 4, par1ChunkCoordinates.posZ - 3 >> 4);
+ var3.loadChunk(par1ChunkCoordinates.posX + 3 >> 4, par1ChunkCoordinates.posZ - 3 >> 4);
+ var3.loadChunk(par1ChunkCoordinates.posX - 3 >> 4, par1ChunkCoordinates.posZ + 3 >> 4);
+ var3.loadChunk(par1ChunkCoordinates.posX + 3 >> 4, par1ChunkCoordinates.posZ + 3 >> 4);
+
+ if (par0World.getBlockId(par1ChunkCoordinates.posX, par1ChunkCoordinates.posY,
+ par1ChunkCoordinates.posZ) == Block.bed.blockID) {
+ ChunkCoordinates var8 = BlockBed.getNearestEmptyChunkCoordinates(par0World, par1ChunkCoordinates.posX,
+ par1ChunkCoordinates.posY, par1ChunkCoordinates.posZ, 0);
+ return var8;
+ } else {
+ Material var4 = par0World.getBlockMaterial(par1ChunkCoordinates.posX, par1ChunkCoordinates.posY,
+ par1ChunkCoordinates.posZ);
+ Material var5 = par0World.getBlockMaterial(par1ChunkCoordinates.posX, par1ChunkCoordinates.posY + 1,
+ par1ChunkCoordinates.posZ);
+ boolean var6 = !var4.isSolid() && !var4.isLiquid();
+ boolean var7 = !var5.isSolid() && !var5.isLiquid();
+ return par2 && var6 && var7 ? par1ChunkCoordinates : null;
+ }
+ }
+
+ /**
+ * Returns whether player is sleeping or not
+ */
+ public boolean isPlayerSleeping() {
+ return this.sleeping;
+ }
+
+ /**
+ * Returns whether or not the player is asleep and the screen has fully faded.
+ */
+ public boolean isPlayerFullyAsleep() {
+ return this.sleeping && this.sleepTimer >= 100;
+ }
+
+ protected void setHideCape(int par1, boolean par2) {
+ byte var3 = this.dataWatcher.getWatchableObjectByte(16);
+
+ if (par2) {
+ this.dataWatcher.updateObject(16, Byte.valueOf((byte) (var3 | 1 << par1)));
+ } else {
+ this.dataWatcher.updateObject(16, Byte.valueOf((byte) (var3 & ~(1 << par1))));
+ }
+ }
+
+ /**
+ * Add a chat message to the player
+ */
+ public void addChatMessage(String par1Str) {
+ }
+
+ /**
+ * Returns the location of the bed the player will respawn at, or null if the
+ * player has not slept in a bed.
+ */
+ public ChunkCoordinates getBedLocation() {
+ return this.spawnChunk;
+ }
+
+ public boolean isSpawnForced() {
+ return this.spawnForced;
+ }
+
+ /**
+ * Defines a spawn coordinate to player spawn. Used by bed after the player
+ * sleep on it.
+ */
+ public void setSpawnChunk(ChunkCoordinates par1ChunkCoordinates, boolean par2) {
+ if (par1ChunkCoordinates != null) {
+ this.spawnChunk = new ChunkCoordinates(par1ChunkCoordinates);
+ this.spawnForced = par2;
+ } else {
+ this.spawnChunk = null;
+ this.spawnForced = false;
+ }
+ }
+
+ /**
+ * Will trigger the specified trigger.
+ */
+ public void triggerAchievement(StatBase par1StatBase) {
+ this.addStat(par1StatBase, 1);
+ }
+
+ /**
+ * Adds a value to a statistic field.
+ */
+ public void addStat(StatBase par1StatBase, int par2) {
+ }
+
+ /**
+ * Causes this entity to do an upwards motion (jumping).
+ */
+ protected void jump() {
+ super.jump();
+ this.addStat(StatList.jumpStat, 1);
+
+ if (this.isSprinting()) {
+ this.addExhaustion(0.8F);
+ } else {
+ this.addExhaustion(0.2F);
+ }
+ }
+
+ /**
+ * Moves the entity based on the specified heading. Args: strafe, forward
+ */
+ public void moveEntityWithHeading(float par1, float par2) {
+ double var3 = this.posX;
+ double var5 = this.posY;
+ double var7 = this.posZ;
+
+ if (this.capabilities.isFlying && this.ridingEntity == null) {
+ double var9 = this.motionY;
+ float var11 = this.jumpMovementFactor;
+ this.jumpMovementFactor = this.capabilities.getFlySpeed();
+ super.moveEntityWithHeading(par1, par2);
+ this.motionY = var9 * 0.6D;
+ this.jumpMovementFactor = var11;
+ } else {
+ super.moveEntityWithHeading(par1, par2);
+ }
+
+ this.addMovementStat(this.posX - var3, this.posY - var5, this.posZ - var7);
+ }
+
+ /**
+ * Adds a value to a movement statistic field - like run, walk, swin or climb.
+ */
+ public void addMovementStat(double par1, double par3, double par5) {
+ if (this.ridingEntity == null) {
+ int var7;
+
+ if (this.isInsideOfMaterial(Material.water)) {
+ var7 = Math.round(MathHelper.sqrt_double(par1 * par1 + par3 * par3 + par5 * par5) * 100.0F);
+
+ if (var7 > 0) {
+ this.addStat(StatList.distanceDoveStat, var7);
+ this.addExhaustion(0.015F * (float) var7 * 0.01F);
+ }
+ } else if (this.isInWater()) {
+ var7 = Math.round(MathHelper.sqrt_double(par1 * par1 + par5 * par5) * 100.0F);
+
+ if (var7 > 0) {
+ this.addStat(StatList.distanceSwumStat, var7);
+ this.addExhaustion(0.015F * (float) var7 * 0.01F);
+ }
+ } else if (this.isOnLadder()) {
+ if (par3 > 0.0D) {
+ this.addStat(StatList.distanceClimbedStat, (int) Math.round(par3 * 100.0D));
+ }
+ } else if (this.onGround) {
+ var7 = Math.round(MathHelper.sqrt_double(par1 * par1 + par5 * par5) * 100.0F);
+
+ if (var7 > 0) {
+ this.addStat(StatList.distanceWalkedStat, var7);
+
+ if (this.isSprinting()) {
+ this.addExhaustion(0.099999994F * (float) var7 * 0.01F);
+ } else {
+ this.addExhaustion(0.01F * (float) var7 * 0.01F);
+ }
+ }
+ } else {
+ var7 = Math.round(MathHelper.sqrt_double(par1 * par1 + par5 * par5) * 100.0F);
+
+ if (var7 > 25) {
+ this.addStat(StatList.distanceFlownStat, var7);
+ }
+ }
+ }
+ }
+
+ /**
+ * Adds a value to a mounted movement statistic field - by minecart, boat, or
+ * pig.
+ */
+ private void addMountedMovementStat(double par1, double par3, double par5) {
+ if (this.ridingEntity != null) {
+ int var7 = Math.round(MathHelper.sqrt_double(par1 * par1 + par3 * par3 + par5 * par5) * 100.0F);
+
+ if (var7 > 0) {
+ if (this.ridingEntity instanceof EntityMinecart) {
+ this.addStat(StatList.distanceByMinecartStat, var7);
+
+ if (this.startMinecartRidingCoordinate == null) {
+ this.startMinecartRidingCoordinate = new ChunkCoordinates(MathHelper.floor_double(this.posX),
+ MathHelper.floor_double(this.posY), MathHelper.floor_double(this.posZ));
+ } else if ((double) this.startMinecartRidingCoordinate.getDistanceSquared(
+ MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY),
+ MathHelper.floor_double(this.posZ)) >= 1000000.0D) {
+ this.addStat(AchievementList.onARail, 1);
+ }
+ } else if (this.ridingEntity instanceof EntityBoat) {
+ this.addStat(StatList.distanceByBoatStat, var7);
+ } else if (this.ridingEntity instanceof EntityPig) {
+ this.addStat(StatList.distanceByPigStat, var7);
+ }
+ }
+ }
+ }
+
+ /**
+ * Called when the mob is falling. Calculates and applies fall damage.
+ */
+ protected void fall(float par1) {
+ if (!this.capabilities.allowFlying) {
+ if (par1 >= 2.0F) {
+ this.addStat(StatList.distanceFallenStat, (int) Math.round((double) par1 * 100.0D));
+ }
+
+ super.fall(par1);
+ }
+ }
+
+ /**
+ * This method gets called when the entity kills another one.
+ */
+ public void onKillEntity(EntityLiving par1EntityLiving) {
+ if (par1EntityLiving instanceof IMob) {
+ this.triggerAchievement(AchievementList.killEnemy);
+ }
+ }
+
+ /**
+ * Sets the Entity inside a web block.
+ */
+ public void setInWeb() {
+ if (!this.capabilities.isFlying) {
+ super.setInWeb();
+ }
+ }
+
+ public ItemStack getCurrentArmor(int par1) {
+ return this.inventory.armorItemInSlot(par1);
+ }
+
+ /**
+ * Makes entity wear random armor based on difficulty
+ */
+ protected void addRandomArmor() {
+ }
+
+ protected void func_82162_bC() {
+ }
+
+ /**
+ * Add experience points to player.
+ */
+ public void addExperience(int par1) {
+ this.addScore(par1);
+ int var2 = Integer.MAX_VALUE - this.experienceTotal;
+
+ if (par1 > var2) {
+ par1 = var2;
+ }
+
+ this.experience += (float) par1 / (float) this.xpBarCap();
+
+ for (this.experienceTotal += par1; this.experience >= 1.0F; this.experience /= (float) this.xpBarCap()) {
+ this.experience = (this.experience - 1.0F) * (float) this.xpBarCap();
+ this.addExperienceLevel(1);
+ }
+ }
+
+ /**
+ * Add experience levels to this player.
+ */
+ public void addExperienceLevel(int par1) {
+ this.experienceLevel += par1;
+
+ if (this.experienceLevel < 0) {
+ this.experienceLevel = 0;
+ this.experience = 0.0F;
+ this.experienceTotal = 0;
+ }
+
+ if (par1 > 0 && this.experienceLevel % 5 == 0
+ && (float) this.field_82249_h < (float) this.ticksExisted - 100.0F) {
+ float var2 = this.experienceLevel > 30 ? 1.0F : (float) this.experienceLevel / 30.0F;
+ this.worldObj.playSoundAtEntity(this, "random.levelup", var2 * 0.75F, 1.0F);
+ this.field_82249_h = this.ticksExisted;
+ }
+ }
+
+ /**
+ * This method returns the cap amount of experience that the experience bar can
+ * hold. With each level, the experience cap on the player's experience bar is
+ * raised by 10.
+ */
+ public int xpBarCap() {
+ return this.experienceLevel >= 30 ? 62 + (this.experienceLevel - 30) * 7
+ : (this.experienceLevel >= 15 ? 17 + (this.experienceLevel - 15) * 3 : 17);
+ }
+
+ /**
+ * increases exhaustion level by supplied amount
+ */
+ public void addExhaustion(float par1) {
+ if (!this.capabilities.disableDamage) {
+ if (!this.worldObj.isRemote) {
+ this.foodStats.addExhaustion(par1);
+ }
+ }
+ }
+
+ /**
+ * Returns the player's FoodStats object.
+ */
+ public FoodStats getFoodStats() {
+ return this.foodStats;
+ }
+
+ public boolean canEat(boolean par1) {
+ return (par1 || this.foodStats.needFood()) && !this.capabilities.disableDamage;
+ }
+
+ /**
+ * Checks if the player's health is not full and not zero.
+ */
+ public boolean shouldHeal() {
+ return this.getHealth() > 0 && this.getHealth() < this.getMaxHealth();
+ }
+
+ /**
+ * sets the itemInUse when the use item button is clicked. Args: itemstack, int
+ * maxItemUseDuration
+ */
+ public void setItemInUse(ItemStack par1ItemStack, int par2) {
+ if (par1ItemStack != this.itemInUse) {
+ this.itemInUse = par1ItemStack;
+ this.itemInUseCount = par2;
+
+ if (!this.worldObj.isRemote) {
+ this.setEating(true);
+ }
+ }
+ }
+
+ /**
+ * Returns true if the item the player is holding can harvest the block at the
+ * given coords. Args: x, y, z.
+ */
+ public boolean canCurrentToolHarvestBlock(int par1, int par2, int par3) {
+ if (this.capabilities.allowEdit) {
+ return true;
+ } else {
+ int var4 = this.worldObj.getBlockId(par1, par2, par3);
+
+ if (var4 > 0) {
+ Block var5 = Block.blocksList[var4];
+
+ if (var5.blockMaterial.isAlwaysHarvested()) {
+ return true;
+ }
+
+ if (this.getCurrentEquippedItem() != null) {
+ ItemStack var6 = this.getCurrentEquippedItem();
+
+ if (var6.canHarvestBlock(var5) || var6.getStrVsBlock(var5) > 1.0F) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+ }
+
+ public boolean canPlayerEdit(int par1, int par2, int par3, int par4, ItemStack par5ItemStack) {
+ return this.capabilities.allowEdit ? true : (par5ItemStack != null ? par5ItemStack.func_82835_x() : false);
+ }
+
+ /**
+ * Get the experience points the entity currently has.
+ */
+ protected int getExperiencePoints(EntityPlayer par1EntityPlayer) {
+ if (this.worldObj.getGameRules().getGameRuleBooleanValue("keepInventory")) {
+ return 0;
+ } else {
+ int var2 = this.experienceLevel * 7;
+ return var2 > 100 ? 100 : var2;
+ }
+ }
+
+ /**
+ * Only use is to identify if class is an instance of player for experience
+ * dropping
+ */
+ protected boolean isPlayer() {
+ return true;
+ }
+
+ /**
+ * Gets the username of the entity.
+ */
+ public String getEntityName() {
+ return this.username;
+ }
+
+ public boolean func_94062_bN() {
+ return super.func_94062_bN();
+ }
+
+ public boolean canPickUpLoot() {
+ return false;
+ }
+
+ /**
+ * Copies the values from the given player into this player if boolean par2 is
+ * true. Always clones Ender Chest Inventory.
+ */
+ public void clonePlayer(EntityPlayer par1EntityPlayer, boolean par2) {
+ if (par2) {
+ this.inventory.copyInventory(par1EntityPlayer.inventory);
+ this.health = par1EntityPlayer.health;
+ this.foodStats = par1EntityPlayer.foodStats;
+ this.experienceLevel = par1EntityPlayer.experienceLevel;
+ this.experienceTotal = par1EntityPlayer.experienceTotal;
+ this.experience = par1EntityPlayer.experience;
+ this.setScore(par1EntityPlayer.getScore());
+ this.teleportDirection = par1EntityPlayer.teleportDirection;
+ } else if (this.worldObj.getGameRules().getGameRuleBooleanValue("keepInventory")) {
+ this.inventory.copyInventory(par1EntityPlayer.inventory);
+ this.experienceLevel = par1EntityPlayer.experienceLevel;
+ this.experienceTotal = par1EntityPlayer.experienceTotal;
+ this.experience = par1EntityPlayer.experience;
+ this.setScore(par1EntityPlayer.getScore());
+ }
+
+ this.theInventoryEnderChest = par1EntityPlayer.theInventoryEnderChest;
+ }
+
+ /**
+ * returns if this entity triggers Block.onEntityWalking on the blocks they walk
+ * on. used for spiders and wolves to prevent them from trampling crops
+ */
+ protected boolean canTriggerWalking() {
+ return !this.capabilities.isFlying;
+ }
+
+ /**
+ * Sends the player's abilities to the server (if there is one).
+ */
+ public void sendPlayerAbilities() {
+ }
+
+ /**
+ * Sets the player's game mode and sends it to them.
+ */
+ public void setGameType(EnumGameType par1EnumGameType) {
+ }
+
+ /**
+ * Gets the name of this command sender (usually username, but possibly "Rcon")
+ */
+ public String getCommandSenderName() {
+ return this.username;
+ }
+
+ public StringTranslate getTranslator() {
+ return StringTranslate.getInstance();
+ }
+
+ /**
+ * Translates and formats the given string key with the given arguments.
+ */
+ public String translateString(String par1Str, Object... par2ArrayOfObj) {
+ return this.getTranslator().translateKeyFormat(par1Str, par2ArrayOfObj);
+ }
+
+ /**
+ * Returns the InventoryEnderChest of this player.
+ */
+ public InventoryEnderChest getInventoryEnderChest() {
+ return this.theInventoryEnderChest;
+ }
+
+ /**
+ * 0: Tool in Hand; 1-4: Armor
+ */
+ public ItemStack getEquipmentInSlot(int par1) {
+ return par1 == 0 ? this.inventory.getCurrentItem() : this.inventory.armorInventory[par1 - 1];
+ }
+
+ /**
+ * Returns the item that this EntityLiving is holding, if any.
+ */
+ public ItemStack getHeldItem() {
+ return this.inventory.getCurrentItem();
+ }
+
+ /**
+ * Sets the held item, or an armor slot. Slot 0 is held item. Slot 1-4 is armor.
+ * Params: Item, slot
+ */
+ public void setCurrentItemOrArmor(int par1, ItemStack par2ItemStack) {
+ this.inventory.armorInventory[par1] = par2ItemStack;
+ }
+
+ /**
+ * returns the inventory of this entity (only used in EntityPlayerMP it seems)
+ */
+ public ItemStack[] getInventory() {
+ return this.inventory.armorInventory;
+ }
+
+ public boolean func_96092_aw() {
+ return !this.capabilities.isFlying;
+ }
+
+ public Scoreboard getWorldScoreboard() {
+ return this.worldObj.getScoreboard();
+ }
+
+ public ScorePlayerTeam getTeam() {
+ return this.getWorldScoreboard().getPlayersTeam(this.username);
+ }
+
+ /**
+ * Returns the translated name of the entity.
+ */
+ public String getTranslatedEntityName() {
+ return ScorePlayerTeam.func_96667_a(this.getTeam(), this.username);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityPlayerMP.java b/sp-server/src/main/java/net/minecraft/src/EntityPlayerMP.java
new file mode 100644
index 0000000..3a123e2
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityPlayerMP.java
@@ -0,0 +1,875 @@
+package net.minecraft.src;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglerUUID;
+import net.minecraft.server.MinecraftServer;
+
+public class EntityPlayerMP extends EntityPlayer implements ICrafting {
+ private StringTranslate translator = StringTranslate.getInstance();
+
+ /**
+ * The NetServerHandler assigned to this player by the
+ * ServerConfigurationManager.
+ */
+ public NetServerHandler playerNetServerHandler;
+
+ /** Reference to the MinecraftServer object. */
+ public MinecraftServer mcServer;
+
+ /** The ItemInWorldManager belonging to this player */
+ public ItemInWorldManager theItemInWorldManager;
+
+ /** player X position as seen by PlayerManager */
+ public double managedPosX;
+
+ /** player Z position as seen by PlayerManager */
+ public double managedPosZ;
+
+ /** LinkedList that holds the loaded chunks. */
+ public final List loadedChunks = new LinkedList();
+
+ /** entities added to this list will be packet29'd to the player */
+ public final List destroyedItemsNetCache = new LinkedList();
+
+ /** amount of health the client was last set to */
+ private int lastHealth = -99999999;
+
+ /** set to foodStats.GetFoodLevel */
+ private int lastFoodLevel = -99999999;
+
+ /** set to foodStats.getSaturationLevel() == 0.0F each tick */
+ private boolean wasHungry = true;
+
+ /** Amount of experience the client was last set to */
+ private int lastExperience = -99999999;
+
+ /** how many ticks of invulnerability(spawn protection) this player has */
+ private int ticksOfInvuln = 60;
+
+ /** must be between 3>x>15 (strictly between) */
+ public int renderDistance = 4;
+ public int lastRenderDistance = 4;
+ public int chatVisibility = 0;
+ private boolean chatColours = true;
+
+ /**
+ * The currently in use window ID. Incremented every time a window is opened.
+ */
+ private int currentWindowId = 0;
+
+ /**
+ * set to true when player is moving quantity of items from one inventory to
+ * another(crafting) but item in either slot is not changed
+ */
+ public boolean isChangingQuantityOnly;
+ public int ping;
+
+ /**
+ * Set when a player beats the ender dragon, used to respawn the player at the
+ * spawn point while retaining inventory and XP
+ */
+ public boolean playerConqueredTheEnd = false;
+
+ public EntityPlayerMP(MinecraftServer par1MinecraftServer, World par2World, String par3Str,
+ ItemInWorldManager par4ItemInWorldManager) {
+ super(par2World);
+ par4ItemInWorldManager.thisPlayerMP = this;
+ this.theItemInWorldManager = par4ItemInWorldManager;
+ ChunkCoordinates var5 = par2World.getSpawnPoint();
+ int var6 = var5.posX;
+ int var7 = var5.posZ;
+ int var8 = var5.posY;
+
+ if (!par2World.provider.hasNoSky && par2World.getWorldInfo().getGameType() != EnumGameType.ADVENTURE) {
+ int var9 = Math.max(5, par1MinecraftServer.getSpawnProtectionSize() - 6);
+ var6 += this.rand.nextInt(var9 * 2) - var9;
+ var7 += this.rand.nextInt(var9 * 2) - var9;
+ var8 = par2World.getTopSolidOrLiquidBlock(var6, var7);
+ }
+
+ this.mcServer = par1MinecraftServer;
+ this.stepHeight = 0.0F;
+ this.username = par3Str;
+ this.yOffset = 0.0F;
+ this.setLocationAndAngles((double) var6 + 0.5D, (double) var8, (double) var7 + 0.5D, 0.0F, 0.0F);
+
+ while (!par2World.getCollidingBoundingBoxes(this, this.boundingBox).isEmpty()) {
+ this.setPosition(this.posX, this.posY + 1.0D, this.posZ);
+ }
+
+ this.entityUniqueID = EaglerUUID.nameUUIDFromBytes(("OfflinePlayer:" + par3Str).getBytes(StandardCharsets.UTF_8));
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ super.readEntityFromNBT(par1NBTTagCompound);
+
+ if (par1NBTTagCompound.hasKey("playerGameType")) {
+ if (MinecraftServer.getServer().func_104056_am()) {
+ this.theItemInWorldManager.setGameType(MinecraftServer.getServer().getGameType());
+ } else {
+ this.theItemInWorldManager
+ .setGameType(EnumGameType.getByID(par1NBTTagCompound.getInteger("playerGameType")));
+ }
+ }
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ super.writeEntityToNBT(par1NBTTagCompound);
+ par1NBTTagCompound.setInteger("playerGameType", this.theItemInWorldManager.getGameType().getID());
+ }
+
+ /**
+ * Add experience levels to this player.
+ */
+ public void addExperienceLevel(int par1) {
+ super.addExperienceLevel(par1);
+ this.lastExperience = -1;
+ }
+
+ public void addSelfToInternalCraftingInventory() {
+ this.openContainer.onCraftGuiOpened(this);
+ }
+
+ /**
+ * sets the players height back to normal after doing things like sleeping and
+ * dieing
+ */
+ protected void resetHeight() {
+ this.yOffset = 0.0F;
+ }
+
+ public float getEyeHeight() {
+ return 1.62F;
+ }
+
+ /**
+ * Called to update the entity's position/logic.
+ */
+ public void onUpdate() {
+ this.theItemInWorldManager.updateBlockRemoving();
+ --this.ticksOfInvuln;
+ this.openContainer.detectAndSendChanges();
+
+ while (!this.destroyedItemsNetCache.isEmpty()) {
+ int var1 = Math.min(this.destroyedItemsNetCache.size(), 127);
+ int[] var2 = new int[var1];
+ Iterator var3 = this.destroyedItemsNetCache.iterator();
+ int var4 = 0;
+
+ while (var3.hasNext() && var4 < var1) {
+ var2[var4++] = ((Integer) var3.next()).intValue();
+ var3.remove();
+ }
+
+ this.playerNetServerHandler.sendPacket(new Packet29DestroyEntity(var2));
+ }
+
+ if (!this.loadedChunks.isEmpty()) {
+ ArrayList var6 = new ArrayList();
+ Iterator var7 = this.loadedChunks.iterator();
+ ArrayList var8 = new ArrayList();
+
+ while (var7.hasNext() && var6.size() < this.renderDistance / 2) {
+ ChunkCoordIntPair var9 = (ChunkCoordIntPair) var7.next();
+ var7.remove();
+
+ if (var9 != null && this.worldObj.blockExists(var9.chunkXPos << 4, 0, var9.chunkZPos << 4)) {
+ var6.add(this.worldObj.getChunkFromChunkCoords(var9.chunkXPos, var9.chunkZPos));
+ var8.addAll(((WorldServer) this.worldObj).getTileEntityList(var9.chunkXPos * 16, 0,
+ var9.chunkZPos * 16, var9.chunkXPos * 16 + 16, 256, var9.chunkZPos * 16 + 16));
+ }
+ }
+
+ if (!var6.isEmpty()) {
+ this.playerNetServerHandler.sendPacket(new Packet56MapChunks(var6));
+ Iterator var10 = var8.iterator();
+
+ while (var10.hasNext()) {
+ TileEntity var5 = (TileEntity) var10.next();
+ this.getTileEntityInfo(var5);
+ }
+
+ var10 = var6.iterator();
+
+ while (var10.hasNext()) {
+ Chunk var11 = (Chunk) var10.next();
+ this.getServerForPlayer().getEntityTracker().func_85172_a(this, var11);
+ }
+ }
+ }
+ }
+
+ public void setEntityHealth(int par1) {
+ super.setEntityHealth(par1);
+ Collection var2 = this.getWorldScoreboard().func_96520_a(ScoreObjectiveCriteria.field_96638_f);
+ Iterator var3 = var2.iterator();
+
+ while (var3.hasNext()) {
+ ScoreObjective var4 = (ScoreObjective) var3.next();
+ this.getWorldScoreboard().func_96529_a(this.getEntityName(), var4)
+ .func_96651_a(Arrays.asList(new EntityPlayer[] { this }));
+ }
+ }
+
+ public void onUpdateEntity() {
+ super.onUpdate();
+
+ for (int var1 = 0; var1 < this.inventory.getSizeInventory(); ++var1) {
+ ItemStack var5 = this.inventory.getStackInSlot(var1);
+
+ if (var5 != null && Item.itemsList[var5.itemID].isMap()
+ && this.playerNetServerHandler.getNumChunkDataPackets() <= 5) {
+ Packet var6 = ((ItemMapBase) Item.itemsList[var5.itemID]).getUpdatePacket(var5, this.worldObj,
+ this);
+
+ if (var6 != null) {
+ this.playerNetServerHandler.sendPacket(var6);
+ }
+ }
+ }
+
+ if (this.getHealth() != this.lastHealth || this.lastFoodLevel != this.foodStats.getFoodLevel()
+ || this.foodStats.getSaturationLevel() == 0.0F != this.wasHungry) {
+ this.playerNetServerHandler.sendPacket(new Packet8UpdateHealth(this.getHealth(),
+ this.foodStats.getFoodLevel(), this.foodStats.getSaturationLevel()));
+ this.lastHealth = this.getHealth();
+ this.lastFoodLevel = this.foodStats.getFoodLevel();
+ this.wasHungry = this.foodStats.getSaturationLevel() == 0.0F;
+ }
+
+ if (this.experienceTotal != this.lastExperience) {
+ this.lastExperience = this.experienceTotal;
+ this.playerNetServerHandler.sendPacket(
+ new Packet43Experience(this.experience, this.experienceTotal, this.experienceLevel));
+ }
+ }
+
+ /**
+ * Called when the mob's health reaches 0.
+ */
+ public void onDeath(DamageSource par1DamageSource) {
+ this.mcServer.getConfigurationManager().sendChatMsg(this.field_94063_bt.func_94546_b());
+
+ if (!this.worldObj.getGameRules().getGameRuleBooleanValue("keepInventory")) {
+ this.inventory.dropAllItems();
+ }
+
+ Collection var2 = this.worldObj.getScoreboard().func_96520_a(ScoreObjectiveCriteria.field_96642_c);
+ Iterator var3 = var2.iterator();
+
+ while (var3.hasNext()) {
+ ScoreObjective var4 = (ScoreObjective) var3.next();
+ Score var5 = this.getWorldScoreboard().func_96529_a(this.getEntityName(), var4);
+ var5.func_96648_a();
+ }
+
+ EntityLiving var6 = this.func_94060_bK();
+
+ if (var6 != null) {
+ var6.addToPlayerScore(this, this.scoreValue);
+ }
+ }
+
+ /**
+ * Called when the entity is attacked.
+ */
+ public boolean attackEntityFrom(DamageSource par1DamageSource, int par2) {
+ if (this.isEntityInvulnerable()) {
+ return false;
+ } else {
+ boolean var3 = this.mcServer.isDedicatedServer() && this.mcServer.isPVPEnabled()
+ && "fall".equals(par1DamageSource.damageType);
+
+ if (!var3 && this.ticksOfInvuln > 0 && par1DamageSource != DamageSource.outOfWorld) {
+ return false;
+ } else {
+ if (par1DamageSource instanceof EntityDamageSource) {
+ Entity var4 = par1DamageSource.getEntity();
+
+ if (var4 instanceof EntityPlayer && !this.func_96122_a((EntityPlayer) var4)) {
+ return false;
+ }
+
+ if (var4 instanceof EntityArrow) {
+ EntityArrow var5 = (EntityArrow) var4;
+
+ if (var5.shootingEntity instanceof EntityPlayer
+ && !this.func_96122_a((EntityPlayer) var5.shootingEntity)) {
+ return false;
+ }
+ }
+ }
+
+ return super.attackEntityFrom(par1DamageSource, par2);
+ }
+ }
+ }
+
+ public boolean func_96122_a(EntityPlayer par1EntityPlayer) {
+ return !this.mcServer.isPVPEnabled() ? false : super.func_96122_a(par1EntityPlayer);
+ }
+
+ public void travelToTheEnd(int par1) {
+ if (this.dimension == 1 && par1 == 1) {
+ this.triggerAchievement(AchievementList.theEnd2);
+ this.worldObj.removeEntity(this);
+ this.playerConqueredTheEnd = true;
+ this.playerNetServerHandler.sendPacket(new Packet70GameEvent(4, 0));
+ } else {
+ if (this.dimension == 1 && par1 == 0) {
+ this.triggerAchievement(AchievementList.theEnd);
+ ChunkCoordinates var2 = this.mcServer.worldServerForDimension(par1).getEntrancePortalLocation();
+
+ if (var2 != null) {
+ this.playerNetServerHandler.setPlayerLocation((double) var2.posX, (double) var2.posY,
+ (double) var2.posZ, 0.0F, 0.0F);
+ }
+
+ par1 = 1;
+ } else {
+ this.triggerAchievement(AchievementList.portal);
+ }
+
+ this.mcServer.getConfigurationManager().transferPlayerToDimension(this, par1);
+ this.lastExperience = -1;
+ this.lastHealth = -1;
+ this.lastFoodLevel = -1;
+ }
+ }
+
+ /**
+ * gets description packets from all TileEntity's that override func_20070
+ */
+ private void getTileEntityInfo(TileEntity par1TileEntity) {
+ if (par1TileEntity != null) {
+ Packet var2 = par1TileEntity.getDescriptionPacket();
+
+ if (var2 != null) {
+ this.playerNetServerHandler.sendPacket(var2);
+ }
+ }
+ }
+
+ /**
+ * Called whenever an item is picked up from walking over it. Args:
+ * pickedUpEntity, stackSize
+ */
+ public void onItemPickup(Entity par1Entity, int par2) {
+ super.onItemPickup(par1Entity, par2);
+ this.openContainer.detectAndSendChanges();
+ }
+
+ /**
+ * puts player to sleep on specified bed if possible
+ */
+ public EnumStatus sleepInBedAt(int par1, int par2, int par3) {
+ EnumStatus var4 = super.sleepInBedAt(par1, par2, par3);
+
+ if (var4 == EnumStatus.OK) {
+ Packet17Sleep var5 = new Packet17Sleep(this, 0, par1, par2, par3);
+ this.getServerForPlayer().getEntityTracker().sendPacketToTrackedPlayers(this, var5);
+ this.playerNetServerHandler.setPlayerLocation(this.posX, this.posY, this.posZ, this.rotationYaw,
+ this.rotationPitch);
+ this.playerNetServerHandler.sendPacket(var5);
+ }
+
+ return var4;
+ }
+
+ /**
+ * Wake up the player if they're sleeping.
+ */
+ public void wakeUpPlayer(boolean par1, boolean par2, boolean par3) {
+ if (this.isPlayerSleeping()) {
+ this.getServerForPlayer().getEntityTracker().sendPacketToTrackedPlayersAndTrackedEntity(this,
+ new Packet18Animation(this, 3));
+ }
+
+ super.wakeUpPlayer(par1, par2, par3);
+
+ if (this.playerNetServerHandler != null) {
+ this.playerNetServerHandler.setPlayerLocation(this.posX, this.posY, this.posZ, this.rotationYaw,
+ this.rotationPitch);
+ }
+ }
+
+ /**
+ * Called when a player mounts an entity. e.g. mounts a pig, mounts a boat.
+ */
+ public void mountEntity(Entity par1Entity) {
+ super.mountEntity(par1Entity);
+ this.playerNetServerHandler.sendPacket(new Packet39AttachEntity(this, this.ridingEntity));
+ this.playerNetServerHandler.setPlayerLocation(this.posX, this.posY, this.posZ, this.rotationYaw,
+ this.rotationPitch);
+ }
+
+ /**
+ * Takes in the distance the entity has fallen this tick and whether its on the
+ * ground to update the fall distance and deal fall damage if landing on the
+ * ground. Args: distanceFallenThisTick, onGround
+ */
+ protected void updateFallState(double par1, boolean par3) {
+ }
+
+ /**
+ * process player falling based on movement packet
+ */
+ public void handleFalling(double par1, boolean par3) {
+ super.updateFallState(par1, par3);
+ }
+
+ /**
+ * get the next window id to use
+ */
+ private void getNextWindowId() {
+ this.currentWindowId = this.currentWindowId % 100 + 1;
+ }
+
+ /**
+ * Displays the crafting GUI for a workbench.
+ */
+ public void displayGUIWorkbench(int par1, int par2, int par3) {
+ this.getNextWindowId();
+ this.playerNetServerHandler.sendPacket(new Packet100OpenWindow(this.currentWindowId, 1, "Crafting", 9, true));
+ this.openContainer = new ContainerWorkbench(this.inventory, this.worldObj, par1, par2, par3);
+ this.openContainer.windowId = this.currentWindowId;
+ this.openContainer.onCraftGuiOpened(this);
+ }
+
+ public void displayGUIEnchantment(int par1, int par2, int par3, String par4Str) {
+ this.getNextWindowId();
+ this.playerNetServerHandler.sendPacket(
+ new Packet100OpenWindow(this.currentWindowId, 4, par4Str == null ? "" : par4Str, 9, par4Str != null));
+ this.openContainer = new ContainerEnchantment(this.inventory, this.worldObj, par1, par2, par3);
+ this.openContainer.windowId = this.currentWindowId;
+ this.openContainer.onCraftGuiOpened(this);
+ }
+
+ /**
+ * Displays the GUI for interacting with an anvil.
+ */
+ public void displayGUIAnvil(int par1, int par2, int par3) {
+ this.getNextWindowId();
+ this.playerNetServerHandler.sendPacket(new Packet100OpenWindow(this.currentWindowId, 8, "Repairing", 9, true));
+ this.openContainer = new ContainerRepair(this.inventory, this.worldObj, par1, par2, par3, this);
+ this.openContainer.windowId = this.currentWindowId;
+ this.openContainer.onCraftGuiOpened(this);
+ }
+
+ /**
+ * Displays the GUI for interacting with a chest inventory. Args: chestInventory
+ */
+ public void displayGUIChest(IInventory par1IInventory) {
+ if (this.openContainer != this.inventoryContainer) {
+ this.closeScreen();
+ }
+
+ this.getNextWindowId();
+ this.playerNetServerHandler.sendPacket(new Packet100OpenWindow(this.currentWindowId, 0,
+ par1IInventory.getInvName(), par1IInventory.getSizeInventory(), par1IInventory.isInvNameLocalized()));
+ this.openContainer = new ContainerChest(this.inventory, par1IInventory);
+ this.openContainer.windowId = this.currentWindowId;
+ this.openContainer.onCraftGuiOpened(this);
+ }
+
+ public void displayGUIHopper(TileEntityHopper par1TileEntityHopper) {
+ this.getNextWindowId();
+ this.playerNetServerHandler
+ .sendPacket(new Packet100OpenWindow(this.currentWindowId, 9, par1TileEntityHopper.getInvName(),
+ par1TileEntityHopper.getSizeInventory(), par1TileEntityHopper.isInvNameLocalized()));
+ this.openContainer = new ContainerHopper(this.inventory, par1TileEntityHopper);
+ this.openContainer.windowId = this.currentWindowId;
+ this.openContainer.onCraftGuiOpened(this);
+ }
+
+ public void displayGUIHopperMinecart(EntityMinecartHopper par1EntityMinecartHopper) {
+ this.getNextWindowId();
+ this.playerNetServerHandler
+ .sendPacket(new Packet100OpenWindow(this.currentWindowId, 9, par1EntityMinecartHopper.getInvName(),
+ par1EntityMinecartHopper.getSizeInventory(), par1EntityMinecartHopper.isInvNameLocalized()));
+ this.openContainer = new ContainerHopper(this.inventory, par1EntityMinecartHopper);
+ this.openContainer.windowId = this.currentWindowId;
+ this.openContainer.onCraftGuiOpened(this);
+ }
+
+ /**
+ * Displays the furnace GUI for the passed in furnace entity. Args:
+ * tileEntityFurnace
+ */
+ public void displayGUIFurnace(TileEntityFurnace par1TileEntityFurnace) {
+ this.getNextWindowId();
+ this.playerNetServerHandler
+ .sendPacket(new Packet100OpenWindow(this.currentWindowId, 2, par1TileEntityFurnace.getInvName(),
+ par1TileEntityFurnace.getSizeInventory(), par1TileEntityFurnace.isInvNameLocalized()));
+ this.openContainer = new ContainerFurnace(this.inventory, par1TileEntityFurnace);
+ this.openContainer.windowId = this.currentWindowId;
+ this.openContainer.onCraftGuiOpened(this);
+ }
+
+ /**
+ * Displays the dipsenser GUI for the passed in dispenser entity. Args:
+ * TileEntityDispenser
+ */
+ public void displayGUIDispenser(TileEntityDispenser par1TileEntityDispenser) {
+ this.getNextWindowId();
+ this.playerNetServerHandler.sendPacket(new Packet100OpenWindow(this.currentWindowId,
+ par1TileEntityDispenser instanceof TileEntityDropper ? 10 : 3, par1TileEntityDispenser.getInvName(),
+ par1TileEntityDispenser.getSizeInventory(), par1TileEntityDispenser.isInvNameLocalized()));
+ this.openContainer = new ContainerDispenser(this.inventory, par1TileEntityDispenser);
+ this.openContainer.windowId = this.currentWindowId;
+ this.openContainer.onCraftGuiOpened(this);
+ }
+
+ /**
+ * Displays the GUI for interacting with a brewing stand.
+ */
+ public void displayGUIBrewingStand(TileEntityBrewingStand par1TileEntityBrewingStand) {
+ this.getNextWindowId();
+ this.playerNetServerHandler.sendPacket(new Packet100OpenWindow(this.currentWindowId, 5,
+ par1TileEntityBrewingStand.getInvName(), par1TileEntityBrewingStand.getSizeInventory(),
+ par1TileEntityBrewingStand.isInvNameLocalized()));
+ this.openContainer = new ContainerBrewingStand(this.inventory, par1TileEntityBrewingStand);
+ this.openContainer.windowId = this.currentWindowId;
+ this.openContainer.onCraftGuiOpened(this);
+ }
+
+ /**
+ * Displays the GUI for interacting with a beacon.
+ */
+ public void displayGUIBeacon(TileEntityBeacon par1TileEntityBeacon) {
+ this.getNextWindowId();
+ this.playerNetServerHandler
+ .sendPacket(new Packet100OpenWindow(this.currentWindowId, 7, par1TileEntityBeacon.getInvName(),
+ par1TileEntityBeacon.getSizeInventory(), par1TileEntityBeacon.isInvNameLocalized()));
+ this.openContainer = new ContainerBeacon(this.inventory, par1TileEntityBeacon);
+ this.openContainer.windowId = this.currentWindowId;
+ this.openContainer.onCraftGuiOpened(this);
+ }
+
+ public void displayGUIMerchant(IMerchant par1IMerchant, String par2Str) {
+ this.getNextWindowId();
+ this.openContainer = new ContainerMerchant(this.inventory, par1IMerchant, this.worldObj);
+ this.openContainer.windowId = this.currentWindowId;
+ this.openContainer.onCraftGuiOpened(this);
+ InventoryMerchant var3 = ((ContainerMerchant) this.openContainer).getMerchantInventory();
+ this.playerNetServerHandler.sendPacket(new Packet100OpenWindow(this.currentWindowId, 6,
+ par2Str == null ? "" : par2Str, var3.getSizeInventory(), par2Str != null));
+ MerchantRecipeList var4 = par1IMerchant.getRecipes(this);
+
+ if (var4 != null) {
+ try {
+ ByteArrayOutputStream var5 = new ByteArrayOutputStream();
+ DataOutputStream var6 = new DataOutputStream(var5);
+ var6.writeInt(this.currentWindowId);
+ var4.writeRecipiesToStream(var6);
+ this.playerNetServerHandler.sendPacket(new Packet250CustomPayload("MC|TrList", var5.toByteArray()));
+ } catch (IOException var7) {
+ var7.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * Sends the contents of an inventory slot to the client-side Container. This
+ * doesn't have to match the actual contents of that slot. Args: Container, slot
+ * number, slot contents
+ */
+ public void sendSlotContents(Container par1Container, int par2, ItemStack par3ItemStack) {
+ if (!(par1Container.getSlot(par2) instanceof SlotCrafting)) {
+ if (!this.isChangingQuantityOnly) {
+ this.playerNetServerHandler
+ .sendPacket(new Packet103SetSlot(par1Container.windowId, par2, par3ItemStack));
+ }
+ }
+ }
+
+ public void sendContainerToPlayer(Container par1Container) {
+ this.updateCraftingInventory(par1Container, par1Container.getInventory());
+ }
+
+ /**
+ * update the crafting window inventory with the items in the list
+ */
+ public void updateCraftingInventory(Container par1Container, List par2List) {
+ this.playerNetServerHandler.sendPacket(new Packet104WindowItems(par1Container.windowId, par2List));
+ this.playerNetServerHandler.sendPacket(new Packet103SetSlot(-1, -1, this.inventory.getItemStack()));
+ }
+
+ /**
+ * Sends two ints to the client-side Container. Used for furnace burning time,
+ * smelting progress, brewing progress, and enchanting level. Normally the first
+ * int identifies which variable to update, and the second contains the new
+ * value. Both are truncated to shorts in non-local SMP.
+ */
+ public void sendProgressBarUpdate(Container par1Container, int par2, int par3) {
+ this.playerNetServerHandler.sendPacket(new Packet105UpdateProgressbar(par1Container.windowId, par2, par3));
+ }
+
+ /**
+ * set current crafting inventory back to the 2x2 square
+ */
+ public void closeScreen() {
+ this.playerNetServerHandler.sendPacket(new Packet101CloseWindow(this.openContainer.windowId));
+ this.closeCraftingGui();
+ }
+
+ /**
+ * updates item held by mouse
+ */
+ public void updateHeldItem() {
+ if (!this.isChangingQuantityOnly) {
+ this.playerNetServerHandler.sendPacket(new Packet103SetSlot(-1, -1, this.inventory.getItemStack()));
+ }
+ }
+
+ /**
+ * close the current crafting gui
+ */
+ public void closeCraftingGui() {
+ this.openContainer.onCraftGuiClosed(this);
+ this.openContainer = this.inventoryContainer;
+ }
+
+ /**
+ * Adds a value to a statistic field.
+ */
+ public void addStat(StatBase par1StatBase, int par2) {
+ if (par1StatBase != null) {
+ if (!par1StatBase.isIndependent) {
+ while (par2 > 100) {
+ this.playerNetServerHandler.sendPacket(new Packet200Statistic(par1StatBase.statId, 100));
+ par2 -= 100;
+ }
+
+ this.playerNetServerHandler.sendPacket(new Packet200Statistic(par1StatBase.statId, par2));
+ }
+ }
+ }
+
+ public void mountEntityAndWakeUp() {
+ if (this.riddenByEntity != null) {
+ this.riddenByEntity.mountEntity(this);
+ }
+
+ if (this.sleeping) {
+ this.wakeUpPlayer(true, false, false);
+ }
+ }
+
+ /**
+ * this function is called when a players inventory is sent to him, lastHealth
+ * is updated on any dimension transitions, then reset.
+ */
+ public void setPlayerHealthUpdated() {
+ this.lastHealth = -99999999;
+ }
+
+ /**
+ * Add a chat message to the player
+ */
+ public void addChatMessage(String par1Str) {
+ StringTranslate var2 = StringTranslate.getInstance();
+ String var3 = var2.translateKey(par1Str);
+ this.playerNetServerHandler.sendPacket(new Packet3Chat(var3));
+ }
+
+ /**
+ * Used for when item use count runs out, ie: eating completed
+ */
+ protected void onItemUseFinish() {
+ this.playerNetServerHandler.sendPacket(new Packet38EntityStatus(this.entityId, (byte) 9));
+ super.onItemUseFinish();
+ }
+
+ /**
+ * sets the itemInUse when the use item button is clicked. Args: itemstack, int
+ * maxItemUseDuration
+ */
+ public void setItemInUse(ItemStack par1ItemStack, int par2) {
+ super.setItemInUse(par1ItemStack, par2);
+
+ if (par1ItemStack != null && par1ItemStack.getItem() != null
+ && par1ItemStack.getItem().getItemUseAction(par1ItemStack) == EnumAction.eat) {
+ this.getServerForPlayer().getEntityTracker().sendPacketToTrackedPlayersAndTrackedEntity(this,
+ new Packet18Animation(this, 5));
+ }
+ }
+
+ /**
+ * Copies the values from the given player into this player if boolean par2 is
+ * true. Always clones Ender Chest Inventory.
+ */
+ public void clonePlayer(EntityPlayer par1EntityPlayer, boolean par2) {
+ super.clonePlayer(par1EntityPlayer, par2);
+ this.renderDistance = ((EntityPlayerMP)par1EntityPlayer).renderDistance;
+ this.lastExperience = -1;
+ this.lastHealth = -1;
+ this.lastFoodLevel = -1;
+ this.destroyedItemsNetCache.addAll(((EntityPlayerMP) par1EntityPlayer).destroyedItemsNetCache);
+ }
+
+ protected void onNewPotionEffect(PotionEffect par1PotionEffect) {
+ super.onNewPotionEffect(par1PotionEffect);
+ this.playerNetServerHandler.sendPacket(new Packet41EntityEffect(this.entityId, par1PotionEffect));
+ }
+
+ protected void onChangedPotionEffect(PotionEffect par1PotionEffect) {
+ super.onChangedPotionEffect(par1PotionEffect);
+ this.playerNetServerHandler.sendPacket(new Packet41EntityEffect(this.entityId, par1PotionEffect));
+ }
+
+ protected void onFinishedPotionEffect(PotionEffect par1PotionEffect) {
+ super.onFinishedPotionEffect(par1PotionEffect);
+ this.playerNetServerHandler.sendPacket(new Packet42RemoveEntityEffect(this.entityId, par1PotionEffect));
+ }
+
+ /**
+ * Sets the position of the entity and updates the 'last' variables
+ */
+ public void setPositionAndUpdate(double par1, double par3, double par5) {
+ this.playerNetServerHandler.setPlayerLocation(par1, par3, par5, this.rotationYaw, this.rotationPitch);
+ }
+
+ /**
+ * Called when the player performs a critical hit on the Entity. Args: entity
+ * that was hit critically
+ */
+ public void onCriticalHit(Entity par1Entity) {
+ this.getServerForPlayer().getEntityTracker().sendPacketToTrackedPlayersAndTrackedEntity(this,
+ new Packet18Animation(par1Entity, 6));
+ }
+
+ public void onEnchantmentCritical(Entity par1Entity) {
+ this.getServerForPlayer().getEntityTracker().sendPacketToTrackedPlayersAndTrackedEntity(this,
+ new Packet18Animation(par1Entity, 7));
+ }
+
+ /**
+ * Sends the player's abilities to the server (if there is one).
+ */
+ public void sendPlayerAbilities() {
+ if (this.playerNetServerHandler != null) {
+ this.playerNetServerHandler.sendPacket(new Packet202PlayerAbilities(this.capabilities));
+ }
+ }
+
+ public WorldServer getServerForPlayer() {
+ return (WorldServer) this.worldObj;
+ }
+
+ /**
+ * Sets the player's game mode and sends it to them.
+ */
+ public void setGameType(EnumGameType par1EnumGameType) {
+ this.theItemInWorldManager.setGameType(par1EnumGameType);
+ this.playerNetServerHandler.sendPacket(new Packet70GameEvent(3, par1EnumGameType.getID()));
+ }
+
+ public void sendChatToPlayer(String par1Str) {
+ this.playerNetServerHandler.sendPacket(new Packet3Chat(par1Str));
+ }
+
+ /**
+ * Returns true if the command sender is allowed to use the given command.
+ */
+ public boolean canCommandSenderUseCommand(int par1, String par2Str) {
+ return "seed".equals(par2Str) && !this.mcServer.isDedicatedServer() ? true
+ : (!"tell".equals(par2Str) && !"help".equals(par2Str) && !"me".equals(par2Str)
+ ? this.mcServer.getConfigurationManager().areCommandsAllowed(this.username)
+ : true);
+ }
+
+ /**
+ * Gets the player's IP address. Used in /banip.
+ */
+ public String getPlayerIP() {
+ //String var1 = this.playerNetServerHandler.netManager.getRemoteAddress().toString();
+ //var1 = var1.substring(var1.indexOf("/") + 1);
+ //var1 = var1.substring(0, var1.indexOf(":"));
+ return "not implemented";
+ }
+
+ public void updateClientInfo(Packet204ClientInfo par1Packet204ClientInfo) {
+
+ // rip
+
+ //if (this.translator.getLanguageList().containsKey(par1Packet204ClientInfo.getLanguage())) {
+ // this.translator.setLanguage(par1Packet204ClientInfo.getLanguage(), false);
+ //}
+
+ int var2 = 64 << 3 - par1Packet204ClientInfo.getRenderDistance();
+ if(var2 > 400) {
+ var2 = 400;
+ }
+ var2 = (var2 >> 5) + 2;
+
+ if (var2 > 3 && var2 < 15) {
+ if (this.mcServer.getServerOwner().equals(this.username)) {
+ this.renderDistance = var2;
+ } else {
+ EntityPlayerMP fard = this.mcServer.getConfigurationManager().getPlayerEntity(this.mcServer.getServerOwner());
+ int maxRenderDistance = fard == null ? 10 : (fard.renderDistance > 10 ? 10 : fard.renderDistance);
+ this.renderDistance = var2 > maxRenderDistance ? maxRenderDistance : var2;
+ }
+ if(this.lastRenderDistance != this.renderDistance) {
+ if(this.mcServer.isSinglePlayer() && this.mcServer.getServerOwner().equals(this.username)) {
+ for(int i = 0; i < this.mcServer.worldServers.length; ++i) {
+ this.mcServer.worldServers[i].getEntityTracker().setMainRenderDistance(
+ PlayerManager.getFurthestViewableBlock(this.renderDistance));
+ }
+ }
+ ((WorldServer)this.worldObj).getPlayerManager().cycleRenderDistance(this);
+ }
+ }
+
+ this.chatVisibility = par1Packet204ClientInfo.getChatVisibility();
+ this.chatColours = par1Packet204ClientInfo.getChatColours();
+
+ if (this.mcServer.isSinglePlayer() && this.mcServer.getServerOwner().equals(this.username)) {
+ this.mcServer.setDifficultyForAllWorlds(par1Packet204ClientInfo.getDifficulty());
+ }
+
+ this.setHideCape(1, !par1Packet204ClientInfo.getShowCape());
+ }
+
+ public StringTranslate getTranslator() {
+ return this.translator;
+ }
+
+ public int getChatVisibility() {
+ return this.chatVisibility;
+ }
+
+ /**
+ * on recieving this message the client (if permission is given) will download
+ * the requested textures
+ */
+ public void requestTexturePackLoad(String par1Str, int par2) {
+ String var3 = par1Str + "\u0000" + par2;
+ this.playerNetServerHandler.sendPacket(new Packet250CustomPayload("MC|TPack", var3.getBytes()));
+ }
+
+ /**
+ * Return the position for this command sender.
+ */
+ public ChunkCoordinates getCommandSenderPosition() {
+ return new ChunkCoordinates(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY + 0.5D),
+ MathHelper.floor_double(this.posZ));
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityPotion.java b/sp-server/src/main/java/net/minecraft/src/EntityPotion.java
new file mode 100644
index 0000000..3414232
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityPotion.java
@@ -0,0 +1,145 @@
+package net.minecraft.src;
+
+import java.util.Iterator;
+import java.util.List;
+
+public class EntityPotion extends EntityThrowable {
+ /**
+ * The damage value of the thrown potion that this EntityPotion represents.
+ */
+ private ItemStack potionDamage;
+
+ public EntityPotion(World par1World) {
+ super(par1World);
+ }
+
+ public EntityPotion(World par1World, EntityLiving par2EntityLiving, int par3) {
+ this(par1World, par2EntityLiving, new ItemStack(Item.potion, 1, par3));
+ }
+
+ public EntityPotion(World par1World, EntityLiving par2EntityLiving, ItemStack par3ItemStack) {
+ super(par1World, par2EntityLiving);
+ this.potionDamage = par3ItemStack;
+ }
+
+ public EntityPotion(World par1World, double par2, double par4, double par6, ItemStack par8ItemStack) {
+ super(par1World, par2, par4, par6);
+ this.potionDamage = par8ItemStack;
+ }
+
+ /**
+ * Gets the amount of gravity to apply to the thrown entity with each tick.
+ */
+ protected float getGravityVelocity() {
+ return 0.05F;
+ }
+
+ protected float func_70182_d() {
+ return 0.5F;
+ }
+
+ protected float func_70183_g() {
+ return -20.0F;
+ }
+
+ public void setPotionDamage(int par1) {
+ if (this.potionDamage == null) {
+ this.potionDamage = new ItemStack(Item.potion, 1, 0);
+ }
+
+ this.potionDamage.setItemDamage(par1);
+ }
+
+ /**
+ * Returns the damage value of the thrown potion that this EntityPotion
+ * represents.
+ */
+ public int getPotionDamage() {
+ if (this.potionDamage == null) {
+ this.potionDamage = new ItemStack(Item.potion, 1, 0);
+ }
+
+ return this.potionDamage.getItemDamage();
+ }
+
+ /**
+ * Called when this EntityThrowable hits a block or entity.
+ */
+ protected void onImpact(MovingObjectPosition par1MovingObjectPosition) {
+ if (!this.worldObj.isRemote) {
+ List var2 = Item.potion.getEffects(this.potionDamage);
+
+ if (var2 != null && !var2.isEmpty()) {
+ AxisAlignedBB var3 = this.boundingBox.expand(4.0D, 2.0D, 4.0D);
+ List var4 = this.worldObj.getEntitiesWithinAABB(EntityLiving.class, var3);
+
+ if (var4 != null && !var4.isEmpty()) {
+ Iterator var5 = var4.iterator();
+
+ while (var5.hasNext()) {
+ EntityLiving var6 = (EntityLiving) var5.next();
+ double var7 = this.getDistanceSqToEntity(var6);
+
+ if (var7 < 16.0D) {
+ double var9 = 1.0D - Math.sqrt(var7) / 4.0D;
+
+ if (var6 == par1MovingObjectPosition.entityHit) {
+ var9 = 1.0D;
+ }
+
+ Iterator var11 = var2.iterator();
+
+ while (var11.hasNext()) {
+ PotionEffect var12 = (PotionEffect) var11.next();
+ int var13 = var12.getPotionID();
+
+ if (Potion.potionTypes[var13].isInstant()) {
+ Potion.potionTypes[var13].affectEntity(this.getThrower(), var6,
+ var12.getAmplifier(), var9);
+ } else {
+ int var14 = (int) (var9 * (double) var12.getDuration() + 0.5D);
+
+ if (var14 > 20) {
+ var6.addPotionEffect(new PotionEffect(var13, var14, var12.getAmplifier()));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ this.worldObj.playAuxSFX(2002, (int) Math.round(this.posX), (int) Math.round(this.posY),
+ (int) Math.round(this.posZ), this.getPotionDamage());
+ this.setDead();
+ }
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ super.readEntityFromNBT(par1NBTTagCompound);
+
+ if (par1NBTTagCompound.hasKey("Potion")) {
+ this.potionDamage = ItemStack.loadItemStackFromNBT(par1NBTTagCompound.getCompoundTag("Potion"));
+ } else {
+ this.setPotionDamage(par1NBTTagCompound.getInteger("potionValue"));
+ }
+
+ if (this.potionDamage == null) {
+ this.setDead();
+ }
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ super.writeEntityToNBT(par1NBTTagCompound);
+
+ if (this.potionDamage != null) {
+ par1NBTTagCompound.setCompoundTag("Potion", this.potionDamage.writeToNBT(new NBTTagCompound()));
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntitySelectorAlive.java b/sp-server/src/main/java/net/minecraft/src/EntitySelectorAlive.java
new file mode 100644
index 0000000..29b843f
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntitySelectorAlive.java
@@ -0,0 +1,10 @@
+package net.minecraft.src;
+
+final class EntitySelectorAlive implements IEntitySelector {
+ /**
+ * Return whether the specified entity is applicable to this filter.
+ */
+ public boolean isEntityApplicable(Entity par1Entity) {
+ return par1Entity.isEntityAlive();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntitySelectorArmoredMob.java b/sp-server/src/main/java/net/minecraft/src/EntitySelectorArmoredMob.java
new file mode 100644
index 0000000..3c5749d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntitySelectorArmoredMob.java
@@ -0,0 +1,24 @@
+package net.minecraft.src;
+
+public class EntitySelectorArmoredMob implements IEntitySelector {
+ private final ItemStack field_96567_c;
+
+ public EntitySelectorArmoredMob(ItemStack par1ItemStack) {
+ this.field_96567_c = par1ItemStack;
+ }
+
+ /**
+ * Return whether the specified entity is applicable to this filter.
+ */
+ public boolean isEntityApplicable(Entity par1Entity) {
+ if (!par1Entity.isEntityAlive()) {
+ return false;
+ } else if (!(par1Entity instanceof EntityLiving)) {
+ return false;
+ } else {
+ EntityLiving var2 = (EntityLiving) par1Entity;
+ return var2.getEquipmentInSlot(EntityLiving.getArmorPosition(this.field_96567_c)) != null ? false
+ : var2.canPickUpLoot() || var2 instanceof EntityPlayer;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntitySelectorInventory.java b/sp-server/src/main/java/net/minecraft/src/EntitySelectorInventory.java
new file mode 100644
index 0000000..06eaf87
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntitySelectorInventory.java
@@ -0,0 +1,10 @@
+package net.minecraft.src;
+
+final class EntitySelectorInventory implements IEntitySelector {
+ /**
+ * Return whether the specified entity is applicable to this filter.
+ */
+ public boolean isEntityApplicable(Entity par1Entity) {
+ return par1Entity instanceof IInventory && par1Entity.isEntityAlive();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntitySenses.java b/sp-server/src/main/java/net/minecraft/src/EntitySenses.java
new file mode 100644
index 0000000..9d792a9
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntitySenses.java
@@ -0,0 +1,48 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class EntitySenses {
+ EntityLiving entityObj;
+
+ /** Cache of entities which we can see */
+ List seenEntities = new ArrayList();
+
+ /** Cache of entities which we cannot see */
+ List unseenEntities = new ArrayList();
+
+ public EntitySenses(EntityLiving par1EntityLiving) {
+ this.entityObj = par1EntityLiving;
+ }
+
+ /**
+ * Clears canSeeCachePositive and canSeeCacheNegative.
+ */
+ public void clearSensingCache() {
+ this.seenEntities.clear();
+ this.unseenEntities.clear();
+ }
+
+ /**
+ * Checks, whether 'our' entity can see the entity given as argument (true) or
+ * not (false), caching the result.
+ */
+ public boolean canSee(Entity par1Entity) {
+ if (this.seenEntities.contains(par1Entity)) {
+ return true;
+ } else if (this.unseenEntities.contains(par1Entity)) {
+ return false;
+ } else {
+ boolean var2 = this.entityObj.canEntityBeSeen(par1Entity);
+
+ if (var2) {
+ this.seenEntities.add(par1Entity);
+ } else {
+ this.unseenEntities.add(par1Entity);
+ }
+
+ return var2;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntitySheep.java b/sp-server/src/main/java/net/minecraft/src/EntitySheep.java
new file mode 100644
index 0000000..2cdd677
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntitySheep.java
@@ -0,0 +1,267 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class EntitySheep extends EntityAnimal {
+ private final InventoryCrafting field_90016_e = new InventoryCrafting(new ContainerSheep(this), 2, 1);
+
+ /**
+ * Holds the RGB table of the sheep colors - in OpenGL glColor3f values - used
+ * to render the sheep colored fleece.
+ */
+ public static final float[][] fleeceColorTable = new float[][] { { 1.0F, 1.0F, 1.0F }, { 0.85F, 0.5F, 0.2F },
+ { 0.7F, 0.3F, 0.85F }, { 0.4F, 0.6F, 0.85F }, { 0.9F, 0.9F, 0.2F }, { 0.5F, 0.8F, 0.1F },
+ { 0.95F, 0.5F, 0.65F }, { 0.3F, 0.3F, 0.3F }, { 0.6F, 0.6F, 0.6F }, { 0.3F, 0.5F, 0.6F },
+ { 0.5F, 0.25F, 0.7F }, { 0.2F, 0.3F, 0.7F }, { 0.4F, 0.3F, 0.2F }, { 0.4F, 0.5F, 0.2F },
+ { 0.6F, 0.2F, 0.2F }, { 0.1F, 0.1F, 0.1F } };
+
+ /**
+ * Used to control movement as well as wool regrowth. Set to 40 on
+ * handleHealthUpdate and counts down with each tick.
+ */
+ private int sheepTimer;
+
+ /** The eat grass AI task for this mob. */
+ private EntityAIEatGrass aiEatGrass = new EntityAIEatGrass(this);
+
+ public EntitySheep(World par1World) {
+ super(par1World);
+ this.texture = "/mob/sheep.png";
+ this.setSize(0.9F, 1.3F);
+ float var2 = 0.23F;
+ this.getNavigator().setAvoidsWater(true);
+ this.tasks.addTask(0, new EntityAISwimming(this));
+ this.tasks.addTask(1, new EntityAIPanic(this, 0.38F));
+ this.tasks.addTask(2, new EntityAIMate(this, var2));
+ this.tasks.addTask(3, new EntityAITempt(this, 0.25F, Item.wheat.itemID, false));
+ this.tasks.addTask(4, new EntityAIFollowParent(this, 0.25F));
+ this.tasks.addTask(5, this.aiEatGrass);
+ this.tasks.addTask(6, new EntityAIWander(this, var2));
+ this.tasks.addTask(7, new EntityAIWatchClosest(this, EntityPlayer.class, 6.0F));
+ this.tasks.addTask(8, new EntityAILookIdle(this));
+ this.field_90016_e.setInventorySlotContents(0, new ItemStack(Item.dyePowder, 1, 0));
+ this.field_90016_e.setInventorySlotContents(1, new ItemStack(Item.dyePowder, 1, 0));
+ }
+
+ /**
+ * Returns true if the newer Entity AI code should be run
+ */
+ protected boolean isAIEnabled() {
+ return true;
+ }
+
+ protected void updateAITasks() {
+ this.sheepTimer = this.aiEatGrass.getEatGrassTick();
+ super.updateAITasks();
+ }
+
+ /**
+ * Called frequently so the entity can update its state every tick as required.
+ * For example, zombies and skeletons use this to react to sunlight and start to
+ * burn.
+ */
+ public void onLivingUpdate() {
+ if (this.worldObj.isRemote) {
+ this.sheepTimer = Math.max(0, this.sheepTimer - 1);
+ }
+
+ super.onLivingUpdate();
+ }
+
+ public int getMaxHealth() {
+ return 8;
+ }
+
+ protected void entityInit() {
+ super.entityInit();
+ this.dataWatcher.addObject(16, Byte.valueOf((byte) 0));
+ }
+
+ /**
+ * Drop 0-2 items of this living's type
+ */
+ protected void dropFewItems(boolean par1, int par2) {
+ if (!this.getSheared()) {
+ this.entityDropItem(new ItemStack(Block.cloth.blockID, 1, this.getFleeceColor()), 0.0F);
+ }
+ }
+
+ /**
+ * Returns the item ID for the item the mob drops on death.
+ */
+ protected int getDropItemId() {
+ return Block.cloth.blockID;
+ }
+
+ /**
+ * Called when a player interacts with a mob. e.g. gets milk from a cow, gets
+ * into the saddle on a pig.
+ */
+ public boolean interact(EntityPlayer par1EntityPlayer) {
+ ItemStack var2 = par1EntityPlayer.inventory.getCurrentItem();
+
+ if (var2 != null && var2.itemID == Item.shears.itemID && !this.getSheared() && !this.isChild()) {
+ if (!this.worldObj.isRemote) {
+ this.setSheared(true);
+ int var3 = 1 + this.rand.nextInt(3);
+
+ for (int var4 = 0; var4 < var3; ++var4) {
+ EntityItem var5 = this.entityDropItem(new ItemStack(Block.cloth.blockID, 1, this.getFleeceColor()),
+ 1.0F);
+ var5.motionY += (double) (this.rand.nextFloat() * 0.05F);
+ var5.motionX += (double) ((this.rand.nextFloat() - this.rand.nextFloat()) * 0.1F);
+ var5.motionZ += (double) ((this.rand.nextFloat() - this.rand.nextFloat()) * 0.1F);
+ }
+ }
+
+ var2.damageItem(1, par1EntityPlayer);
+ this.playSound("mob.sheep.shear", 1.0F, 1.0F);
+ }
+
+ return super.interact(par1EntityPlayer);
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ super.writeEntityToNBT(par1NBTTagCompound);
+ par1NBTTagCompound.setBoolean("Sheared", this.getSheared());
+ par1NBTTagCompound.setByte("Color", (byte) this.getFleeceColor());
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ super.readEntityFromNBT(par1NBTTagCompound);
+ this.setSheared(par1NBTTagCompound.getBoolean("Sheared"));
+ this.setFleeceColor(par1NBTTagCompound.getByte("Color"));
+ }
+
+ /**
+ * Returns the sound this mob makes while it's alive.
+ */
+ protected String getLivingSound() {
+ return "mob.sheep.say";
+ }
+
+ /**
+ * Returns the sound this mob makes when it is hurt.
+ */
+ protected String getHurtSound() {
+ return "mob.sheep.say";
+ }
+
+ /**
+ * Returns the sound this mob makes on death.
+ */
+ protected String getDeathSound() {
+ return "mob.sheep.say";
+ }
+
+ /**
+ * Plays step sound at given x, y, z for the entity
+ */
+ protected void playStepSound(int par1, int par2, int par3, int par4) {
+ this.playSound("mob.sheep.step", 0.15F, 1.0F);
+ }
+
+ public int getFleeceColor() {
+ return this.dataWatcher.getWatchableObjectByte(16) & 15;
+ }
+
+ public void setFleeceColor(int par1) {
+ byte var2 = this.dataWatcher.getWatchableObjectByte(16);
+ this.dataWatcher.updateObject(16, Byte.valueOf((byte) (var2 & 240 | par1 & 15)));
+ }
+
+ /**
+ * returns true if a sheeps wool has been sheared
+ */
+ public boolean getSheared() {
+ return (this.dataWatcher.getWatchableObjectByte(16) & 16) != 0;
+ }
+
+ /**
+ * make a sheep sheared if set to true
+ */
+ public void setSheared(boolean par1) {
+ byte var2 = this.dataWatcher.getWatchableObjectByte(16);
+
+ if (par1) {
+ this.dataWatcher.updateObject(16, Byte.valueOf((byte) (var2 | 16)));
+ } else {
+ this.dataWatcher.updateObject(16, Byte.valueOf((byte) (var2 & -17)));
+ }
+ }
+
+ /**
+ * This method is called when a sheep spawns in the world to select the color of
+ * sheep fleece.
+ */
+ public static int getRandomFleeceColor(EaglercraftRandom par0Random) {
+ int var1 = par0Random.nextInt(100);
+ return var1 < 5 ? 15
+ : (var1 < 10 ? 7 : (var1 < 15 ? 8 : (var1 < 18 ? 12 : (par0Random.nextInt(500) == 0 ? 6 : 0))));
+ }
+
+ public EntitySheep func_90015_b(EntityAgeable par1EntityAgeable) {
+ EntitySheep var2 = (EntitySheep) par1EntityAgeable;
+ EntitySheep var3 = new EntitySheep(this.worldObj);
+ int var4 = this.func_90014_a(this, var2);
+ var3.setFleeceColor(15 - var4);
+ return var3;
+ }
+
+ /**
+ * This function applies the benefits of growing back wool and faster growing up
+ * to the acting entity. (This function is used in the AIEatGrass)
+ */
+ public void eatGrassBonus() {
+ this.setSheared(false);
+
+ if (this.isChild()) {
+ int var1 = this.getGrowingAge() + 1200;
+
+ if (var1 > 0) {
+ var1 = 0;
+ }
+
+ this.setGrowingAge(var1);
+ }
+ }
+
+ /**
+ * Initialize this creature.
+ */
+ public void initCreature() {
+ this.setFleeceColor(getRandomFleeceColor(this.worldObj.rand));
+ }
+
+ private int func_90014_a(EntityAnimal par1EntityAnimal, EntityAnimal par2EntityAnimal) {
+ int var3 = this.func_90013_b(par1EntityAnimal);
+ int var4 = this.func_90013_b(par2EntityAnimal);
+ this.field_90016_e.getStackInSlot(0).setItemDamage(var3);
+ this.field_90016_e.getStackInSlot(1).setItemDamage(var4);
+ ItemStack var5 = CraftingManager.getInstance().findMatchingRecipe(this.field_90016_e,
+ ((EntitySheep) par1EntityAnimal).worldObj);
+ int var6;
+
+ if (var5 != null && var5.getItem().itemID == Item.dyePowder.itemID) {
+ var6 = var5.getItemDamage();
+ } else {
+ var6 = this.worldObj.rand.nextBoolean() ? var3 : var4;
+ }
+
+ return var6;
+ }
+
+ private int func_90013_b(EntityAnimal par1EntityAnimal) {
+ return 15 - ((EntitySheep) par1EntityAnimal).getFleeceColor();
+ }
+
+ public EntityAgeable createChild(EntityAgeable par1EntityAgeable) {
+ return this.func_90015_b(par1EntityAgeable);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntitySilverfish.java b/sp-server/src/main/java/net/minecraft/src/EntitySilverfish.java
new file mode 100644
index 0000000..113579f
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntitySilverfish.java
@@ -0,0 +1,214 @@
+package net.minecraft.src;
+
+public class EntitySilverfish extends EntityMob {
+ /**
+ * A cooldown before this entity will search for another Silverfish to join them
+ * in battle.
+ */
+ private int allySummonCooldown;
+
+ public EntitySilverfish(World par1World) {
+ super(par1World);
+ this.texture = "/mob/silverfish.png";
+ this.setSize(0.3F, 0.7F);
+ this.moveSpeed = 0.6F;
+ }
+
+ public int getMaxHealth() {
+ return 8;
+ }
+
+ /**
+ * returns if this entity triggers Block.onEntityWalking on the blocks they walk
+ * on. used for spiders and wolves to prevent them from trampling crops
+ */
+ protected boolean canTriggerWalking() {
+ return false;
+ }
+
+ /**
+ * Finds the closest player within 16 blocks to attack, or null if this Entity
+ * isn't interested in attacking (Animals, Spiders at day, peaceful PigZombies).
+ */
+ protected Entity findPlayerToAttack() {
+ double var1 = 8.0D;
+ return this.worldObj.getClosestVulnerablePlayerToEntity(this, var1);
+ }
+
+ /**
+ * Returns the sound this mob makes while it's alive.
+ */
+ protected String getLivingSound() {
+ return "mob.silverfish.say";
+ }
+
+ /**
+ * Returns the sound this mob makes when it is hurt.
+ */
+ protected String getHurtSound() {
+ return "mob.silverfish.hit";
+ }
+
+ /**
+ * Returns the sound this mob makes on death.
+ */
+ protected String getDeathSound() {
+ return "mob.silverfish.kill";
+ }
+
+ /**
+ * Called when the entity is attacked.
+ */
+ public boolean attackEntityFrom(DamageSource par1DamageSource, int par2) {
+ if (this.isEntityInvulnerable()) {
+ return false;
+ } else {
+ if (this.allySummonCooldown <= 0
+ && (par1DamageSource instanceof EntityDamageSource || par1DamageSource == DamageSource.magic)) {
+ this.allySummonCooldown = 20;
+ }
+
+ return super.attackEntityFrom(par1DamageSource, par2);
+ }
+ }
+
+ /**
+ * Basic mob attack. Default to touch of death in EntityCreature. Overridden by
+ * each mob to define their attack.
+ */
+ protected void attackEntity(Entity par1Entity, float par2) {
+ if (this.attackTime <= 0 && par2 < 1.2F && par1Entity.boundingBox.maxY > this.boundingBox.minY
+ && par1Entity.boundingBox.minY < this.boundingBox.maxY) {
+ this.attackTime = 20;
+ this.attackEntityAsMob(par1Entity);
+ }
+ }
+
+ /**
+ * Plays step sound at given x, y, z for the entity
+ */
+ protected void playStepSound(int par1, int par2, int par3, int par4) {
+ this.playSound("mob.silverfish.step", 0.15F, 1.0F);
+ }
+
+ /**
+ * Returns the item ID for the item the mob drops on death.
+ */
+ protected int getDropItemId() {
+ return 0;
+ }
+
+ /**
+ * Called to update the entity's position/logic.
+ */
+ public void onUpdate() {
+ this.renderYawOffset = this.rotationYaw;
+ super.onUpdate();
+ }
+
+ protected void updateEntityActionState() {
+ super.updateEntityActionState();
+
+ if (!this.worldObj.isRemote) {
+ int var1;
+ int var2;
+ int var3;
+ int var5;
+
+ if (this.allySummonCooldown > 0) {
+ --this.allySummonCooldown;
+
+ if (this.allySummonCooldown == 0) {
+ var1 = MathHelper.floor_double(this.posX);
+ var2 = MathHelper.floor_double(this.posY);
+ var3 = MathHelper.floor_double(this.posZ);
+ boolean var4 = false;
+
+ for (var5 = 0; !var4 && var5 <= 5 && var5 >= -5; var5 = var5 <= 0 ? 1 - var5 : 0 - var5) {
+ for (int var6 = 0; !var4 && var6 <= 10 && var6 >= -10; var6 = var6 <= 0 ? 1 - var6 : 0 - var6) {
+ for (int var7 = 0; !var4 && var7 <= 10
+ && var7 >= -10; var7 = var7 <= 0 ? 1 - var7 : 0 - var7) {
+ int var8 = this.worldObj.getBlockId(var1 + var6, var2 + var5, var3 + var7);
+
+ if (var8 == Block.silverfish.blockID) {
+ this.worldObj.destroyBlock(var1 + var6, var2 + var5, var3 + var7, false);
+ Block.silverfish.onBlockDestroyedByPlayer(this.worldObj, var1 + var6, var2 + var5,
+ var3 + var7, 0);
+
+ if (this.rand.nextBoolean()) {
+ var4 = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (this.entityToAttack == null && !this.hasPath()) {
+ var1 = MathHelper.floor_double(this.posX);
+ var2 = MathHelper.floor_double(this.posY + 0.5D);
+ var3 = MathHelper.floor_double(this.posZ);
+ int var9 = this.rand.nextInt(6);
+ var5 = this.worldObj.getBlockId(var1 + Facing.offsetsXForSide[var9],
+ var2 + Facing.offsetsYForSide[var9], var3 + Facing.offsetsZForSide[var9]);
+
+ if (BlockSilverfish.getPosingIdByMetadata(var5)) {
+ this.worldObj.setBlock(var1 + Facing.offsetsXForSide[var9], var2 + Facing.offsetsYForSide[var9],
+ var3 + Facing.offsetsZForSide[var9], Block.silverfish.blockID,
+ BlockSilverfish.getMetadataForBlockType(var5), 3);
+ this.spawnExplosionParticle();
+ this.setDead();
+ } else {
+ this.updateWanderPath();
+ }
+ } else if (this.entityToAttack != null && !this.hasPath()) {
+ this.entityToAttack = null;
+ }
+ }
+ }
+
+ /**
+ * Takes a coordinate in and returns a weight to determine how likely this
+ * creature will try to path to the block. Args: x, y, z
+ */
+ public float getBlockPathWeight(int par1, int par2, int par3) {
+ return this.worldObj.getBlockId(par1, par2 - 1, par3) == Block.stone.blockID ? 10.0F
+ : super.getBlockPathWeight(par1, par2, par3);
+ }
+
+ /**
+ * Checks to make sure the light is not too bright where the mob is spawning
+ */
+ protected boolean isValidLightLevel() {
+ return true;
+ }
+
+ /**
+ * Checks if the entity's current position is a valid location to spawn this
+ * entity.
+ */
+ public boolean getCanSpawnHere() {
+ if (super.getCanSpawnHere()) {
+ EntityPlayer var1 = this.worldObj.getClosestPlayerToEntity(this, 5.0D);
+ return var1 == null;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Returns the amount of damage a mob should deal.
+ */
+ public int getAttackStrength(Entity par1Entity) {
+ return 1;
+ }
+
+ /**
+ * Get this Entity's EnumCreatureAttribute
+ */
+ public EnumCreatureAttribute getCreatureAttribute() {
+ return EnumCreatureAttribute.ARTHROPOD;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntitySkeleton.java b/sp-server/src/main/java/net/minecraft/src/EntitySkeleton.java
new file mode 100644
index 0000000..509d884
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntitySkeleton.java
@@ -0,0 +1,341 @@
+package net.minecraft.src;
+
+import java.util.Calendar;
+
+public class EntitySkeleton extends EntityMob implements IRangedAttackMob {
+ private EntityAIArrowAttack aiArrowAttack = new EntityAIArrowAttack(this, 0.25F, 20, 60, 15.0F);
+ private EntityAIAttackOnCollide aiAttackOnCollide = new EntityAIAttackOnCollide(this, EntityPlayer.class, 0.31F,
+ false);
+
+ public EntitySkeleton(World par1World) {
+ super(par1World);
+ this.texture = "/mob/skeleton.png";
+ this.moveSpeed = 0.25F;
+ this.tasks.addTask(1, new EntityAISwimming(this));
+ this.tasks.addTask(2, new EntityAIRestrictSun(this));
+ this.tasks.addTask(3, new EntityAIFleeSun(this, this.moveSpeed));
+ this.tasks.addTask(5, new EntityAIWander(this, this.moveSpeed));
+ this.tasks.addTask(6, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F));
+ this.tasks.addTask(6, new EntityAILookIdle(this));
+ this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, false));
+ this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, EntityPlayer.class, 16.0F, 0, true));
+
+ if (par1World != null && !par1World.isRemote) {
+ this.setCombatTask();
+ }
+ }
+
+ protected void entityInit() {
+ super.entityInit();
+ this.dataWatcher.addObject(13, Byte.valueOf((byte) 0));
+ }
+
+ /**
+ * Returns true if the newer Entity AI code should be run
+ */
+ public boolean isAIEnabled() {
+ return true;
+ }
+
+ public int getMaxHealth() {
+ return 20;
+ }
+
+ /**
+ * Returns the sound this mob makes while it's alive.
+ */
+ protected String getLivingSound() {
+ return "mob.skeleton.say";
+ }
+
+ /**
+ * Returns the sound this mob makes when it is hurt.
+ */
+ protected String getHurtSound() {
+ return "mob.skeleton.hurt";
+ }
+
+ /**
+ * Returns the sound this mob makes on death.
+ */
+ protected String getDeathSound() {
+ return "mob.skeleton.death";
+ }
+
+ /**
+ * Plays step sound at given x, y, z for the entity
+ */
+ protected void playStepSound(int par1, int par2, int par3, int par4) {
+ this.playSound("mob.skeleton.step", 0.15F, 1.0F);
+ }
+
+ public boolean attackEntityAsMob(Entity par1Entity) {
+ if (super.attackEntityAsMob(par1Entity)) {
+ if (this.getSkeletonType() == 1 && par1Entity instanceof EntityLiving) {
+ ((EntityLiving) par1Entity).addPotionEffect(new PotionEffect(Potion.wither.id, 200));
+ }
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Returns the amount of damage a mob should deal.
+ */
+ public int getAttackStrength(Entity par1Entity) {
+ if (this.getSkeletonType() == 1) {
+ ItemStack var2 = this.getHeldItem();
+ int var3 = 4;
+
+ if (var2 != null) {
+ var3 += var2.getDamageVsEntity(this);
+ }
+
+ return var3;
+ } else {
+ return super.getAttackStrength(par1Entity);
+ }
+ }
+
+ /**
+ * Get this Entity's EnumCreatureAttribute
+ */
+ public EnumCreatureAttribute getCreatureAttribute() {
+ return EnumCreatureAttribute.UNDEAD;
+ }
+
+ /**
+ * Called frequently so the entity can update its state every tick as required.
+ * For example, zombies and skeletons use this to react to sunlight and start to
+ * burn.
+ */
+ public void onLivingUpdate() {
+ if (this.worldObj.isDaytime() && !this.worldObj.isRemote) {
+ float var1 = this.getBrightness(1.0F);
+
+ if (var1 > 0.5F && this.rand.nextFloat() * 30.0F < (var1 - 0.4F) * 2.0F
+ && this.worldObj.canBlockSeeTheSky(MathHelper.floor_double(this.posX),
+ MathHelper.floor_double(this.posY), MathHelper.floor_double(this.posZ))) {
+ boolean var2 = true;
+ ItemStack var3 = this.getEquipmentInSlot(4);
+
+ if (var3 != null) {
+ if (var3.isItemStackDamageable()) {
+ var3.setItemDamage(var3.getItemDamageForDisplay() + this.rand.nextInt(2));
+
+ if (var3.getItemDamageForDisplay() >= var3.getMaxDamage()) {
+ this.renderBrokenItemStack(var3);
+ this.setCurrentItemOrArmor(4, (ItemStack) null);
+ }
+ }
+
+ var2 = false;
+ }
+
+ if (var2) {
+ this.setFire(8);
+ }
+ }
+ }
+
+ if (this.worldObj.isRemote && this.getSkeletonType() == 1) {
+ this.setSize(0.72F, 2.34F);
+ }
+
+ super.onLivingUpdate();
+ }
+
+ /**
+ * Called when the mob's health reaches 0.
+ */
+ public void onDeath(DamageSource par1DamageSource) {
+ super.onDeath(par1DamageSource);
+
+ if (par1DamageSource.getSourceOfDamage() instanceof EntityArrow
+ && par1DamageSource.getEntity() instanceof EntityPlayer) {
+ EntityPlayer var2 = (EntityPlayer) par1DamageSource.getEntity();
+ double var3 = var2.posX - this.posX;
+ double var5 = var2.posZ - this.posZ;
+
+ if (var3 * var3 + var5 * var5 >= 2500.0D) {
+ var2.triggerAchievement(AchievementList.snipeSkeleton);
+ }
+ }
+ }
+
+ /**
+ * Returns the item ID for the item the mob drops on death.
+ */
+ protected int getDropItemId() {
+ return Item.arrow.itemID;
+ }
+
+ /**
+ * Drop 0-2 items of this living's type
+ */
+ protected void dropFewItems(boolean par1, int par2) {
+ int var3;
+ int var4;
+
+ if (this.getSkeletonType() == 1) {
+ var3 = this.rand.nextInt(3 + par2) - 1;
+
+ for (var4 = 0; var4 < var3; ++var4) {
+ this.dropItem(Item.coal.itemID, 1);
+ }
+ } else {
+ var3 = this.rand.nextInt(3 + par2);
+
+ for (var4 = 0; var4 < var3; ++var4) {
+ this.dropItem(Item.arrow.itemID, 1);
+ }
+ }
+
+ var3 = this.rand.nextInt(3 + par2);
+
+ for (var4 = 0; var4 < var3; ++var4) {
+ this.dropItem(Item.bone.itemID, 1);
+ }
+ }
+
+ protected void dropRareDrop(int par1) {
+ if (this.getSkeletonType() == 1) {
+ this.entityDropItem(new ItemStack(Item.skull.itemID, 1, 1), 0.0F);
+ }
+ }
+
+ /**
+ * Makes entity wear random armor based on difficulty
+ */
+ protected void addRandomArmor() {
+ super.addRandomArmor();
+ this.setCurrentItemOrArmor(0, new ItemStack(Item.bow));
+ }
+
+ /**
+ * Initialize this creature.
+ */
+ public void initCreature() {
+ if (this.worldObj.provider instanceof WorldProviderHell && this.getRNG().nextInt(5) > 0) {
+ this.tasks.addTask(4, this.aiAttackOnCollide);
+ this.setSkeletonType(1);
+ this.setCurrentItemOrArmor(0, new ItemStack(Item.swordStone));
+ } else {
+ this.tasks.addTask(4, this.aiArrowAttack);
+ this.addRandomArmor();
+ this.func_82162_bC();
+ }
+
+ this.setCanPickUpLoot(this.rand.nextFloat() < pickUpLootProability[this.worldObj.difficultySetting]);
+
+ if (this.getEquipmentInSlot(4) == null) {
+ Calendar var1 = this.worldObj.getCurrentDate();
+
+ if (var1.get(2) + 1 == 10 && var1.get(5) == 31 && this.rand.nextFloat() < 0.25F) {
+ this.setCurrentItemOrArmor(4,
+ new ItemStack(this.rand.nextFloat() < 0.1F ? Block.pumpkinLantern : Block.pumpkin));
+ this.equipmentDropChances[4] = 0.0F;
+ }
+ }
+ }
+
+ /**
+ * sets this entity's combat AI.
+ */
+ public void setCombatTask() {
+ this.tasks.removeTask(this.aiAttackOnCollide);
+ this.tasks.removeTask(this.aiArrowAttack);
+ ItemStack var1 = this.getHeldItem();
+
+ if (var1 != null && var1.itemID == Item.bow.itemID) {
+ this.tasks.addTask(4, this.aiArrowAttack);
+ } else {
+ this.tasks.addTask(4, this.aiAttackOnCollide);
+ }
+ }
+
+ /**
+ * Attack the specified entity using a ranged attack.
+ */
+ public void attackEntityWithRangedAttack(EntityLiving par1EntityLiving, float par2) {
+ EntityArrow var3 = new EntityArrow(this.worldObj, this, par1EntityLiving, 1.6F,
+ (float) (14 - this.worldObj.difficultySetting * 4));
+ int var4 = EnchantmentHelper.getEnchantmentLevel(Enchantment.power.effectId, this.getHeldItem());
+ int var5 = EnchantmentHelper.getEnchantmentLevel(Enchantment.punch.effectId, this.getHeldItem());
+ var3.setDamage((double) (par2 * 2.0F) + this.rand.nextGaussian() * 0.25D
+ + (double) ((float) this.worldObj.difficultySetting * 0.11F));
+
+ if (var4 > 0) {
+ var3.setDamage(var3.getDamage() + (double) var4 * 0.5D + 0.5D);
+ }
+
+ if (var5 > 0) {
+ var3.setKnockbackStrength(var5);
+ }
+
+ if (EnchantmentHelper.getEnchantmentLevel(Enchantment.flame.effectId, this.getHeldItem()) > 0
+ || this.getSkeletonType() == 1) {
+ var3.setFire(100);
+ }
+
+ this.playSound("random.bow", 1.0F, 1.0F / (this.getRNG().nextFloat() * 0.4F + 0.8F));
+ this.worldObj.spawnEntityInWorld(var3);
+ }
+
+ /**
+ * Return this skeleton's type.
+ */
+ public int getSkeletonType() {
+ return this.dataWatcher.getWatchableObjectByte(13);
+ }
+
+ /**
+ * Set this skeleton's type.
+ */
+ public void setSkeletonType(int par1) {
+ this.dataWatcher.updateObject(13, Byte.valueOf((byte) par1));
+ this.isImmuneToFire = par1 == 1;
+
+ if (par1 == 1) {
+ this.setSize(0.72F, 2.34F);
+ } else {
+ this.setSize(0.6F, 1.8F);
+ }
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ super.readEntityFromNBT(par1NBTTagCompound);
+
+ if (par1NBTTagCompound.hasKey("SkeletonType")) {
+ byte var2 = par1NBTTagCompound.getByte("SkeletonType");
+ this.setSkeletonType(var2);
+ }
+
+ this.setCombatTask();
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ super.writeEntityToNBT(par1NBTTagCompound);
+ par1NBTTagCompound.setByte("SkeletonType", (byte) this.getSkeletonType());
+ }
+
+ /**
+ * Sets the held item, or an armor slot. Slot 0 is held item. Slot 1-4 is armor.
+ * Params: Item, slot
+ */
+ public void setCurrentItemOrArmor(int par1, ItemStack par2ItemStack) {
+ super.setCurrentItemOrArmor(par1, par2ItemStack);
+
+ if (!this.worldObj.isRemote && par1 == 0) {
+ this.setCombatTask();
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntitySlime.java b/sp-server/src/main/java/net/minecraft/src/EntitySlime.java
new file mode 100644
index 0000000..7b381ad
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntitySlime.java
@@ -0,0 +1,308 @@
+package net.minecraft.src;
+
+public class EntitySlime extends EntityLiving implements IMob {
+ /** Chances for slimes to spawn in swamps for every moon phase. */
+ private static final float[] spawnChances = new float[] { 1.0F, 0.75F, 0.5F, 0.25F, 0.0F, 0.25F, 0.5F, 0.75F };
+ public float field_70813_a;
+ public float field_70811_b;
+ public float field_70812_c;
+
+ /** ticks until this slime jumps again */
+ private int slimeJumpDelay = 0;
+
+ public EntitySlime(World par1World) {
+ super(par1World);
+ this.texture = "/mob/slime.png";
+ int var2 = 1 << this.rand.nextInt(3);
+ this.yOffset = 0.0F;
+ this.slimeJumpDelay = this.rand.nextInt(20) + 10;
+ this.setSlimeSize(var2);
+ }
+
+ protected void entityInit() {
+ super.entityInit();
+ this.dataWatcher.addObject(16, Byte.valueOf((byte) 1));
+ }
+
+ protected void setSlimeSize(int par1) {
+ this.dataWatcher.updateObject(16, Byte.valueOf((byte) par1));
+ this.setSize(0.6F * (float) par1, 0.6F * (float) par1);
+ this.setPosition(this.posX, this.posY, this.posZ);
+ this.setEntityHealth(this.getMaxHealth());
+ this.experienceValue = par1;
+ }
+
+ public int getMaxHealth() {
+ int var1 = this.getSlimeSize();
+ return var1 * var1;
+ }
+
+ /**
+ * Returns the size of the slime.
+ */
+ public int getSlimeSize() {
+ return this.dataWatcher.getWatchableObjectByte(16);
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ super.writeEntityToNBT(par1NBTTagCompound);
+ par1NBTTagCompound.setInteger("Size", this.getSlimeSize() - 1);
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ super.readEntityFromNBT(par1NBTTagCompound);
+ this.setSlimeSize(par1NBTTagCompound.getInteger("Size") + 1);
+ }
+
+ /**
+ * Returns the name of a particle effect that may be randomly created by
+ * EntitySlime.onUpdate()
+ */
+ protected String getSlimeParticle() {
+ return "slime";
+ }
+
+ /**
+ * Returns the name of the sound played when the slime jumps.
+ */
+ protected String getJumpSound() {
+ return "mob.slime." + (this.getSlimeSize() > 1 ? "big" : "small");
+ }
+
+ /**
+ * Called to update the entity's position/logic.
+ */
+ public void onUpdate() {
+ if (!this.worldObj.isRemote && this.worldObj.difficultySetting == 0 && this.getSlimeSize() > 0) {
+ this.isDead = true;
+ }
+
+ this.field_70811_b += (this.field_70813_a - this.field_70811_b) * 0.5F;
+ this.field_70812_c = this.field_70811_b;
+ boolean var1 = this.onGround;
+ super.onUpdate();
+ int var2;
+
+ if (this.onGround && !var1) {
+ var2 = this.getSlimeSize();
+
+ for (int var3 = 0; var3 < var2 * 8; ++var3) {
+ float var4 = this.rand.nextFloat() * (float) Math.PI * 2.0F;
+ float var5 = this.rand.nextFloat() * 0.5F + 0.5F;
+ float var6 = MathHelper.sin(var4) * (float) var2 * 0.5F * var5;
+ float var7 = MathHelper.cos(var4) * (float) var2 * 0.5F * var5;
+ this.worldObj.spawnParticle(this.getSlimeParticle(), this.posX + (double) var6, this.boundingBox.minY,
+ this.posZ + (double) var7, 0.0D, 0.0D, 0.0D);
+ }
+
+ if (this.makesSoundOnLand()) {
+ this.playSound(this.getJumpSound(), this.getSoundVolume(),
+ ((this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F + 1.0F) / 0.8F);
+ }
+
+ this.field_70813_a = -0.5F;
+ } else if (!this.onGround && var1) {
+ this.field_70813_a = 1.0F;
+ }
+
+ this.func_70808_l();
+
+ if (this.worldObj.isRemote) {
+ var2 = this.getSlimeSize();
+ this.setSize(0.6F * (float) var2, 0.6F * (float) var2);
+ }
+ }
+
+ protected void updateEntityActionState() {
+ this.despawnEntity();
+ EntityPlayer var1 = this.worldObj.getClosestVulnerablePlayerToEntity(this, 16.0D);
+
+ if (var1 != null) {
+ this.faceEntity(var1, 10.0F, 20.0F);
+ }
+
+ if (this.onGround && this.slimeJumpDelay-- <= 0) {
+ this.slimeJumpDelay = this.getJumpDelay();
+
+ if (var1 != null) {
+ this.slimeJumpDelay /= 3;
+ }
+
+ this.isJumping = true;
+
+ if (this.makesSoundOnJump()) {
+ this.playSound(this.getJumpSound(), this.getSoundVolume(),
+ ((this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F + 1.0F) * 0.8F);
+ }
+
+ this.moveStrafing = 1.0F - this.rand.nextFloat() * 2.0F;
+ this.moveForward = (float) (1 * this.getSlimeSize());
+ } else {
+ this.isJumping = false;
+
+ if (this.onGround) {
+ this.moveStrafing = this.moveForward = 0.0F;
+ }
+ }
+ }
+
+ protected void func_70808_l() {
+ this.field_70813_a *= 0.6F;
+ }
+
+ /**
+ * Gets the amount of time the slime needs to wait between jumps.
+ */
+ protected int getJumpDelay() {
+ return this.rand.nextInt(20) + 10;
+ }
+
+ protected EntitySlime createInstance() {
+ return new EntitySlime(this.worldObj);
+ }
+
+ /**
+ * Will get destroyed next tick.
+ */
+ public void setDead() {
+ int var1 = this.getSlimeSize();
+
+ if (!this.worldObj.isRemote && var1 > 1 && this.getHealth() <= 0) {
+ int var2 = 2 + this.rand.nextInt(3);
+
+ for (int var3 = 0; var3 < var2; ++var3) {
+ float var4 = ((float) (var3 % 2) - 0.5F) * (float) var1 / 4.0F;
+ float var5 = ((float) (var3 / 2) - 0.5F) * (float) var1 / 4.0F;
+ EntitySlime var6 = this.createInstance();
+ var6.setSlimeSize(var1 / 2);
+ var6.setLocationAndAngles(this.posX + (double) var4, this.posY + 0.5D, this.posZ + (double) var5,
+ this.rand.nextFloat() * 360.0F, 0.0F);
+ this.worldObj.spawnEntityInWorld(var6);
+ }
+ }
+
+ super.setDead();
+ }
+
+ /**
+ * Called by a player entity when they collide with an entity
+ */
+ public void onCollideWithPlayer(EntityPlayer par1EntityPlayer) {
+ if (this.canDamagePlayer()) {
+ int var2 = this.getSlimeSize();
+
+ if (this.canEntityBeSeen(par1EntityPlayer)
+ && this.getDistanceSqToEntity(par1EntityPlayer) < 0.6D * (double) var2 * 0.6D * (double) var2
+ && par1EntityPlayer.attackEntityFrom(DamageSource.causeMobDamage(this), this.getAttackStrength())) {
+ this.playSound("mob.attack", 1.0F, (this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F + 1.0F);
+ }
+ }
+ }
+
+ /**
+ * Indicates weather the slime is able to damage the player (based upon the
+ * slime's size)
+ */
+ protected boolean canDamagePlayer() {
+ return this.getSlimeSize() > 1;
+ }
+
+ /**
+ * Gets the amount of damage dealt to the player when "attacked" by the slime.
+ */
+ protected int getAttackStrength() {
+ return this.getSlimeSize();
+ }
+
+ /**
+ * Returns the sound this mob makes when it is hurt.
+ */
+ protected String getHurtSound() {
+ return "mob.slime." + (this.getSlimeSize() > 1 ? "big" : "small");
+ }
+
+ /**
+ * Returns the sound this mob makes on death.
+ */
+ protected String getDeathSound() {
+ return "mob.slime." + (this.getSlimeSize() > 1 ? "big" : "small");
+ }
+
+ /**
+ * Returns the item ID for the item the mob drops on death.
+ */
+ protected int getDropItemId() {
+ return this.getSlimeSize() == 1 ? Item.slimeBall.itemID : 0;
+ }
+
+ /**
+ * Checks if the entity's current position is a valid location to spawn this
+ * entity.
+ */
+ public boolean getCanSpawnHere() {
+ Chunk var1 = this.worldObj.getChunkFromBlockCoords(MathHelper.floor_double(this.posX),
+ MathHelper.floor_double(this.posZ));
+
+ if (this.worldObj.getWorldInfo().getTerrainType() == WorldType.FLAT && this.rand.nextInt(4) != 1) {
+ return false;
+ } else {
+ if (this.getSlimeSize() == 1 || this.worldObj.difficultySetting > 0) {
+ BiomeGenBase var2 = this.worldObj.getBiomeGenForCoords(MathHelper.floor_double(this.posX),
+ MathHelper.floor_double(this.posZ));
+
+ if (var2 == BiomeGenBase.swampland && this.posY > 50.0D && this.posY < 70.0D
+ && this.rand.nextFloat() < 0.5F
+ && this.rand.nextFloat() < spawnChances[this.worldObj.getMoonPhase()]
+ && this.worldObj.getBlockLightValue(MathHelper.floor_double(this.posX),
+ MathHelper.floor_double(this.posY),
+ MathHelper.floor_double(this.posZ)) <= this.rand.nextInt(8)) {
+ return super.getCanSpawnHere();
+ }
+
+ if (this.rand.nextInt(10) == 0 && var1.getRandomWithSeed(987234911L).nextInt(10) == 0
+ && this.posY < 40.0D) {
+ return super.getCanSpawnHere();
+ }
+ }
+
+ return false;
+ }
+ }
+
+ /**
+ * Returns the volume for the sounds this mob makes.
+ */
+ protected float getSoundVolume() {
+ return 0.4F * (float) this.getSlimeSize();
+ }
+
+ /**
+ * The speed it takes to move the entityliving's rotationPitch through the
+ * faceEntity method. This is only currently use in wolves.
+ */
+ public int getVerticalFaceSpeed() {
+ return 0;
+ }
+
+ /**
+ * Returns true if the slime makes a sound when it jumps (based upon the slime's
+ * size)
+ */
+ protected boolean makesSoundOnJump() {
+ return this.getSlimeSize() > 0;
+ }
+
+ /**
+ * Returns true if the slime makes a sound when it lands after a jump (based
+ * upon the slime's size)
+ */
+ protected boolean makesSoundOnLand() {
+ return this.getSlimeSize() > 2;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntitySmallFireball.java b/sp-server/src/main/java/net/minecraft/src/EntitySmallFireball.java
new file mode 100644
index 0000000..9672175
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntitySmallFireball.java
@@ -0,0 +1,83 @@
+package net.minecraft.src;
+
+public class EntitySmallFireball extends EntityFireball {
+ public EntitySmallFireball(World par1World) {
+ super(par1World);
+ this.setSize(0.3125F, 0.3125F);
+ }
+
+ public EntitySmallFireball(World par1World, EntityLiving par2EntityLiving, double par3, double par5, double par7) {
+ super(par1World, par2EntityLiving, par3, par5, par7);
+ this.setSize(0.3125F, 0.3125F);
+ }
+
+ public EntitySmallFireball(World par1World, double par2, double par4, double par6, double par8, double par10,
+ double par12) {
+ super(par1World, par2, par4, par6, par8, par10, par12);
+ this.setSize(0.3125F, 0.3125F);
+ }
+
+ /**
+ * Called when this EntityFireball hits a block or entity.
+ */
+ protected void onImpact(MovingObjectPosition par1MovingObjectPosition) {
+ if (!this.worldObj.isRemote) {
+ if (par1MovingObjectPosition.entityHit != null) {
+ if (!par1MovingObjectPosition.entityHit.isImmuneToFire() && par1MovingObjectPosition.entityHit
+ .attackEntityFrom(DamageSource.causeFireballDamage(this, this.shootingEntity), 5)) {
+ par1MovingObjectPosition.entityHit.setFire(5);
+ }
+ } else {
+ int var2 = par1MovingObjectPosition.blockX;
+ int var3 = par1MovingObjectPosition.blockY;
+ int var4 = par1MovingObjectPosition.blockZ;
+
+ switch (par1MovingObjectPosition.sideHit) {
+ case 0:
+ --var3;
+ break;
+
+ case 1:
+ ++var3;
+ break;
+
+ case 2:
+ --var4;
+ break;
+
+ case 3:
+ ++var4;
+ break;
+
+ case 4:
+ --var2;
+ break;
+
+ case 5:
+ ++var2;
+ }
+
+ if (this.worldObj.isAirBlock(var2, var3, var4)) {
+ this.worldObj.setBlock(var2, var3, var4, Block.fire.blockID);
+ }
+ }
+
+ this.setDead();
+ }
+ }
+
+ /**
+ * Returns true if other Entities should be prevented from moving through this
+ * Entity.
+ */
+ public boolean canBeCollidedWith() {
+ return false;
+ }
+
+ /**
+ * Called when the entity is attacked.
+ */
+ public boolean attackEntityFrom(DamageSource par1DamageSource, int par2) {
+ return false;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntitySnowball.java b/sp-server/src/main/java/net/minecraft/src/EntitySnowball.java
new file mode 100644
index 0000000..2d1eb77
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntitySnowball.java
@@ -0,0 +1,39 @@
+package net.minecraft.src;
+
+public class EntitySnowball extends EntityThrowable {
+ public EntitySnowball(World par1World) {
+ super(par1World);
+ }
+
+ public EntitySnowball(World par1World, EntityLiving par2EntityLiving) {
+ super(par1World, par2EntityLiving);
+ }
+
+ public EntitySnowball(World par1World, double par2, double par4, double par6) {
+ super(par1World, par2, par4, par6);
+ }
+
+ /**
+ * Called when this EntityThrowable hits a block or entity.
+ */
+ protected void onImpact(MovingObjectPosition par1MovingObjectPosition) {
+ if (par1MovingObjectPosition.entityHit != null) {
+ byte var2 = 0;
+
+ if (par1MovingObjectPosition.entityHit instanceof EntityBlaze) {
+ var2 = 3;
+ }
+
+ par1MovingObjectPosition.entityHit.attackEntityFrom(DamageSource.causeThrownDamage(this, this.getThrower()),
+ var2);
+ }
+
+ for (int var3 = 0; var3 < 8; ++var3) {
+ this.worldObj.spawnParticle("snowballpoof", this.posX, this.posY, this.posZ, 0.0D, 0.0D, 0.0D);
+ }
+
+ if (!this.worldObj.isRemote) {
+ this.setDead();
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntitySnowman.java b/sp-server/src/main/java/net/minecraft/src/EntitySnowman.java
new file mode 100644
index 0000000..98ab96c
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntitySnowman.java
@@ -0,0 +1,91 @@
+package net.minecraft.src;
+
+public class EntitySnowman extends EntityGolem implements IRangedAttackMob {
+ public EntitySnowman(World par1World) {
+ super(par1World);
+ this.texture = "/mob/snowman.png";
+ this.setSize(0.4F, 1.8F);
+ this.getNavigator().setAvoidsWater(true);
+ this.tasks.addTask(1, new EntityAIArrowAttack(this, 0.25F, 20, 10.0F));
+ this.tasks.addTask(2, new EntityAIWander(this, 0.2F));
+ this.tasks.addTask(3, new EntityAIWatchClosest(this, EntityPlayer.class, 6.0F));
+ this.tasks.addTask(4, new EntityAILookIdle(this));
+ this.targetTasks.addTask(1,
+ new EntityAINearestAttackableTarget(this, EntityLiving.class, 16.0F, 0, true, false, IMob.mobSelector));
+ }
+
+ /**
+ * Returns true if the newer Entity AI code should be run
+ */
+ public boolean isAIEnabled() {
+ return true;
+ }
+
+ public int getMaxHealth() {
+ return 4;
+ }
+
+ /**
+ * Called frequently so the entity can update its state every tick as required.
+ * For example, zombies and skeletons use this to react to sunlight and start to
+ * burn.
+ */
+ public void onLivingUpdate() {
+ super.onLivingUpdate();
+
+ if (this.isWet()) {
+ this.attackEntityFrom(DamageSource.drown, 1);
+ }
+
+ int var1 = MathHelper.floor_double(this.posX);
+ int var2 = MathHelper.floor_double(this.posZ);
+
+ if (this.worldObj.getBiomeGenForCoords(var1, var2).getFloatTemperature() > 1.0F) {
+ this.attackEntityFrom(DamageSource.onFire, 1);
+ }
+
+ for (var1 = 0; var1 < 4; ++var1) {
+ var2 = MathHelper.floor_double(this.posX + (double) ((float) (var1 % 2 * 2 - 1) * 0.25F));
+ int var3 = MathHelper.floor_double(this.posY);
+ int var4 = MathHelper.floor_double(this.posZ + (double) ((float) (var1 / 2 % 2 * 2 - 1) * 0.25F));
+
+ if (this.worldObj.getBlockId(var2, var3, var4) == 0
+ && this.worldObj.getBiomeGenForCoords(var2, var4).getFloatTemperature() < 0.8F
+ && Block.snow.canPlaceBlockAt(this.worldObj, var2, var3, var4)) {
+ this.worldObj.setBlock(var2, var3, var4, Block.snow.blockID);
+ }
+ }
+ }
+
+ /**
+ * Returns the item ID for the item the mob drops on death.
+ */
+ protected int getDropItemId() {
+ return Item.snowball.itemID;
+ }
+
+ /**
+ * Drop 0-2 items of this living's type
+ */
+ protected void dropFewItems(boolean par1, int par2) {
+ int var3 = this.rand.nextInt(16);
+
+ for (int var4 = 0; var4 < var3; ++var4) {
+ this.dropItem(Item.snowball.itemID, 1);
+ }
+ }
+
+ /**
+ * Attack the specified entity using a ranged attack.
+ */
+ public void attackEntityWithRangedAttack(EntityLiving par1EntityLiving, float par2) {
+ EntitySnowball var3 = new EntitySnowball(this.worldObj, this);
+ double var4 = par1EntityLiving.posX - this.posX;
+ double var6 = par1EntityLiving.posY + (double) par1EntityLiving.getEyeHeight() - 1.100000023841858D - var3.posY;
+ double var8 = par1EntityLiving.posZ - this.posZ;
+ float var10 = MathHelper.sqrt_double(var4 * var4 + var8 * var8) * 0.2F;
+ var3.setThrowableHeading(var4, var6 + (double) var10, var8, 1.6F, 12.0F);
+ this.playSound("random.bow", 1.0F, 1.0F / (this.getRNG().nextFloat() * 0.4F + 0.8F));
+ this.worldObj.spawnEntityInWorld(var3);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntitySpider.java b/sp-server/src/main/java/net/minecraft/src/EntitySpider.java
new file mode 100644
index 0000000..78b6cd6
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntitySpider.java
@@ -0,0 +1,187 @@
+package net.minecraft.src;
+
+public class EntitySpider extends EntityMob {
+ public EntitySpider(World par1World) {
+ super(par1World);
+ this.texture = "/mob/spider.png";
+ this.setSize(1.4F, 0.9F);
+ this.moveSpeed = 0.8F;
+ }
+
+ protected void entityInit() {
+ super.entityInit();
+ this.dataWatcher.addObject(16, Byte.valueOf((byte) 0));
+ }
+
+ /**
+ * Called to update the entity's position/logic.
+ */
+ public void onUpdate() {
+ super.onUpdate();
+
+ if (!this.worldObj.isRemote) {
+ this.setBesideClimbableBlock(this.isCollidedHorizontally);
+ }
+ }
+
+ public int getMaxHealth() {
+ return 16;
+ }
+
+ /**
+ * Returns the Y offset from the entity's position for any entity riding this
+ * one.
+ */
+ public double getMountedYOffset() {
+ return (double) this.height * 0.75D - 0.5D;
+ }
+
+ /**
+ * Finds the closest player within 16 blocks to attack, or null if this Entity
+ * isn't interested in attacking (Animals, Spiders at day, peaceful PigZombies).
+ */
+ protected Entity findPlayerToAttack() {
+ float var1 = this.getBrightness(1.0F);
+
+ if (var1 < 0.5F) {
+ double var2 = 16.0D;
+ return this.worldObj.getClosestVulnerablePlayerToEntity(this, var2);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Returns the sound this mob makes while it's alive.
+ */
+ protected String getLivingSound() {
+ return "mob.spider.say";
+ }
+
+ /**
+ * Returns the sound this mob makes when it is hurt.
+ */
+ protected String getHurtSound() {
+ return "mob.spider.say";
+ }
+
+ /**
+ * Returns the sound this mob makes on death.
+ */
+ protected String getDeathSound() {
+ return "mob.spider.death";
+ }
+
+ /**
+ * Plays step sound at given x, y, z for the entity
+ */
+ protected void playStepSound(int par1, int par2, int par3, int par4) {
+ this.playSound("mob.spider.step", 0.15F, 1.0F);
+ }
+
+ /**
+ * Basic mob attack. Default to touch of death in EntityCreature. Overridden by
+ * each mob to define their attack.
+ */
+ protected void attackEntity(Entity par1Entity, float par2) {
+ float var3 = this.getBrightness(1.0F);
+
+ if (var3 > 0.5F && this.rand.nextInt(100) == 0) {
+ this.entityToAttack = null;
+ } else {
+ if (par2 > 2.0F && par2 < 6.0F && this.rand.nextInt(10) == 0) {
+ if (this.onGround) {
+ double var4 = par1Entity.posX - this.posX;
+ double var6 = par1Entity.posZ - this.posZ;
+ float var8 = MathHelper.sqrt_double(var4 * var4 + var6 * var6);
+ this.motionX = var4 / (double) var8 * 0.5D * 0.800000011920929D
+ + this.motionX * 0.20000000298023224D;
+ this.motionZ = var6 / (double) var8 * 0.5D * 0.800000011920929D
+ + this.motionZ * 0.20000000298023224D;
+ this.motionY = 0.4000000059604645D;
+ }
+ } else {
+ super.attackEntity(par1Entity, par2);
+ }
+ }
+ }
+
+ /**
+ * Returns the item ID for the item the mob drops on death.
+ */
+ protected int getDropItemId() {
+ return Item.silk.itemID;
+ }
+
+ /**
+ * Drop 0-2 items of this living's type
+ */
+ protected void dropFewItems(boolean par1, int par2) {
+ super.dropFewItems(par1, par2);
+
+ if (par1 && (this.rand.nextInt(3) == 0 || this.rand.nextInt(1 + par2) > 0)) {
+ this.dropItem(Item.spiderEye.itemID, 1);
+ }
+ }
+
+ /**
+ * returns true if this entity is by a ladder, false otherwise
+ */
+ public boolean isOnLadder() {
+ return this.isBesideClimbableBlock();
+ }
+
+ /**
+ * Sets the Entity inside a web block.
+ */
+ public void setInWeb() {
+ }
+
+ /**
+ * Get this Entity's EnumCreatureAttribute
+ */
+ public EnumCreatureAttribute getCreatureAttribute() {
+ return EnumCreatureAttribute.ARTHROPOD;
+ }
+
+ public boolean isPotionApplicable(PotionEffect par1PotionEffect) {
+ return par1PotionEffect.getPotionID() == Potion.poison.id ? false : super.isPotionApplicable(par1PotionEffect);
+ }
+
+ /**
+ * Returns true if the WatchableObject (Byte) is 0x01 otherwise returns false.
+ * The WatchableObject is updated using setBesideClimableBlock.
+ */
+ public boolean isBesideClimbableBlock() {
+ return (this.dataWatcher.getWatchableObjectByte(16) & 1) != 0;
+ }
+
+ /**
+ * Updates the WatchableObject (Byte) created in entityInit(), setting it to
+ * 0x01 if par1 is true or 0x00 if it is false.
+ */
+ public void setBesideClimbableBlock(boolean par1) {
+ byte var2 = this.dataWatcher.getWatchableObjectByte(16);
+
+ if (par1) {
+ var2 = (byte) (var2 | 1);
+ } else {
+ var2 &= -2;
+ }
+
+ this.dataWatcher.updateObject(16, Byte.valueOf(var2));
+ }
+
+ /**
+ * Initialize this creature.
+ */
+ public void initCreature() {
+ if (this.worldObj.rand.nextInt(100) == 0) {
+ EntitySkeleton var1 = new EntitySkeleton(this.worldObj);
+ var1.setLocationAndAngles(this.posX, this.posY, this.posZ, this.rotationYaw, 0.0F);
+ var1.initCreature();
+ this.worldObj.spawnEntityInWorld(var1);
+ var1.mountEntity(this);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntitySquid.java b/sp-server/src/main/java/net/minecraft/src/EntitySquid.java
new file mode 100644
index 0000000..54e61b9
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntitySquid.java
@@ -0,0 +1,186 @@
+package net.minecraft.src;
+
+public class EntitySquid extends EntityWaterMob {
+ public float field_70861_d = 0.0F;
+ public float field_70862_e = 0.0F;
+ public float field_70859_f = 0.0F;
+ public float field_70860_g = 0.0F;
+ public float field_70867_h = 0.0F;
+ public float field_70868_i = 0.0F;
+
+ /** angle of the tentacles in radians */
+ public float tentacleAngle = 0.0F;
+
+ /** the last calculated angle of the tentacles in radians */
+ public float lastTentacleAngle = 0.0F;
+ private float randomMotionSpeed = 0.0F;
+ private float field_70864_bA = 0.0F;
+ private float field_70871_bB = 0.0F;
+ private float randomMotionVecX = 0.0F;
+ private float randomMotionVecY = 0.0F;
+ private float randomMotionVecZ = 0.0F;
+
+ public EntitySquid(World par1World) {
+ super(par1World);
+ this.texture = "/mob/squid.png";
+ this.setSize(0.95F, 0.95F);
+ this.field_70864_bA = 1.0F / (this.rand.nextFloat() + 1.0F) * 0.2F;
+ }
+
+ public int getMaxHealth() {
+ return 10;
+ }
+
+ /**
+ * Returns the sound this mob makes while it's alive.
+ */
+ protected String getLivingSound() {
+ return null;
+ }
+
+ /**
+ * Returns the sound this mob makes when it is hurt.
+ */
+ protected String getHurtSound() {
+ return null;
+ }
+
+ /**
+ * Returns the sound this mob makes on death.
+ */
+ protected String getDeathSound() {
+ return null;
+ }
+
+ /**
+ * Returns the volume for the sounds this mob makes.
+ */
+ protected float getSoundVolume() {
+ return 0.4F;
+ }
+
+ /**
+ * Returns the item ID for the item the mob drops on death.
+ */
+ protected int getDropItemId() {
+ return 0;
+ }
+
+ /**
+ * Drop 0-2 items of this living's type
+ */
+ protected void dropFewItems(boolean par1, int par2) {
+ int var3 = this.rand.nextInt(3 + par2) + 1;
+
+ for (int var4 = 0; var4 < var3; ++var4) {
+ this.entityDropItem(new ItemStack(Item.dyePowder, 1, 0), 0.0F);
+ }
+ }
+
+ /**
+ * Checks if this entity is inside water (if inWater field is true as a result
+ * of handleWaterMovement() returning true)
+ */
+ public boolean isInWater() {
+ return this.worldObj.handleMaterialAcceleration(this.boundingBox.expand(0.0D, -0.6000000238418579D, 0.0D),
+ Material.water, this);
+ }
+
+ /**
+ * Called frequently so the entity can update its state every tick as required.
+ * For example, zombies and skeletons use this to react to sunlight and start to
+ * burn.
+ */
+ public void onLivingUpdate() {
+ super.onLivingUpdate();
+ this.field_70862_e = this.field_70861_d;
+ this.field_70860_g = this.field_70859_f;
+ this.field_70868_i = this.field_70867_h;
+ this.lastTentacleAngle = this.tentacleAngle;
+ this.field_70867_h += this.field_70864_bA;
+
+ if (this.field_70867_h > ((float) Math.PI * 2F)) {
+ this.field_70867_h -= ((float) Math.PI * 2F);
+
+ if (this.rand.nextInt(10) == 0) {
+ this.field_70864_bA = 1.0F / (this.rand.nextFloat() + 1.0F) * 0.2F;
+ }
+ }
+
+ if (this.isInWater()) {
+ float var1;
+
+ if (this.field_70867_h < (float) Math.PI) {
+ var1 = this.field_70867_h / (float) Math.PI;
+ this.tentacleAngle = MathHelper.sin(var1 * var1 * (float) Math.PI) * (float) Math.PI * 0.25F;
+
+ if ((double) var1 > 0.75D) {
+ this.randomMotionSpeed = 1.0F;
+ this.field_70871_bB = 1.0F;
+ } else {
+ this.field_70871_bB *= 0.8F;
+ }
+ } else {
+ this.tentacleAngle = 0.0F;
+ this.randomMotionSpeed *= 0.9F;
+ this.field_70871_bB *= 0.99F;
+ }
+
+ if (!this.worldObj.isRemote) {
+ this.motionX = (double) (this.randomMotionVecX * this.randomMotionSpeed);
+ this.motionY = (double) (this.randomMotionVecY * this.randomMotionSpeed);
+ this.motionZ = (double) (this.randomMotionVecZ * this.randomMotionSpeed);
+ }
+
+ var1 = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ);
+ this.renderYawOffset += (-((float) Math.atan2(this.motionX, this.motionZ)) * 180.0F / (float) Math.PI
+ - this.renderYawOffset) * 0.1F;
+ this.rotationYaw = this.renderYawOffset;
+ this.field_70859_f += (float) Math.PI * this.field_70871_bB * 1.5F;
+ this.field_70861_d += (-((float) Math.atan2((double) var1, this.motionY)) * 180.0F / (float) Math.PI
+ - this.field_70861_d) * 0.1F;
+ } else {
+ this.tentacleAngle = MathHelper.abs(MathHelper.sin(this.field_70867_h)) * (float) Math.PI * 0.25F;
+
+ if (!this.worldObj.isRemote) {
+ this.motionX = 0.0D;
+ this.motionY -= 0.08D;
+ this.motionY *= 0.9800000190734863D;
+ this.motionZ = 0.0D;
+ }
+
+ this.field_70861_d = (float) ((double) this.field_70861_d + (double) (-90.0F - this.field_70861_d) * 0.02D);
+ }
+ }
+
+ /**
+ * Moves the entity based on the specified heading. Args: strafe, forward
+ */
+ public void moveEntityWithHeading(float par1, float par2) {
+ this.moveEntity(this.motionX, this.motionY, this.motionZ);
+ }
+
+ protected void updateEntityActionState() {
+ ++this.entityAge;
+
+ if (this.entityAge > 100) {
+ this.randomMotionVecX = this.randomMotionVecY = this.randomMotionVecZ = 0.0F;
+ } else if (this.rand.nextInt(50) == 0 || !this.inWater
+ || this.randomMotionVecX == 0.0F && this.randomMotionVecY == 0.0F && this.randomMotionVecZ == 0.0F) {
+ float var1 = this.rand.nextFloat() * (float) Math.PI * 2.0F;
+ this.randomMotionVecX = MathHelper.cos(var1) * 0.2F;
+ this.randomMotionVecY = -0.1F + this.rand.nextFloat() * 0.2F;
+ this.randomMotionVecZ = MathHelper.sin(var1) * 0.2F;
+ }
+
+ this.despawnEntity();
+ }
+
+ /**
+ * Checks if the entity's current position is a valid location to spawn this
+ * entity.
+ */
+ public boolean getCanSpawnHere() {
+ return this.posY > 45.0D && this.posY < 63.0D && super.getCanSpawnHere();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityTNTPrimed.java b/sp-server/src/main/java/net/minecraft/src/EntityTNTPrimed.java
new file mode 100644
index 0000000..89f01a2
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityTNTPrimed.java
@@ -0,0 +1,104 @@
+package net.minecraft.src;
+
+public class EntityTNTPrimed extends Entity {
+ /** How long the fuse is */
+ public int fuse;
+ private EntityLiving tntPlacedBy;
+
+ public EntityTNTPrimed(World par1World) {
+ super(par1World);
+ this.fuse = 0;
+ this.preventEntitySpawning = true;
+ this.setSize(0.98F, 0.98F);
+ this.yOffset = this.height / 2.0F;
+ }
+
+ public EntityTNTPrimed(World par1World, double par2, double par4, double par6, EntityLiving par8EntityLiving) {
+ this(par1World);
+ this.setPosition(par2, par4, par6);
+ float var9 = (float) (Math.random() * Math.PI * 2.0D);
+ this.motionX = (double) (-((float) Math.sin((double) var9)) * 0.02F);
+ this.motionY = 0.20000000298023224D;
+ this.motionZ = (double) (-((float) Math.cos((double) var9)) * 0.02F);
+ this.fuse = 80;
+ this.prevPosX = par2;
+ this.prevPosY = par4;
+ this.prevPosZ = par6;
+ this.tntPlacedBy = par8EntityLiving;
+ }
+
+ protected void entityInit() {
+ }
+
+ /**
+ * returns if this entity triggers Block.onEntityWalking on the blocks they walk
+ * on. used for spiders and wolves to prevent them from trampling crops
+ */
+ protected boolean canTriggerWalking() {
+ return false;
+ }
+
+ /**
+ * Returns true if other Entities should be prevented from moving through this
+ * Entity.
+ */
+ public boolean canBeCollidedWith() {
+ return !this.isDead;
+ }
+
+ /**
+ * Called to update the entity's position/logic.
+ */
+ public void onUpdate() {
+ this.prevPosX = this.posX;
+ this.prevPosY = this.posY;
+ this.prevPosZ = this.posZ;
+ this.motionY -= 0.03999999910593033D;
+ this.moveEntity(this.motionX, this.motionY, this.motionZ);
+ this.motionX *= 0.9800000190734863D;
+ this.motionY *= 0.9800000190734863D;
+ this.motionZ *= 0.9800000190734863D;
+
+ if (this.onGround) {
+ this.motionX *= 0.699999988079071D;
+ this.motionZ *= 0.699999988079071D;
+ this.motionY *= -0.5D;
+ }
+
+ if (this.fuse-- <= 0) {
+ this.setDead();
+
+ if (!this.worldObj.isRemote) {
+ this.explode();
+ }
+ } else {
+ this.worldObj.spawnParticle("smoke", this.posX, this.posY + 0.5D, this.posZ, 0.0D, 0.0D, 0.0D);
+ }
+ }
+
+ private void explode() {
+ float var1 = 4.0F;
+ this.worldObj.createExplosion(this, this.posX, this.posY, this.posZ, var1, true);
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ protected void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ par1NBTTagCompound.setByte("Fuse", (byte) this.fuse);
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ protected void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ this.fuse = par1NBTTagCompound.getByte("Fuse");
+ }
+
+ /**
+ * returns null or the entityliving it was placed or ignited by
+ */
+ public EntityLiving getTntPlacedBy() {
+ return this.tntPlacedBy;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityTameable.java b/sp-server/src/main/java/net/minecraft/src/EntityTameable.java
new file mode 100644
index 0000000..7cde1d9
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityTameable.java
@@ -0,0 +1,112 @@
+package net.minecraft.src;
+
+public abstract class EntityTameable extends EntityAnimal {
+ protected EntityAISit aiSit = new EntityAISit(this);
+
+ public EntityTameable(World par1World) {
+ super(par1World);
+ }
+
+ protected void entityInit() {
+ super.entityInit();
+ this.dataWatcher.addObject(16, Byte.valueOf((byte) 0));
+ this.dataWatcher.addObject(17, "");
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ super.writeEntityToNBT(par1NBTTagCompound);
+
+ if (this.getOwnerName() == null) {
+ par1NBTTagCompound.setString("Owner", "");
+ } else {
+ par1NBTTagCompound.setString("Owner", this.getOwnerName());
+ }
+
+ par1NBTTagCompound.setBoolean("Sitting", this.isSitting());
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ super.readEntityFromNBT(par1NBTTagCompound);
+ String var2 = par1NBTTagCompound.getString("Owner");
+
+ if (var2.length() > 0) {
+ this.setOwner(var2);
+ this.setTamed(true);
+ }
+
+ this.aiSit.setSitting(par1NBTTagCompound.getBoolean("Sitting"));
+ this.setSitting(par1NBTTagCompound.getBoolean("Sitting"));
+ }
+
+ /**
+ * Play the taming effect, will either be hearts or smoke depending on status
+ */
+ protected void playTameEffect(boolean par1) {
+ String var2 = "heart";
+
+ if (!par1) {
+ var2 = "smoke";
+ }
+
+ for (int var3 = 0; var3 < 7; ++var3) {
+ double var4 = this.rand.nextGaussian() * 0.02D;
+ double var6 = this.rand.nextGaussian() * 0.02D;
+ double var8 = this.rand.nextGaussian() * 0.02D;
+ this.worldObj.spawnParticle(var2,
+ this.posX + (double) (this.rand.nextFloat() * this.width * 2.0F) - (double) this.width,
+ this.posY + 0.5D + (double) (this.rand.nextFloat() * this.height),
+ this.posZ + (double) (this.rand.nextFloat() * this.width * 2.0F) - (double) this.width, var4, var6,
+ var8);
+ }
+ }
+
+ public boolean isTamed() {
+ return (this.dataWatcher.getWatchableObjectByte(16) & 4) != 0;
+ }
+
+ public void setTamed(boolean par1) {
+ byte var2 = this.dataWatcher.getWatchableObjectByte(16);
+
+ if (par1) {
+ this.dataWatcher.updateObject(16, Byte.valueOf((byte) (var2 | 4)));
+ } else {
+ this.dataWatcher.updateObject(16, Byte.valueOf((byte) (var2 & -5)));
+ }
+ }
+
+ public boolean isSitting() {
+ return (this.dataWatcher.getWatchableObjectByte(16) & 1) != 0;
+ }
+
+ public void setSitting(boolean par1) {
+ byte var2 = this.dataWatcher.getWatchableObjectByte(16);
+
+ if (par1) {
+ this.dataWatcher.updateObject(16, Byte.valueOf((byte) (var2 | 1)));
+ } else {
+ this.dataWatcher.updateObject(16, Byte.valueOf((byte) (var2 & -2)));
+ }
+ }
+
+ public String getOwnerName() {
+ return this.dataWatcher.getWatchableObjectString(17);
+ }
+
+ public void setOwner(String par1Str) {
+ this.dataWatcher.updateObject(17, par1Str);
+ }
+
+ public EntityLiving getOwner() {
+ return this.worldObj.getPlayerEntityByName(this.getOwnerName());
+ }
+
+ public EntityAISit func_70907_r() {
+ return this.aiSit;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityThrowable.java b/sp-server/src/main/java/net/minecraft/src/EntityThrowable.java
new file mode 100644
index 0000000..169ae49
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityThrowable.java
@@ -0,0 +1,279 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+public abstract class EntityThrowable extends Entity implements IProjectile {
+ private int xTile = -1;
+ private int yTile = -1;
+ private int zTile = -1;
+ private int inTile = 0;
+ protected boolean inGround = false;
+ public int throwableShake = 0;
+
+ /** The entity that threw this throwable item. */
+ private EntityLiving thrower;
+ private String throwerName = null;
+ private int ticksInGround;
+ private int ticksInAir = 0;
+
+ public EntityThrowable(World par1World) {
+ super(par1World);
+ this.setSize(0.25F, 0.25F);
+ }
+
+ protected void entityInit() {
+ }
+
+ public EntityThrowable(World par1World, EntityLiving par2EntityLiving) {
+ super(par1World);
+ this.thrower = par2EntityLiving;
+ this.setSize(0.25F, 0.25F);
+ this.setLocationAndAngles(par2EntityLiving.posX,
+ par2EntityLiving.posY + (double) par2EntityLiving.getEyeHeight(), par2EntityLiving.posZ,
+ par2EntityLiving.rotationYaw, par2EntityLiving.rotationPitch);
+ this.posX -= (double) (MathHelper.cos(this.rotationYaw / 180.0F * (float) Math.PI) * 0.16F);
+ this.posY -= 0.10000000149011612D;
+ this.posZ -= (double) (MathHelper.sin(this.rotationYaw / 180.0F * (float) Math.PI) * 0.16F);
+ this.setPosition(this.posX, this.posY, this.posZ);
+ this.yOffset = 0.0F;
+ float var3 = 0.4F;
+ this.motionX = (double) (-MathHelper.sin(this.rotationYaw / 180.0F * (float) Math.PI)
+ * MathHelper.cos(this.rotationPitch / 180.0F * (float) Math.PI) * var3);
+ this.motionZ = (double) (MathHelper.cos(this.rotationYaw / 180.0F * (float) Math.PI)
+ * MathHelper.cos(this.rotationPitch / 180.0F * (float) Math.PI) * var3);
+ this.motionY = (double) (-MathHelper.sin((this.rotationPitch + this.func_70183_g()) / 180.0F * (float) Math.PI)
+ * var3);
+ this.setThrowableHeading(this.motionX, this.motionY, this.motionZ, this.func_70182_d(), 1.0F);
+ }
+
+ public EntityThrowable(World par1World, double par2, double par4, double par6) {
+ super(par1World);
+ this.ticksInGround = 0;
+ this.setSize(0.25F, 0.25F);
+ this.setPosition(par2, par4, par6);
+ this.yOffset = 0.0F;
+ }
+
+ protected float func_70182_d() {
+ return 1.5F;
+ }
+
+ protected float func_70183_g() {
+ return 0.0F;
+ }
+
+ /**
+ * Similar to setArrowHeading, it's point the throwable entity to a x, y, z
+ * direction.
+ */
+ public void setThrowableHeading(double par1, double par3, double par5, float par7, float par8) {
+ float var9 = MathHelper.sqrt_double(par1 * par1 + par3 * par3 + par5 * par5);
+ par1 /= (double) var9;
+ par3 /= (double) var9;
+ par5 /= (double) var9;
+ par1 += this.rand.nextGaussian() * 0.007499999832361937D * (double) par8;
+ par3 += this.rand.nextGaussian() * 0.007499999832361937D * (double) par8;
+ par5 += this.rand.nextGaussian() * 0.007499999832361937D * (double) par8;
+ par1 *= (double) par7;
+ par3 *= (double) par7;
+ par5 *= (double) par7;
+ this.motionX = par1;
+ this.motionY = par3;
+ this.motionZ = par5;
+ float var10 = MathHelper.sqrt_double(par1 * par1 + par5 * par5);
+ this.prevRotationYaw = this.rotationYaw = (float) (Math.atan2(par1, par5) * 180.0D / Math.PI);
+ this.prevRotationPitch = this.rotationPitch = (float) (Math.atan2(par3, (double) var10) * 180.0D / Math.PI);
+ this.ticksInGround = 0;
+ }
+
+ /**
+ * Called to update the entity's position/logic.
+ */
+ public void onUpdate() {
+ this.lastTickPosX = this.posX;
+ this.lastTickPosY = this.posY;
+ this.lastTickPosZ = this.posZ;
+ super.onUpdate();
+
+ if (this.throwableShake > 0) {
+ --this.throwableShake;
+ }
+
+ if (this.inGround) {
+ int var1 = this.worldObj.getBlockId(this.xTile, this.yTile, this.zTile);
+
+ if (var1 == this.inTile) {
+ ++this.ticksInGround;
+
+ if (this.ticksInGround == 1200) {
+ this.setDead();
+ }
+
+ return;
+ }
+
+ this.inGround = false;
+ this.motionX *= (double) (this.rand.nextFloat() * 0.2F);
+ this.motionY *= (double) (this.rand.nextFloat() * 0.2F);
+ this.motionZ *= (double) (this.rand.nextFloat() * 0.2F);
+ this.ticksInGround = 0;
+ this.ticksInAir = 0;
+ } else {
+ ++this.ticksInAir;
+ }
+
+ Vec3 var16 = this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX, this.posY, this.posZ);
+ Vec3 var2 = this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX + this.motionX, this.posY + this.motionY,
+ this.posZ + this.motionZ);
+ MovingObjectPosition var3 = this.worldObj.rayTraceBlocks(var16, var2);
+ var16 = this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX, this.posY, this.posZ);
+ var2 = this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX + this.motionX, this.posY + this.motionY,
+ this.posZ + this.motionZ);
+
+ if (var3 != null) {
+ var2 = this.worldObj.getWorldVec3Pool().getVecFromPool(var3.hitVec.xCoord, var3.hitVec.yCoord,
+ var3.hitVec.zCoord);
+ }
+
+ if (!this.worldObj.isRemote) {
+ Entity var4 = null;
+ List var5 = this.worldObj.getEntitiesWithinAABBExcludingEntity(this,
+ this.boundingBox.addCoord(this.motionX, this.motionY, this.motionZ).expand(1.0D, 1.0D, 1.0D));
+ double var6 = 0.0D;
+ EntityLiving var8 = this.getThrower();
+
+ for (int var9 = 0; var9 < var5.size(); ++var9) {
+ Entity var10 = (Entity) var5.get(var9);
+
+ if (var10.canBeCollidedWith() && (var10 != var8 || this.ticksInAir >= 5)) {
+ float var11 = 0.3F;
+ AxisAlignedBB var12 = var10.boundingBox.expand((double) var11, (double) var11, (double) var11);
+ MovingObjectPosition var13 = var12.calculateIntercept(var16, var2);
+
+ if (var13 != null) {
+ double var14 = var16.distanceTo(var13.hitVec);
+
+ if (var14 < var6 || var6 == 0.0D) {
+ var4 = var10;
+ var6 = var14;
+ }
+ }
+ }
+ }
+
+ if (var4 != null) {
+ var3 = new MovingObjectPosition(var4);
+ }
+ }
+
+ if (var3 != null) {
+ if (var3.typeOfHit == EnumMovingObjectType.TILE
+ && this.worldObj.getBlockId(var3.blockX, var3.blockY, var3.blockZ) == Block.portal.blockID) {
+ this.setInPortal();
+ } else {
+ this.onImpact(var3);
+ }
+ }
+
+ this.posX += this.motionX;
+ this.posY += this.motionY;
+ this.posZ += this.motionZ;
+ float var17 = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ);
+ this.rotationYaw = (float) (Math.atan2(this.motionX, this.motionZ) * 180.0D / Math.PI);
+
+ for (this.rotationPitch = (float) (Math.atan2(this.motionY, (double) var17) * 180.0D
+ / Math.PI); this.rotationPitch - this.prevRotationPitch < -180.0F; this.prevRotationPitch -= 360.0F) {
+ ;
+ }
+
+ while (this.rotationPitch - this.prevRotationPitch >= 180.0F) {
+ this.prevRotationPitch += 360.0F;
+ }
+
+ while (this.rotationYaw - this.prevRotationYaw < -180.0F) {
+ this.prevRotationYaw -= 360.0F;
+ }
+
+ while (this.rotationYaw - this.prevRotationYaw >= 180.0F) {
+ this.prevRotationYaw += 360.0F;
+ }
+
+ this.rotationPitch = this.prevRotationPitch + (this.rotationPitch - this.prevRotationPitch) * 0.2F;
+ this.rotationYaw = this.prevRotationYaw + (this.rotationYaw - this.prevRotationYaw) * 0.2F;
+ float var18 = 0.99F;
+ float var19 = this.getGravityVelocity();
+
+ if (this.isInWater()) {
+ for (int var7 = 0; var7 < 4; ++var7) {
+ float var20 = 0.25F;
+ this.worldObj.spawnParticle("bubble", this.posX - this.motionX * (double) var20,
+ this.posY - this.motionY * (double) var20, this.posZ - this.motionZ * (double) var20,
+ this.motionX, this.motionY, this.motionZ);
+ }
+
+ var18 = 0.8F;
+ }
+
+ this.motionX *= (double) var18;
+ this.motionY *= (double) var18;
+ this.motionZ *= (double) var18;
+ this.motionY -= (double) var19;
+ this.setPosition(this.posX, this.posY, this.posZ);
+ }
+
+ /**
+ * Gets the amount of gravity to apply to the thrown entity with each tick.
+ */
+ protected float getGravityVelocity() {
+ return 0.03F;
+ }
+
+ /**
+ * Called when this EntityThrowable hits a block or entity.
+ */
+ protected abstract void onImpact(MovingObjectPosition var1);
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ par1NBTTagCompound.setShort("xTile", (short) this.xTile);
+ par1NBTTagCompound.setShort("yTile", (short) this.yTile);
+ par1NBTTagCompound.setShort("zTile", (short) this.zTile);
+ par1NBTTagCompound.setByte("inTile", (byte) this.inTile);
+ par1NBTTagCompound.setByte("shake", (byte) this.throwableShake);
+ par1NBTTagCompound.setByte("inGround", (byte) (this.inGround ? 1 : 0));
+
+ if ((this.throwerName == null || this.throwerName.length() == 0) && this.thrower != null
+ && this.thrower instanceof EntityPlayer) {
+ this.throwerName = this.thrower.getEntityName();
+ }
+
+ par1NBTTagCompound.setString("ownerName", this.throwerName == null ? "" : this.throwerName);
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ this.xTile = par1NBTTagCompound.getShort("xTile");
+ this.yTile = par1NBTTagCompound.getShort("yTile");
+ this.zTile = par1NBTTagCompound.getShort("zTile");
+ this.inTile = par1NBTTagCompound.getByte("inTile") & 255;
+ this.throwableShake = par1NBTTagCompound.getByte("shake") & 255;
+ this.inGround = par1NBTTagCompound.getByte("inGround") == 1;
+ this.throwerName = par1NBTTagCompound.getString("ownerName");
+
+ if (this.throwerName != null && this.throwerName.length() == 0) {
+ this.throwerName = null;
+ }
+ }
+
+ public EntityLiving getThrower() {
+ if (this.thrower == null && this.throwerName != null && this.throwerName.length() > 0) {
+ this.thrower = this.worldObj.getPlayerEntityByName(this.throwerName);
+ }
+
+ return this.thrower;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityTracker.java b/sp-server/src/main/java/net/minecraft/src/EntityTracker.java
new file mode 100644
index 0000000..0e6116b
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityTracker.java
@@ -0,0 +1,219 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+public class EntityTracker {
+ private final WorldServer theWorld;
+
+ /**
+ * List of tracked entities, used for iteration operations on tracked entities.
+ */
+ private Set trackedEntities = new HashSet();
+
+ /** Used for identity lookup of tracked entities. */
+ private IntHashMap trackedEntityHashTable = new IntHashMap();
+ private int maxTrackingDistanceThreshold;
+
+ public EntityTracker(WorldServer par1WorldServer) {
+ this.theWorld = par1WorldServer;
+ this.maxTrackingDistanceThreshold = par1WorldServer.getMinecraftServer().getConfigurationManager()
+ .getEntityViewDistance();
+ }
+
+ public void setMainRenderDistance(int newDistance) {
+ if(this.maxTrackingDistanceThreshold != newDistance) {
+ this.maxTrackingDistanceThreshold = newDistance;
+ List currentTrackedEntities = new ArrayList();
+ currentTrackedEntities.addAll(trackedEntities);
+ for(int i = 0, l = currentTrackedEntities.size(); i < l; ++i) {
+ Entity et = (Entity) currentTrackedEntities.get(i);
+ untrackEntity(et);
+ trackEntity(et);
+ }
+ }
+ }
+
+ public void trackEntity(Entity par1Entity) {
+ if (par1Entity instanceof EntityPlayerMP) {
+ this.trackEntity(par1Entity, 512, 2);
+ EntityPlayerMP var2 = (EntityPlayerMP) par1Entity;
+ Iterator var3 = this.trackedEntities.iterator();
+
+ while (var3.hasNext()) {
+ EntityTrackerEntry var4 = (EntityTrackerEntry) var3.next();
+
+ if (var4.trackedEntity != var2) {
+ var4.updatePlayerEntity(var2);
+ }
+ }
+ } else if (par1Entity instanceof EntityFishHook) {
+ this.trackEntity(par1Entity, 64, 5, true);
+ } else if (par1Entity instanceof EntityArrow) {
+ this.trackEntity(par1Entity, 64, 20, false);
+ } else if (par1Entity instanceof EntitySmallFireball) {
+ this.trackEntity(par1Entity, 64, 10, false);
+ } else if (par1Entity instanceof EntityFireball) {
+ this.trackEntity(par1Entity, 64, 10, false);
+ } else if (par1Entity instanceof EntitySnowball) {
+ this.trackEntity(par1Entity, 64, 10, true);
+ } else if (par1Entity instanceof EntityEnderPearl) {
+ this.trackEntity(par1Entity, 64, 10, true);
+ } else if (par1Entity instanceof EntityEnderEye) {
+ this.trackEntity(par1Entity, 64, 4, true);
+ } else if (par1Entity instanceof EntityEgg) {
+ this.trackEntity(par1Entity, 64, 10, true);
+ } else if (par1Entity instanceof EntityPotion) {
+ this.trackEntity(par1Entity, 64, 10, true);
+ } else if (par1Entity instanceof EntityExpBottle) {
+ this.trackEntity(par1Entity, 64, 10, true);
+ } else if (par1Entity instanceof EntityFireworkRocket) {
+ this.trackEntity(par1Entity, 64, 10, true);
+ } else if (par1Entity instanceof EntityItem) {
+ this.trackEntity(par1Entity, 64, 20, true);
+ } else if (par1Entity instanceof EntityMinecart) {
+ this.trackEntity(par1Entity, 80, 3, true);
+ } else if (par1Entity instanceof EntityBoat) {
+ this.trackEntity(par1Entity, 80, 3, true);
+ } else if (par1Entity instanceof EntitySquid) {
+ this.trackEntity(par1Entity, 64, 3, true);
+ } else if (par1Entity instanceof EntityWither) {
+ this.trackEntity(par1Entity, 80, 3, false);
+ } else if (par1Entity instanceof EntityBat) {
+ this.trackEntity(par1Entity, 80, 3, false);
+ } else if (par1Entity instanceof IAnimals) {
+ this.trackEntity(par1Entity, 80, 3, true);
+ } else if (par1Entity instanceof EntityDragon) {
+ this.trackEntity(par1Entity, 160, 3, true);
+ } else if (par1Entity instanceof EntityTNTPrimed) {
+ this.trackEntity(par1Entity, 160, 10, true);
+ } else if (par1Entity instanceof EntityFallingSand) {
+ this.trackEntity(par1Entity, 160, 20, true);
+ } else if (par1Entity instanceof EntityPainting) {
+ this.trackEntity(par1Entity, 160, Integer.MAX_VALUE, false);
+ } else if (par1Entity instanceof EntityXPOrb) {
+ this.trackEntity(par1Entity, 160, 20, true);
+ } else if (par1Entity instanceof EntityEnderCrystal) {
+ this.trackEntity(par1Entity, 256, Integer.MAX_VALUE, false);
+ } else if (par1Entity instanceof EntityItemFrame) {
+ this.trackEntity(par1Entity, 160, Integer.MAX_VALUE, false);
+ }
+ }
+
+ public void trackEntity(Entity par1Entity, int par2, int par3) {
+ this.trackEntity(par1Entity, par2, par3, false);
+ }
+
+ public void trackEntity(Entity par1Entity, int par2, int par3, boolean par4) {
+ if (par2 > this.maxTrackingDistanceThreshold) {
+ par2 = this.maxTrackingDistanceThreshold;
+ }
+
+ try {
+ if (this.trackedEntityHashTable.containsItem(par1Entity.entityId)) {
+ throw new IllegalStateException("Entity is already tracked!");
+ }
+
+ EntityTrackerEntry var5 = new EntityTrackerEntry(par1Entity, par2, par3, par4);
+ this.trackedEntities.add(var5);
+ this.trackedEntityHashTable.addKey(par1Entity.entityId, var5);
+ var5.updatePlayerEntities(this.theWorld.playerEntities);
+ } catch (Throwable var11) {
+ System.err.println("\"Silently\" catching entity tracking error.");
+ var11.printStackTrace();
+ }
+ }
+
+ public void untrackEntity(Entity par1Entity) {
+ untrackEntity(par1Entity, false);
+ }
+ public void untrackEntity(Entity par1Entity, boolean asap) {
+ if (par1Entity instanceof EntityPlayerMP) {
+ EntityPlayerMP var2 = (EntityPlayerMP) par1Entity;
+ Iterator var3 = this.trackedEntities.iterator();
+
+ while (var3.hasNext()) {
+ EntityTrackerEntry var4 = (EntityTrackerEntry) var3.next();
+ var4.removeFromTrackedPlayers(var2, asap);
+ }
+ }
+
+ EntityTrackerEntry var5 = (EntityTrackerEntry) this.trackedEntityHashTable.removeObject(par1Entity.entityId);
+
+ if (var5 != null) {
+ this.trackedEntities.remove(var5);
+ var5.sendDestroyEntityPacketToTrackedPlayers(asap);
+ }
+ }
+
+ public void updateTrackedEntities() {
+ ArrayList var1 = new ArrayList();
+ Iterator var2 = this.trackedEntities.iterator();
+
+ while (var2.hasNext()) {
+ EntityTrackerEntry var3 = (EntityTrackerEntry) var2.next();
+ var3.updatePlayerList(this.theWorld.playerEntities);
+
+ if (var3.playerEntitiesUpdated && var3.trackedEntity instanceof EntityPlayerMP) {
+ var1.add((EntityPlayerMP) var3.trackedEntity);
+ }
+ }
+
+ for (int var6 = 0; var6 < var1.size(); ++var6) {
+ EntityPlayerMP var7 = (EntityPlayerMP) var1.get(var6);
+ Iterator var4 = this.trackedEntities.iterator();
+
+ while (var4.hasNext()) {
+ EntityTrackerEntry var5 = (EntityTrackerEntry) var4.next();
+
+ if (var5.trackedEntity != var7) {
+ var5.updatePlayerEntity(var7);
+ }
+ }
+ }
+ }
+
+ public void sendPacketToTrackedPlayers(Entity par1Entity, Packet par2Packet) {
+ EntityTrackerEntry var3 = (EntityTrackerEntry) this.trackedEntityHashTable.lookup(par1Entity.entityId);
+
+ if (var3 != null) {
+ var3.sendPacketToTrackedPlayers(par2Packet);
+ }
+ }
+
+ public void sendPacketToTrackedPlayersAndTrackedEntity(Entity par1Entity, Packet par2Packet) {
+ EntityTrackerEntry var3 = (EntityTrackerEntry) this.trackedEntityHashTable.lookup(par1Entity.entityId);
+
+ if (var3 != null) {
+ var3.sendPacketToTrackedPlayersAndTrackedEntity(par2Packet);
+ }
+ }
+
+ public void removePlayerFromTrackers(EntityPlayerMP par1EntityPlayerMP) {
+ removePlayerFromTrackers(par1EntityPlayerMP, false);
+ }
+ public void removePlayerFromTrackers(EntityPlayerMP par1EntityPlayerMP, boolean asap) {
+ Iterator var2 = this.trackedEntities.iterator();
+
+ while (var2.hasNext()) {
+ EntityTrackerEntry var3 = (EntityTrackerEntry) var2.next();
+ var3.removeTrackedPlayerSymmetric(par1EntityPlayerMP, asap);
+ }
+ }
+
+ public void func_85172_a(EntityPlayerMP par1EntityPlayerMP, Chunk par2Chunk) {
+ Iterator var3 = this.trackedEntities.iterator();
+
+ while (var3.hasNext()) {
+ EntityTrackerEntry var4 = (EntityTrackerEntry) var3.next();
+
+ if (var4.trackedEntity != par1EntityPlayerMP && var4.trackedEntity.chunkCoordX == par2Chunk.xPosition
+ && var4.trackedEntity.chunkCoordZ == par2Chunk.zPosition) {
+ var4.updatePlayerEntity(par1EntityPlayerMP);
+ }
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityTrackerEntry.java b/sp-server/src/main/java/net/minecraft/src/EntityTrackerEntry.java
new file mode 100644
index 0000000..164267a
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityTrackerEntry.java
@@ -0,0 +1,498 @@
+package net.minecraft.src;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+public class EntityTrackerEntry {
+ /** The entity that this EntityTrackerEntry tracks. */
+ public Entity trackedEntity;
+ public int trackingDistanceThreshold;
+
+ /** check for sync when ticks % updateFrequency==0 */
+ public int updateFrequency;
+
+ /** The encoded entity X position. */
+ public int encodedPosX;
+
+ /** The encoded entity Y position. */
+ public int encodedPosY;
+
+ /** The encoded entity Z position. */
+ public int encodedPosZ;
+
+ /** The encoded entity yaw rotation. */
+ public int encodedRotationYaw;
+
+ /** The encoded entity pitch rotation. */
+ public int encodedRotationPitch;
+ public int lastHeadMotion;
+ public double lastTrackedEntityMotionX;
+ public double lastTrackedEntityMotionY;
+ public double motionZ;
+ public int updateCounter = 0;
+ private double lastTrackedEntityPosX;
+ private double lastTrackedEntityPosY;
+ private double lastTrackedEntityPosZ;
+ private boolean firstUpdateDone = false;
+ private boolean sendVelocityUpdates;
+
+ /**
+ * every 400 ticks a full teleport packet is sent, rather than just a "move me
+ * +x" command, so that position remains fully synced.
+ */
+ private int ticksSinceLastForcedTeleport = 0;
+ private Entity field_85178_v;
+ private boolean ridingEntity = false;
+ public boolean playerEntitiesUpdated = false;
+
+ /**
+ * Holds references to all the players that are currently receiving position
+ * updates for this entity.
+ */
+ public Set trackingPlayers = new HashSet();
+
+ public EntityTrackerEntry(Entity par1Entity, int par2, int par3, boolean par4) {
+ this.trackedEntity = par1Entity;
+ this.trackingDistanceThreshold = par2;
+ this.updateFrequency = par3;
+ this.sendVelocityUpdates = par4;
+ this.encodedPosX = MathHelper.floor_double(par1Entity.posX * 32.0D);
+ this.encodedPosY = MathHelper.floor_double(par1Entity.posY * 32.0D);
+ this.encodedPosZ = MathHelper.floor_double(par1Entity.posZ * 32.0D);
+ this.encodedRotationYaw = MathHelper.floor_float(par1Entity.rotationYaw * 256.0F / 360.0F);
+ this.encodedRotationPitch = MathHelper.floor_float(par1Entity.rotationPitch * 256.0F / 360.0F);
+ this.lastHeadMotion = MathHelper.floor_float(par1Entity.getRotationYawHead() * 256.0F / 360.0F);
+ }
+
+ public boolean equals(Object par1Obj) {
+ return par1Obj instanceof EntityTrackerEntry
+ ? ((EntityTrackerEntry) par1Obj).trackedEntity.entityId == this.trackedEntity.entityId
+ : false;
+ }
+
+ public int hashCode() {
+ return this.trackedEntity.entityId;
+ }
+
+ public void updatePlayerList(List par1List) {
+ this.playerEntitiesUpdated = false;
+
+ if (!this.firstUpdateDone || this.trackedEntity.getDistanceSq(this.lastTrackedEntityPosX,
+ this.lastTrackedEntityPosY, this.lastTrackedEntityPosZ) > 16.0D) {
+ this.lastTrackedEntityPosX = this.trackedEntity.posX;
+ this.lastTrackedEntityPosY = this.trackedEntity.posY;
+ this.lastTrackedEntityPosZ = this.trackedEntity.posZ;
+ this.firstUpdateDone = true;
+ this.playerEntitiesUpdated = true;
+ this.updatePlayerEntities(par1List);
+ }
+
+ if (this.field_85178_v != this.trackedEntity.ridingEntity
+ || this.trackedEntity.ridingEntity != null && this.updateCounter % 60 == 0) {
+ this.field_85178_v = this.trackedEntity.ridingEntity;
+ this.sendPacketToTrackedPlayers(
+ new Packet39AttachEntity(this.trackedEntity, this.trackedEntity.ridingEntity));
+ }
+
+ if (this.trackedEntity instanceof EntityItemFrame && this.updateCounter % 10 == 0) {
+ EntityItemFrame var23 = (EntityItemFrame) this.trackedEntity;
+ ItemStack var24 = var23.getDisplayedItem();
+
+ if (var24 != null && var24.getItem() instanceof ItemMap) {
+ MapData var26 = Item.map.getMapData(var24, this.trackedEntity.worldObj);
+ Iterator var29 = par1List.iterator();
+
+ while (var29.hasNext()) {
+ EntityPlayer var30 = (EntityPlayer) var29.next();
+ EntityPlayerMP var31 = (EntityPlayerMP) var30;
+ var26.updateVisiblePlayers(var31, var24);
+
+ if (var31.playerNetServerHandler.getNumChunkDataPackets() <= 5) {
+ Packet var32 = Item.map.getUpdatePacket(var24, this.trackedEntity.worldObj, var31);
+
+ if (var32 != null) {
+ var31.playerNetServerHandler.sendPacket(var32);
+ }
+ }
+ }
+ }
+
+ DataWatcher var27 = this.trackedEntity.getDataWatcher();
+
+ if (var27.hasObjectChanged()) {
+ this.sendPacketToTrackedPlayersAndTrackedEntity(
+ new Packet40EntityMetadata(this.trackedEntity.entityId, var27, false));
+ }
+ } else if (this.updateCounter % this.updateFrequency == 0 || this.trackedEntity.isAirBorne
+ || this.trackedEntity.getDataWatcher().hasObjectChanged()) {
+ int var2;
+ int var3;
+
+ if (this.trackedEntity.ridingEntity == null) {
+ ++this.ticksSinceLastForcedTeleport;
+ var2 = this.trackedEntity.myEntitySize.multiplyBy32AndRound(this.trackedEntity.posX);
+ var3 = MathHelper.floor_double(this.trackedEntity.posY * 32.0D);
+ int var4 = this.trackedEntity.myEntitySize.multiplyBy32AndRound(this.trackedEntity.posZ);
+ int var5 = MathHelper.floor_float(this.trackedEntity.rotationYaw * 256.0F / 360.0F);
+ int var6 = MathHelper.floor_float(this.trackedEntity.rotationPitch * 256.0F / 360.0F);
+ int var7 = var2 - this.encodedPosX;
+ int var8 = var3 - this.encodedPosY;
+ int var9 = var4 - this.encodedPosZ;
+ Object var10 = null;
+ boolean var11 = Math.abs(var7) >= 4 || Math.abs(var8) >= 4 || Math.abs(var9) >= 4
+ || this.updateCounter % 60 == 0;
+ boolean var12 = Math.abs(var5 - this.encodedRotationYaw) >= 4
+ || Math.abs(var6 - this.encodedRotationPitch) >= 4;
+
+ if (this.updateCounter > 0 || this.trackedEntity instanceof EntityArrow) {
+ if (var7 >= -128 && var7 < 128 && var8 >= -128 && var8 < 128 && var9 >= -128 && var9 < 128
+ && this.ticksSinceLastForcedTeleport <= 400 && !this.ridingEntity) {
+ if (var11 && var12) {
+ var10 = new Packet33RelEntityMoveLook(this.trackedEntity.entityId, (byte) var7, (byte) var8,
+ (byte) var9, (byte) var5, (byte) var6);
+ } else if (var11) {
+ var10 = new Packet31RelEntityMove(this.trackedEntity.entityId, (byte) var7, (byte) var8,
+ (byte) var9);
+ } else if (var12) {
+ var10 = new Packet32EntityLook(this.trackedEntity.entityId, (byte) var5, (byte) var6);
+ }
+ } else {
+ this.ticksSinceLastForcedTeleport = 0;
+ var10 = new Packet34EntityTeleport(this.trackedEntity.entityId, var2, var3, var4, (byte) var5,
+ (byte) var6);
+ }
+ }
+
+ if (this.sendVelocityUpdates) {
+ double var13 = this.trackedEntity.motionX - this.lastTrackedEntityMotionX;
+ double var15 = this.trackedEntity.motionY - this.lastTrackedEntityMotionY;
+ double var17 = this.trackedEntity.motionZ - this.motionZ;
+ double var19 = 0.02D;
+ double var21 = var13 * var13 + var15 * var15 + var17 * var17;
+
+ if (var21 > var19 * var19 || var21 > 0.0D && this.trackedEntity.motionX == 0.0D
+ && this.trackedEntity.motionY == 0.0D && this.trackedEntity.motionZ == 0.0D) {
+ this.lastTrackedEntityMotionX = this.trackedEntity.motionX;
+ this.lastTrackedEntityMotionY = this.trackedEntity.motionY;
+ this.motionZ = this.trackedEntity.motionZ;
+ this.sendPacketToTrackedPlayers(new Packet28EntityVelocity(this.trackedEntity.entityId,
+ this.lastTrackedEntityMotionX, this.lastTrackedEntityMotionY, this.motionZ));
+ }
+ }
+
+ if (var10 != null) {
+ this.sendPacketToTrackedPlayers((Packet) var10);
+ }
+
+ DataWatcher var33 = this.trackedEntity.getDataWatcher();
+
+ if (var33.hasObjectChanged()) {
+ this.sendPacketToTrackedPlayersAndTrackedEntity(
+ new Packet40EntityMetadata(this.trackedEntity.entityId, var33, false));
+ }
+
+ if (var11) {
+ this.encodedPosX = var2;
+ this.encodedPosY = var3;
+ this.encodedPosZ = var4;
+ }
+
+ if (var12) {
+ this.encodedRotationYaw = var5;
+ this.encodedRotationPitch = var6;
+ }
+
+ this.ridingEntity = false;
+ } else {
+ var2 = MathHelper.floor_float(this.trackedEntity.rotationYaw * 256.0F / 360.0F);
+ var3 = MathHelper.floor_float(this.trackedEntity.rotationPitch * 256.0F / 360.0F);
+ boolean var25 = Math.abs(var2 - this.encodedRotationYaw) >= 4
+ || Math.abs(var3 - this.encodedRotationPitch) >= 4;
+
+ if (var25) {
+ this.sendPacketToTrackedPlayers(
+ new Packet32EntityLook(this.trackedEntity.entityId, (byte) var2, (byte) var3));
+ this.encodedRotationYaw = var2;
+ this.encodedRotationPitch = var3;
+ }
+
+ this.encodedPosX = this.trackedEntity.myEntitySize.multiplyBy32AndRound(this.trackedEntity.posX);
+ this.encodedPosY = MathHelper.floor_double(this.trackedEntity.posY * 32.0D);
+ this.encodedPosZ = this.trackedEntity.myEntitySize.multiplyBy32AndRound(this.trackedEntity.posZ);
+ DataWatcher var28 = this.trackedEntity.getDataWatcher();
+
+ if (var28.hasObjectChanged()) {
+ this.sendPacketToTrackedPlayersAndTrackedEntity(
+ new Packet40EntityMetadata(this.trackedEntity.entityId, var28, false));
+ }
+
+ this.ridingEntity = true;
+ }
+
+ var2 = MathHelper.floor_float(this.trackedEntity.getRotationYawHead() * 256.0F / 360.0F);
+
+ if (Math.abs(var2 - this.lastHeadMotion) >= 4) {
+ this.sendPacketToTrackedPlayers(
+ new Packet35EntityHeadRotation(this.trackedEntity.entityId, (byte) var2));
+ this.lastHeadMotion = var2;
+ }
+
+ this.trackedEntity.isAirBorne = false;
+ }
+
+ ++this.updateCounter;
+
+ if (this.trackedEntity.velocityChanged) {
+ this.sendPacketToTrackedPlayersAndTrackedEntity(new Packet28EntityVelocity(this.trackedEntity));
+ this.trackedEntity.velocityChanged = false;
+ }
+ }
+
+ public void sendPacketToTrackedPlayers(Packet par1Packet) {
+ Iterator var2 = this.trackingPlayers.iterator();
+
+ while (var2.hasNext()) {
+ EntityPlayerMP var3 = (EntityPlayerMP) var2.next();
+ var3.playerNetServerHandler.sendPacket(par1Packet);
+ }
+ }
+
+ public void sendPacketToTrackedPlayersAndTrackedEntity(Packet par1Packet) {
+ this.sendPacketToTrackedPlayers(par1Packet);
+
+ if (this.trackedEntity instanceof EntityPlayerMP) {
+ ((EntityPlayerMP) this.trackedEntity).playerNetServerHandler.sendPacket(par1Packet);
+ }
+ }
+
+ public void sendDestroyEntityPacketToTrackedPlayers() {
+ sendDestroyEntityPacketToTrackedPlayers(false);
+ }
+
+ public void sendDestroyEntityPacketToTrackedPlayers(boolean asap) {
+ Iterator var1 = this.trackingPlayers.iterator();
+
+ while (var1.hasNext()) {
+ EntityPlayerMP var2 = (EntityPlayerMP) var1.next();
+ //System.out.println(this.trackedEntity.getEntityName() + ": sendDestroyEntityPacketToTrackedPlayers");
+ if (asap) {
+ var2.playerNetServerHandler.sendPacket(new Packet29DestroyEntity(Integer.valueOf(this.trackedEntity.entityId)));
+ } else {
+ var2.destroyedItemsNetCache.add(Integer.valueOf(this.trackedEntity.entityId));
+ }
+ }
+ }
+
+ public void removeFromTrackedPlayers(EntityPlayerMP par1EntityPlayerMP) {
+ removeFromTrackedPlayers(par1EntityPlayerMP, false);
+ }
+ public void removeFromTrackedPlayers(EntityPlayerMP par1EntityPlayerMP, boolean asap) {
+ if (this.trackingPlayers.contains(par1EntityPlayerMP)) {
+ //System.out.println(this.trackedEntity.getEntityName() + ": removeFromTrackedPlayers");
+ if (asap) {
+ par1EntityPlayerMP.playerNetServerHandler.sendPacket(new Packet29DestroyEntity(Integer.valueOf(this.trackedEntity.entityId)));
+ } else {
+ par1EntityPlayerMP.destroyedItemsNetCache.add(Integer.valueOf(this.trackedEntity.entityId));
+ }
+ this.trackingPlayers.remove(par1EntityPlayerMP);
+ }
+ }
+
+ public void updatePlayerEntity(EntityPlayerMP par1EntityPlayerMP) {
+ if (par1EntityPlayerMP != this.trackedEntity) {
+ double var2 = par1EntityPlayerMP.posX - (double) (this.encodedPosX / 32);
+ double var4 = par1EntityPlayerMP.posZ - (double) (this.encodedPosZ / 32);
+
+ if (var2 >= (double) (-this.trackingDistanceThreshold) && var2 <= (double) this.trackingDistanceThreshold
+ && var4 >= (double) (-this.trackingDistanceThreshold)
+ && var4 <= (double) this.trackingDistanceThreshold) {
+ if (!this.trackingPlayers.contains(par1EntityPlayerMP)
+ && (this.isPlayerWatchingThisChunk(par1EntityPlayerMP) || this.trackedEntity.field_98038_p)) {
+ this.trackingPlayers.add(par1EntityPlayerMP);
+ Packet var6 = this.getSpawnPacket();
+ par1EntityPlayerMP.playerNetServerHandler.sendPacket(var6);
+
+ if (!this.trackedEntity.getDataWatcher().getIsBlank()) {
+ par1EntityPlayerMP.playerNetServerHandler.sendPacket(new Packet40EntityMetadata(
+ this.trackedEntity.entityId, this.trackedEntity.getDataWatcher(), true));
+ }
+
+ this.lastTrackedEntityMotionX = this.trackedEntity.motionX;
+ this.lastTrackedEntityMotionY = this.trackedEntity.motionY;
+ this.motionZ = this.trackedEntity.motionZ;
+
+ if (this.sendVelocityUpdates && !(var6 instanceof Packet24MobSpawn)) {
+ par1EntityPlayerMP.playerNetServerHandler.sendPacket(
+ new Packet28EntityVelocity(this.trackedEntity.entityId, this.trackedEntity.motionX,
+ this.trackedEntity.motionY, this.trackedEntity.motionZ));
+ }
+
+ if (this.trackedEntity.ridingEntity != null) {
+ par1EntityPlayerMP.playerNetServerHandler.sendPacket(
+ new Packet39AttachEntity(this.trackedEntity, this.trackedEntity.ridingEntity));
+ }
+
+ if (this.trackedEntity instanceof EntityLiving) {
+ for (int var7 = 0; var7 < 5; ++var7) {
+ ItemStack var8 = ((EntityLiving) this.trackedEntity).getEquipmentInSlot(var7);
+
+ if (var8 != null) {
+ par1EntityPlayerMP.playerNetServerHandler.sendPacket(
+ new Packet5PlayerInventory(this.trackedEntity.entityId, var7, var8));
+ }
+ }
+ }
+
+ if (this.trackedEntity instanceof EntityPlayer) {
+ EntityPlayer var10 = (EntityPlayer) this.trackedEntity;
+
+ if (var10.isPlayerSleeping()) {
+ par1EntityPlayerMP.playerNetServerHandler.sendPacket(new Packet17Sleep(this.trackedEntity,
+ 0, MathHelper.floor_double(this.trackedEntity.posX),
+ MathHelper.floor_double(this.trackedEntity.posY),
+ MathHelper.floor_double(this.trackedEntity.posZ)));
+ }
+ }
+
+ if (this.trackedEntity instanceof EntityLiving) {
+ EntityLiving var11 = (EntityLiving) this.trackedEntity;
+ Iterator var12 = var11.getActivePotionEffects().iterator();
+
+ while (var12.hasNext()) {
+ PotionEffect var9 = (PotionEffect) var12.next();
+ par1EntityPlayerMP.playerNetServerHandler
+ .sendPacket(new Packet41EntityEffect(this.trackedEntity.entityId, var9));
+ }
+ }
+ }
+ } else if (this.trackingPlayers.contains(par1EntityPlayerMP)) {
+ this.trackingPlayers.remove(par1EntityPlayerMP);
+ //System.out.println(this.trackedEntity.getEntityName() + ": updatePlayerEntity");
+ par1EntityPlayerMP.destroyedItemsNetCache.add(Integer.valueOf(this.trackedEntity.entityId));
+ }
+ }
+ }
+
+ private boolean isPlayerWatchingThisChunk(EntityPlayerMP par1EntityPlayerMP) {
+ return par1EntityPlayerMP.getServerForPlayer().getPlayerManager().isPlayerWatchingChunk(par1EntityPlayerMP,
+ this.trackedEntity.chunkCoordX, this.trackedEntity.chunkCoordZ);
+ }
+
+ public void updatePlayerEntities(List par1List) {
+ for (int var2 = 0; var2 < par1List.size(); ++var2) {
+ this.updatePlayerEntity((EntityPlayerMP) par1List.get(var2));
+ }
+ }
+
+ private Packet getSpawnPacket() {
+ if (this.trackedEntity.isDead) {
+ this.trackedEntity.worldObj.getWorldLogAgent().func_98236_b("Fetching addPacket for removed entity");
+ }
+
+ if (this.trackedEntity instanceof EntityItem) {
+ return new Packet23VehicleSpawn(this.trackedEntity, 2, 1);
+ } else if (this.trackedEntity instanceof EntityPlayerMP) {
+ return new Packet20NamedEntitySpawn((EntityPlayer) this.trackedEntity);
+ } else if (this.trackedEntity instanceof EntityMinecart) {
+ EntityMinecart var8 = (EntityMinecart) this.trackedEntity;
+ return new Packet23VehicleSpawn(this.trackedEntity, 10, var8.getMinecartType());
+ } else if (this.trackedEntity instanceof EntityBoat) {
+ return new Packet23VehicleSpawn(this.trackedEntity, 1);
+ } else if (!(this.trackedEntity instanceof IAnimals) && !(this.trackedEntity instanceof EntityDragon)) {
+ if (this.trackedEntity instanceof EntityFishHook) {
+ EntityPlayer var7 = ((EntityFishHook) this.trackedEntity).angler;
+ return new Packet23VehicleSpawn(this.trackedEntity, 90,
+ var7 != null ? var7.entityId : this.trackedEntity.entityId);
+ } else if (this.trackedEntity instanceof EntityArrow) {
+ Entity var6 = ((EntityArrow) this.trackedEntity).shootingEntity;
+ return new Packet23VehicleSpawn(this.trackedEntity, 60,
+ var6 != null ? var6.entityId : this.trackedEntity.entityId);
+ } else if (this.trackedEntity instanceof EntitySnowball) {
+ return new Packet23VehicleSpawn(this.trackedEntity, 61);
+ } else if (this.trackedEntity instanceof EntityPotion) {
+ return new Packet23VehicleSpawn(this.trackedEntity, 73,
+ ((EntityPotion) this.trackedEntity).getPotionDamage());
+ } else if (this.trackedEntity instanceof EntityExpBottle) {
+ return new Packet23VehicleSpawn(this.trackedEntity, 75);
+ } else if (this.trackedEntity instanceof EntityEnderPearl) {
+ return new Packet23VehicleSpawn(this.trackedEntity, 65);
+ } else if (this.trackedEntity instanceof EntityEnderEye) {
+ return new Packet23VehicleSpawn(this.trackedEntity, 72);
+ } else if (this.trackedEntity instanceof EntityFireworkRocket) {
+ return new Packet23VehicleSpawn(this.trackedEntity, 76);
+ } else {
+ Packet23VehicleSpawn var2;
+
+ if (this.trackedEntity instanceof EntityFireball) {
+ EntityFireball var5 = (EntityFireball) this.trackedEntity;
+ var2 = null;
+ byte var3 = 63;
+
+ if (this.trackedEntity instanceof EntitySmallFireball) {
+ var3 = 64;
+ } else if (this.trackedEntity instanceof EntityWitherSkull) {
+ var3 = 66;
+ }
+
+ if (var5.shootingEntity != null) {
+ var2 = new Packet23VehicleSpawn(this.trackedEntity, var3,
+ ((EntityFireball) this.trackedEntity).shootingEntity.entityId);
+ } else {
+ var2 = new Packet23VehicleSpawn(this.trackedEntity, var3, 0);
+ }
+
+ var2.speedX = (int) (var5.accelerationX * 8000.0D);
+ var2.speedY = (int) (var5.accelerationY * 8000.0D);
+ var2.speedZ = (int) (var5.accelerationZ * 8000.0D);
+ return var2;
+ } else if (this.trackedEntity instanceof EntityEgg) {
+ return new Packet23VehicleSpawn(this.trackedEntity, 62);
+ } else if (this.trackedEntity instanceof EntityTNTPrimed) {
+ return new Packet23VehicleSpawn(this.trackedEntity, 50);
+ } else if (this.trackedEntity instanceof EntityEnderCrystal) {
+ return new Packet23VehicleSpawn(this.trackedEntity, 51);
+ } else if (this.trackedEntity instanceof EntityFallingSand) {
+ EntityFallingSand var4 = (EntityFallingSand) this.trackedEntity;
+ return new Packet23VehicleSpawn(this.trackedEntity, 70, var4.blockID | var4.metadata << 16);
+ } else if (this.trackedEntity instanceof EntityPainting) {
+ return new Packet25EntityPainting((EntityPainting) this.trackedEntity);
+ } else if (this.trackedEntity instanceof EntityItemFrame) {
+ EntityItemFrame var1 = (EntityItemFrame) this.trackedEntity;
+ var2 = new Packet23VehicleSpawn(this.trackedEntity, 71, var1.hangingDirection);
+ var2.xPosition = MathHelper.floor_float((float) (var1.xPosition * 32));
+ var2.yPosition = MathHelper.floor_float((float) (var1.yPosition * 32));
+ var2.zPosition = MathHelper.floor_float((float) (var1.zPosition * 32));
+ return var2;
+ } else if (this.trackedEntity instanceof EntityXPOrb) {
+ return new Packet26EntityExpOrb((EntityXPOrb) this.trackedEntity);
+ } else {
+ throw new IllegalArgumentException("Don\'t know how to add " + this.trackedEntity.getClass() + "!");
+ }
+ }
+ } else {
+ this.lastHeadMotion = MathHelper.floor_float(this.trackedEntity.getRotationYawHead() * 256.0F / 360.0F);
+ return new Packet24MobSpawn((EntityLiving) this.trackedEntity);
+ }
+ }
+
+ /**
+ * Remove a tracked player from our list and tell the tracked player to destroy
+ * us from their world.
+ */
+ public void removeTrackedPlayerSymmetric(EntityPlayerMP par1EntityPlayerMP) {
+ removeTrackedPlayerSymmetric(par1EntityPlayerMP, false);
+ }
+ public void removeTrackedPlayerSymmetric(EntityPlayerMP par1EntityPlayerMP, boolean asap) {
+ if (this.trackingPlayers.contains(par1EntityPlayerMP)) {
+ this.trackingPlayers.remove(par1EntityPlayerMP);
+ //System.out.println(this.trackedEntity.getEntityName() + ": removeTrackedPlayerSymmetric");
+ if (asap) {
+ par1EntityPlayerMP.playerNetServerHandler.sendPacket(new Packet29DestroyEntity(Integer.valueOf(this.trackedEntity.entityId)));
+ } else {
+ par1EntityPlayerMP.destroyedItemsNetCache.add(Integer.valueOf(this.trackedEntity.entityId));
+ }
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityVillager.java b/sp-server/src/main/java/net/minecraft/src/EntityVillager.java
new file mode 100644
index 0000000..f86d9a6
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityVillager.java
@@ -0,0 +1,685 @@
+package net.minecraft.src;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class EntityVillager extends EntityAgeable implements INpc, IMerchant {
+ private int randomTickDivider;
+ private boolean isMating;
+ private boolean isPlaying;
+ Village villageObj;
+
+ /** This villager's current customer. */
+ private EntityPlayer buyingPlayer;
+
+ /** Initialises the MerchantRecipeList.java */
+ private MerchantRecipeList buyingList;
+ private int timeUntilReset;
+
+ /** addDefaultEquipmentAndRecipies is called if this is true */
+ private boolean needsInitilization;
+ private int wealth;
+
+ /** Last player to trade with this villager, used for aggressivity. */
+ private String lastBuyingPlayer;
+ private boolean field_82190_bM;
+ private float field_82191_bN;
+
+ /** Selling list of Villagers items. */
+ private static final Map villagersSellingList = new HashMap();
+
+ /** Selling list of Blacksmith items. */
+ private static final Map blacksmithSellingList = new HashMap();
+
+ public EntityVillager(World par1World) {
+ this(par1World, 0);
+ }
+
+ public EntityVillager(World par1World, int par2) {
+ super(par1World);
+ this.randomTickDivider = 0;
+ this.isMating = false;
+ this.isPlaying = false;
+ this.villageObj = null;
+ this.setProfession(par2);
+ this.texture = "/mob/villager/villager.png";
+ this.moveSpeed = 0.5F;
+ this.setSize(0.6F, 1.8F);
+ this.getNavigator().setBreakDoors(true);
+ this.getNavigator().setAvoidsWater(true);
+ this.tasks.addTask(0, new EntityAISwimming(this));
+ this.tasks.addTask(1, new EntityAIAvoidEntity(this, EntityZombie.class, 8.0F, 0.3F, 0.35F));
+ this.tasks.addTask(1, new EntityAITradePlayer(this));
+ this.tasks.addTask(1, new EntityAILookAtTradePlayer(this));
+ this.tasks.addTask(2, new EntityAIMoveIndoors(this));
+ this.tasks.addTask(3, new EntityAIRestrictOpenDoor(this));
+ this.tasks.addTask(4, new EntityAIOpenDoor(this, true));
+ this.tasks.addTask(5, new EntityAIMoveTwardsRestriction(this, 0.3F));
+ this.tasks.addTask(6, new EntityAIVillagerMate(this));
+ this.tasks.addTask(7, new EntityAIFollowGolem(this));
+ this.tasks.addTask(8, new EntityAIPlay(this, 0.32F));
+ this.tasks.addTask(9, new EntityAIWatchClosest2(this, EntityPlayer.class, 3.0F, 1.0F));
+ this.tasks.addTask(9, new EntityAIWatchClosest2(this, EntityVillager.class, 5.0F, 0.02F));
+ this.tasks.addTask(9, new EntityAIWander(this, 0.3F));
+ this.tasks.addTask(10, new EntityAIWatchClosest(this, EntityLiving.class, 8.0F));
+ }
+
+ /**
+ * Returns true if the newer Entity AI code should be run
+ */
+ public boolean isAIEnabled() {
+ return true;
+ }
+
+ /**
+ * main AI tick function, replaces updateEntityActionState
+ */
+ protected void updateAITick() {
+ if (--this.randomTickDivider <= 0) {
+ this.worldObj.villageCollectionObj.addVillagerPosition(MathHelper.floor_double(this.posX),
+ MathHelper.floor_double(this.posY), MathHelper.floor_double(this.posZ));
+ this.randomTickDivider = 70 + this.rand.nextInt(50);
+ this.villageObj = this.worldObj.villageCollectionObj.findNearestVillage(MathHelper.floor_double(this.posX),
+ MathHelper.floor_double(this.posY), MathHelper.floor_double(this.posZ), 32);
+
+ if (this.villageObj == null) {
+ this.detachHome();
+ } else {
+ ChunkCoordinates var1 = this.villageObj.getCenter();
+ this.setHomeArea(var1.posX, var1.posY, var1.posZ,
+ (int) ((float) this.villageObj.getVillageRadius() * 0.6F));
+
+ if (this.field_82190_bM) {
+ this.field_82190_bM = false;
+ this.villageObj.func_82683_b(5);
+ }
+ }
+ }
+
+ if (!this.isTrading() && this.timeUntilReset > 0) {
+ --this.timeUntilReset;
+
+ if (this.timeUntilReset <= 0) {
+ if (this.needsInitilization) {
+ if (this.buyingList.size() > 1) {
+ Iterator var3 = this.buyingList.iterator();
+
+ while (var3.hasNext()) {
+ MerchantRecipe var2 = (MerchantRecipe) var3.next();
+
+ if (var2.func_82784_g()) {
+ var2.func_82783_a(this.rand.nextInt(6) + this.rand.nextInt(6) + 2);
+ }
+ }
+ }
+
+ this.addDefaultEquipmentAndRecipies(1);
+ this.needsInitilization = false;
+
+ if (this.villageObj != null && this.lastBuyingPlayer != null) {
+ this.worldObj.setEntityState(this, (byte) 14);
+ this.villageObj.setReputationForPlayer(this.lastBuyingPlayer, 1);
+ }
+ }
+
+ this.addPotionEffect(new PotionEffect(Potion.regeneration.id, 200, 0));
+ }
+ }
+
+ super.updateAITick();
+ }
+
+ /**
+ * Called when a player interacts with a mob. e.g. gets milk from a cow, gets
+ * into the saddle on a pig.
+ */
+ public boolean interact(EntityPlayer par1EntityPlayer) {
+ ItemStack var2 = par1EntityPlayer.inventory.getCurrentItem();
+ boolean var3 = var2 != null && var2.itemID == Item.monsterPlacer.itemID;
+
+ if (!var3 && this.isEntityAlive() && !this.isTrading() && !this.isChild()) {
+ if (!this.worldObj.isRemote) {
+ this.setCustomer(par1EntityPlayer);
+ par1EntityPlayer.displayGUIMerchant(this, this.func_94057_bL());
+ }
+
+ return true;
+ } else {
+ return super.interact(par1EntityPlayer);
+ }
+ }
+
+ protected void entityInit() {
+ super.entityInit();
+ this.dataWatcher.addObject(16, Integer.valueOf(0));
+ }
+
+ public int getMaxHealth() {
+ return 20;
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ super.writeEntityToNBT(par1NBTTagCompound);
+ par1NBTTagCompound.setInteger("Profession", this.getProfession());
+ par1NBTTagCompound.setInteger("Riches", this.wealth);
+
+ if (this.buyingList != null) {
+ par1NBTTagCompound.setCompoundTag("Offers", this.buyingList.getRecipiesAsTags());
+ }
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ super.readEntityFromNBT(par1NBTTagCompound);
+ this.setProfession(par1NBTTagCompound.getInteger("Profession"));
+ this.wealth = par1NBTTagCompound.getInteger("Riches");
+
+ if (par1NBTTagCompound.hasKey("Offers")) {
+ NBTTagCompound var2 = par1NBTTagCompound.getCompoundTag("Offers");
+ this.buyingList = new MerchantRecipeList(var2);
+ }
+ }
+
+ /**
+ * Determines if an entity can be despawned, used on idle far away entities
+ */
+ protected boolean canDespawn() {
+ return false;
+ }
+
+ /**
+ * Returns the sound this mob makes while it's alive.
+ */
+ protected String getLivingSound() {
+ return "mob.villager.default";
+ }
+
+ /**
+ * Returns the sound this mob makes when it is hurt.
+ */
+ protected String getHurtSound() {
+ return "mob.villager.defaulthurt";
+ }
+
+ /**
+ * Returns the sound this mob makes on death.
+ */
+ protected String getDeathSound() {
+ return "mob.villager.defaultdeath";
+ }
+
+ public void setProfession(int par1) {
+ this.dataWatcher.updateObject(16, Integer.valueOf(par1));
+ }
+
+ public int getProfession() {
+ return this.dataWatcher.getWatchableObjectInt(16);
+ }
+
+ public boolean isMating() {
+ return this.isMating;
+ }
+
+ public void setMating(boolean par1) {
+ this.isMating = par1;
+ }
+
+ public void setPlaying(boolean par1) {
+ this.isPlaying = par1;
+ }
+
+ public boolean isPlaying() {
+ return this.isPlaying;
+ }
+
+ public void setRevengeTarget(EntityLiving par1EntityLiving) {
+ super.setRevengeTarget(par1EntityLiving);
+
+ if (this.villageObj != null && par1EntityLiving != null) {
+ this.villageObj.addOrRenewAgressor(par1EntityLiving);
+
+ if (par1EntityLiving instanceof EntityPlayer) {
+ byte var2 = -1;
+
+ if (this.isChild()) {
+ var2 = -3;
+ }
+
+ this.villageObj.setReputationForPlayer(((EntityPlayer) par1EntityLiving).getCommandSenderName(), var2);
+
+ if (this.isEntityAlive()) {
+ this.worldObj.setEntityState(this, (byte) 13);
+ }
+ }
+ }
+ }
+
+ /**
+ * Called when the mob's health reaches 0.
+ */
+ public void onDeath(DamageSource par1DamageSource) {
+ if (this.villageObj != null) {
+ Entity var2 = par1DamageSource.getEntity();
+
+ if (var2 != null) {
+ if (var2 instanceof EntityPlayer) {
+ this.villageObj.setReputationForPlayer(((EntityPlayer) var2).getCommandSenderName(), -2);
+ } else if (var2 instanceof IMob) {
+ this.villageObj.endMatingSeason();
+ }
+ } else if (var2 == null) {
+ EntityPlayer var3 = this.worldObj.getClosestPlayerToEntity(this, 16.0D);
+
+ if (var3 != null) {
+ this.villageObj.endMatingSeason();
+ }
+ }
+ }
+
+ super.onDeath(par1DamageSource);
+ }
+
+ public void setCustomer(EntityPlayer par1EntityPlayer) {
+ this.buyingPlayer = par1EntityPlayer;
+ }
+
+ public EntityPlayer getCustomer() {
+ return this.buyingPlayer;
+ }
+
+ public boolean isTrading() {
+ return this.buyingPlayer != null;
+ }
+
+ public void useRecipe(MerchantRecipe par1MerchantRecipe) {
+ par1MerchantRecipe.incrementToolUses();
+
+ if (par1MerchantRecipe.hasSameIDsAs((MerchantRecipe) this.buyingList.get(this.buyingList.size() - 1))) {
+ this.timeUntilReset = 40;
+ this.needsInitilization = true;
+
+ if (this.buyingPlayer != null) {
+ this.lastBuyingPlayer = this.buyingPlayer.getCommandSenderName();
+ } else {
+ this.lastBuyingPlayer = null;
+ }
+ }
+
+ if (par1MerchantRecipe.getItemToBuy().itemID == Item.emerald.itemID) {
+ this.wealth += par1MerchantRecipe.getItemToBuy().stackSize;
+ }
+ }
+
+ public MerchantRecipeList getRecipes(EntityPlayer par1EntityPlayer) {
+ if (this.buyingList == null) {
+ this.addDefaultEquipmentAndRecipies(1);
+ }
+
+ return this.buyingList;
+ }
+
+ private float func_82188_j(float par1) {
+ float var2 = par1 + this.field_82191_bN;
+ return var2 > 0.9F ? 0.9F - (var2 - 0.9F) : var2;
+ }
+
+ /**
+ * based on the villagers profession add items, equipment, and recipies adds
+ * par1 random items to the list of things that the villager wants to buy. (at
+ * most 1 of each wanted type is added)
+ */
+ private void addDefaultEquipmentAndRecipies(int par1) {
+ if (this.buyingList != null) {
+ this.field_82191_bN = MathHelper.sqrt_float((float) this.buyingList.size()) * 0.2F;
+ } else {
+ this.field_82191_bN = 0.0F;
+ }
+
+ MerchantRecipeList var2;
+ var2 = new MerchantRecipeList();
+ int var6;
+ label50:
+
+ switch (this.getProfession()) {
+ case 0:
+ addMerchantItem(var2, Item.wheat.itemID, this.rand, this.func_82188_j(0.9F));
+ addMerchantItem(var2, Block.cloth.blockID, this.rand, this.func_82188_j(0.5F));
+ addMerchantItem(var2, Item.chickenRaw.itemID, this.rand, this.func_82188_j(0.5F));
+ addMerchantItem(var2, Item.fishCooked.itemID, this.rand, this.func_82188_j(0.4F));
+ addBlacksmithItem(var2, Item.bread.itemID, this.rand, this.func_82188_j(0.9F));
+ addBlacksmithItem(var2, Item.melon.itemID, this.rand, this.func_82188_j(0.3F));
+ addBlacksmithItem(var2, Item.appleRed.itemID, this.rand, this.func_82188_j(0.3F));
+ addBlacksmithItem(var2, Item.cookie.itemID, this.rand, this.func_82188_j(0.3F));
+ addBlacksmithItem(var2, Item.shears.itemID, this.rand, this.func_82188_j(0.3F));
+ addBlacksmithItem(var2, Item.flintAndSteel.itemID, this.rand, this.func_82188_j(0.3F));
+ addBlacksmithItem(var2, Item.chickenCooked.itemID, this.rand, this.func_82188_j(0.3F));
+ addBlacksmithItem(var2, Item.arrow.itemID, this.rand, this.func_82188_j(0.5F));
+
+ if (this.rand.nextFloat() < this.func_82188_j(0.5F)) {
+ var2.add(new MerchantRecipe(new ItemStack(Block.gravel, 10), new ItemStack(Item.emerald),
+ new ItemStack(Item.flint.itemID, 4 + this.rand.nextInt(2), 0)));
+ }
+
+ break;
+
+ case 1:
+ addMerchantItem(var2, Item.paper.itemID, this.rand, this.func_82188_j(0.8F));
+ addMerchantItem(var2, Item.book.itemID, this.rand, this.func_82188_j(0.8F));
+ addMerchantItem(var2, Item.writtenBook.itemID, this.rand, this.func_82188_j(0.3F));
+ addBlacksmithItem(var2, Block.bookShelf.blockID, this.rand, this.func_82188_j(0.8F));
+ addBlacksmithItem(var2, Block.glass.blockID, this.rand, this.func_82188_j(0.2F));
+ addBlacksmithItem(var2, Item.compass.itemID, this.rand, this.func_82188_j(0.2F));
+ addBlacksmithItem(var2, Item.pocketSundial.itemID, this.rand, this.func_82188_j(0.2F));
+
+ if (this.rand.nextFloat() < this.func_82188_j(0.07F)) {
+ Enchantment var8 = Enchantment.field_92090_c[this.rand.nextInt(Enchantment.field_92090_c.length)];
+ int var10 = MathHelper.getRandomIntegerInRange(this.rand, var8.getMinLevel(), var8.getMaxLevel());
+ ItemStack var11 = Item.enchantedBook.func_92111_a(new EnchantmentData(var8, var10));
+ var6 = 2 + this.rand.nextInt(5 + var10 * 10) + 3 * var10;
+ var2.add(new MerchantRecipe(new ItemStack(Item.book), new ItemStack(Item.emerald, var6), var11));
+ }
+
+ break;
+
+ case 2:
+ addBlacksmithItem(var2, Item.eyeOfEnder.itemID, this.rand, this.func_82188_j(0.3F));
+ addBlacksmithItem(var2, Item.expBottle.itemID, this.rand, this.func_82188_j(0.2F));
+ addBlacksmithItem(var2, Item.redstone.itemID, this.rand, this.func_82188_j(0.4F));
+ addBlacksmithItem(var2, Block.glowStone.blockID, this.rand, this.func_82188_j(0.3F));
+ int[] var3 = new int[] { Item.swordIron.itemID, Item.swordDiamond.itemID, Item.plateIron.itemID,
+ Item.plateDiamond.itemID, Item.axeIron.itemID, Item.axeDiamond.itemID, Item.pickaxeIron.itemID,
+ Item.pickaxeDiamond.itemID };
+ int[] var4 = var3;
+ int var5 = var3.length;
+ var6 = 0;
+
+ while (true) {
+ if (var6 >= var5) {
+ break label50;
+ }
+
+ int var7 = var4[var6];
+
+ if (this.rand.nextFloat() < this.func_82188_j(0.05F)) {
+ var2.add(new MerchantRecipe(new ItemStack(var7, 1, 0),
+ new ItemStack(Item.emerald, 2 + this.rand.nextInt(3), 0),
+ EnchantmentHelper.addRandomEnchantment(this.rand, new ItemStack(var7, 1, 0),
+ 5 + this.rand.nextInt(15))));
+ }
+
+ ++var6;
+ }
+
+ case 3:
+ addMerchantItem(var2, Item.coal.itemID, this.rand, this.func_82188_j(0.7F));
+ addMerchantItem(var2, Item.ingotIron.itemID, this.rand, this.func_82188_j(0.5F));
+ addMerchantItem(var2, Item.ingotGold.itemID, this.rand, this.func_82188_j(0.5F));
+ addMerchantItem(var2, Item.diamond.itemID, this.rand, this.func_82188_j(0.5F));
+ addBlacksmithItem(var2, Item.swordIron.itemID, this.rand, this.func_82188_j(0.5F));
+ addBlacksmithItem(var2, Item.swordDiamond.itemID, this.rand, this.func_82188_j(0.5F));
+ addBlacksmithItem(var2, Item.axeIron.itemID, this.rand, this.func_82188_j(0.3F));
+ addBlacksmithItem(var2, Item.axeDiamond.itemID, this.rand, this.func_82188_j(0.3F));
+ addBlacksmithItem(var2, Item.pickaxeIron.itemID, this.rand, this.func_82188_j(0.5F));
+ addBlacksmithItem(var2, Item.pickaxeDiamond.itemID, this.rand, this.func_82188_j(0.5F));
+ addBlacksmithItem(var2, Item.shovelIron.itemID, this.rand, this.func_82188_j(0.2F));
+ addBlacksmithItem(var2, Item.shovelDiamond.itemID, this.rand, this.func_82188_j(0.2F));
+ addBlacksmithItem(var2, Item.hoeIron.itemID, this.rand, this.func_82188_j(0.2F));
+ addBlacksmithItem(var2, Item.hoeDiamond.itemID, this.rand, this.func_82188_j(0.2F));
+ addBlacksmithItem(var2, Item.bootsIron.itemID, this.rand, this.func_82188_j(0.2F));
+ addBlacksmithItem(var2, Item.bootsDiamond.itemID, this.rand, this.func_82188_j(0.2F));
+ addBlacksmithItem(var2, Item.helmetIron.itemID, this.rand, this.func_82188_j(0.2F));
+ addBlacksmithItem(var2, Item.helmetDiamond.itemID, this.rand, this.func_82188_j(0.2F));
+ addBlacksmithItem(var2, Item.plateIron.itemID, this.rand, this.func_82188_j(0.2F));
+ addBlacksmithItem(var2, Item.plateDiamond.itemID, this.rand, this.func_82188_j(0.2F));
+ addBlacksmithItem(var2, Item.legsIron.itemID, this.rand, this.func_82188_j(0.2F));
+ addBlacksmithItem(var2, Item.legsDiamond.itemID, this.rand, this.func_82188_j(0.2F));
+ addBlacksmithItem(var2, Item.bootsChain.itemID, this.rand, this.func_82188_j(0.1F));
+ addBlacksmithItem(var2, Item.helmetChain.itemID, this.rand, this.func_82188_j(0.1F));
+ addBlacksmithItem(var2, Item.plateChain.itemID, this.rand, this.func_82188_j(0.1F));
+ addBlacksmithItem(var2, Item.legsChain.itemID, this.rand, this.func_82188_j(0.1F));
+ break;
+
+ case 4:
+ addMerchantItem(var2, Item.coal.itemID, this.rand, this.func_82188_j(0.7F));
+ addMerchantItem(var2, Item.porkRaw.itemID, this.rand, this.func_82188_j(0.5F));
+ addMerchantItem(var2, Item.beefRaw.itemID, this.rand, this.func_82188_j(0.5F));
+ addBlacksmithItem(var2, Item.saddle.itemID, this.rand, this.func_82188_j(0.1F));
+ addBlacksmithItem(var2, Item.plateLeather.itemID, this.rand, this.func_82188_j(0.3F));
+ addBlacksmithItem(var2, Item.bootsLeather.itemID, this.rand, this.func_82188_j(0.3F));
+ addBlacksmithItem(var2, Item.helmetLeather.itemID, this.rand, this.func_82188_j(0.3F));
+ addBlacksmithItem(var2, Item.legsLeather.itemID, this.rand, this.func_82188_j(0.3F));
+ addBlacksmithItem(var2, Item.porkCooked.itemID, this.rand, this.func_82188_j(0.3F));
+ addBlacksmithItem(var2, Item.beefCooked.itemID, this.rand, this.func_82188_j(0.3F));
+ }
+
+ if (var2.isEmpty()) {
+ addMerchantItem(var2, Item.ingotGold.itemID, this.rand, 1.0F);
+ }
+
+ Collections.shuffle(var2);
+
+ if (this.buyingList == null) {
+ this.buyingList = new MerchantRecipeList();
+ }
+
+ for (int var9 = 0; var9 < par1 && var9 < var2.size(); ++var9) {
+ this.buyingList.addToListWithCheck((MerchantRecipe) var2.get(var9));
+ }
+ }
+
+ /**
+ * each recipie takes a random stack from villagerStockList and offers it for 1
+ * emerald
+ */
+ private static void addMerchantItem(MerchantRecipeList par0MerchantRecipeList, int par1, EaglercraftRandom par2Random,
+ float par3) {
+ if (par2Random.nextFloat() < par3) {
+ par0MerchantRecipeList.add(new MerchantRecipe(getRandomSizedStack(par1, par2Random), Item.emerald));
+ }
+ }
+
+ private static ItemStack getRandomSizedStack(int par0, EaglercraftRandom par1Random) {
+ return new ItemStack(par0, getRandomCountForItem(par0, par1Random), 0);
+ }
+
+ /**
+ * default to 1, and villagerStockList contains a min/max amount for each index
+ */
+ private static int getRandomCountForItem(int par0, EaglercraftRandom par1Random) {
+ Tuple var2 = (Tuple) villagersSellingList.get(Integer.valueOf(par0));
+ return var2 == null ? 1
+ : (((Integer) var2.getFirst()).intValue() >= ((Integer) var2.getSecond()).intValue()
+ ? ((Integer) var2.getFirst()).intValue()
+ : ((Integer) var2.getFirst()).intValue() + par1Random.nextInt(
+ ((Integer) var2.getSecond()).intValue() - ((Integer) var2.getFirst()).intValue()));
+ }
+
+ private static void addBlacksmithItem(MerchantRecipeList par0MerchantRecipeList, int par1, EaglercraftRandom par2Random,
+ float par3) {
+ if (par2Random.nextFloat() < par3) {
+ int var4 = getRandomCountForBlacksmithItem(par1, par2Random);
+ ItemStack var5;
+ ItemStack var6;
+
+ if (var4 < 0) {
+ var5 = new ItemStack(Item.emerald.itemID, 1, 0);
+ var6 = new ItemStack(par1, -var4, 0);
+ } else {
+ var5 = new ItemStack(Item.emerald.itemID, var4, 0);
+ var6 = new ItemStack(par1, 1, 0);
+ }
+
+ par0MerchantRecipeList.add(new MerchantRecipe(var5, var6));
+ }
+ }
+
+ private static int getRandomCountForBlacksmithItem(int par0, EaglercraftRandom par1Random) {
+ Tuple var2 = (Tuple) blacksmithSellingList.get(Integer.valueOf(par0));
+ return var2 == null ? 1
+ : (((Integer) var2.getFirst()).intValue() >= ((Integer) var2.getSecond()).intValue()
+ ? ((Integer) var2.getFirst()).intValue()
+ : ((Integer) var2.getFirst()).intValue() + par1Random.nextInt(
+ ((Integer) var2.getSecond()).intValue() - ((Integer) var2.getFirst()).intValue()));
+ }
+
+ /**
+ * Initialize this creature.
+ */
+ public void initCreature() {
+ this.setProfession(this.worldObj.rand.nextInt(5));
+ }
+
+ public void func_82187_q() {
+ this.field_82190_bM = true;
+ }
+
+ public EntityVillager func_90012_b(EntityAgeable par1EntityAgeable) {
+ EntityVillager var2 = new EntityVillager(this.worldObj);
+ var2.initCreature();
+ return var2;
+ }
+
+ public EntityAgeable createChild(EntityAgeable par1EntityAgeable) {
+ return this.func_90012_b(par1EntityAgeable);
+ }
+
+ static {
+ villagersSellingList.put(Integer.valueOf(Item.coal.itemID),
+ new Tuple(Integer.valueOf(16), Integer.valueOf(24)));
+ villagersSellingList.put(Integer.valueOf(Item.ingotIron.itemID),
+ new Tuple(Integer.valueOf(8), Integer.valueOf(10)));
+ villagersSellingList.put(Integer.valueOf(Item.ingotGold.itemID),
+ new Tuple(Integer.valueOf(8), Integer.valueOf(10)));
+ villagersSellingList.put(Integer.valueOf(Item.diamond.itemID),
+ new Tuple(Integer.valueOf(4), Integer.valueOf(6)));
+ villagersSellingList.put(Integer.valueOf(Item.paper.itemID),
+ new Tuple(Integer.valueOf(24), Integer.valueOf(36)));
+ villagersSellingList.put(Integer.valueOf(Item.book.itemID),
+ new Tuple(Integer.valueOf(11), Integer.valueOf(13)));
+ villagersSellingList.put(Integer.valueOf(Item.writtenBook.itemID),
+ new Tuple(Integer.valueOf(1), Integer.valueOf(1)));
+ villagersSellingList.put(Integer.valueOf(Item.enderPearl.itemID),
+ new Tuple(Integer.valueOf(3), Integer.valueOf(4)));
+ villagersSellingList.put(Integer.valueOf(Item.eyeOfEnder.itemID),
+ new Tuple(Integer.valueOf(2), Integer.valueOf(3)));
+ villagersSellingList.put(Integer.valueOf(Item.porkRaw.itemID),
+ new Tuple(Integer.valueOf(14), Integer.valueOf(18)));
+ villagersSellingList.put(Integer.valueOf(Item.beefRaw.itemID),
+ new Tuple(Integer.valueOf(14), Integer.valueOf(18)));
+ villagersSellingList.put(Integer.valueOf(Item.chickenRaw.itemID),
+ new Tuple(Integer.valueOf(14), Integer.valueOf(18)));
+ villagersSellingList.put(Integer.valueOf(Item.fishCooked.itemID),
+ new Tuple(Integer.valueOf(9), Integer.valueOf(13)));
+ villagersSellingList.put(Integer.valueOf(Item.seeds.itemID),
+ new Tuple(Integer.valueOf(34), Integer.valueOf(48)));
+ villagersSellingList.put(Integer.valueOf(Item.melonSeeds.itemID),
+ new Tuple(Integer.valueOf(30), Integer.valueOf(38)));
+ villagersSellingList.put(Integer.valueOf(Item.pumpkinSeeds.itemID),
+ new Tuple(Integer.valueOf(30), Integer.valueOf(38)));
+ villagersSellingList.put(Integer.valueOf(Item.wheat.itemID),
+ new Tuple(Integer.valueOf(18), Integer.valueOf(22)));
+ villagersSellingList.put(Integer.valueOf(Block.cloth.blockID),
+ new Tuple(Integer.valueOf(14), Integer.valueOf(22)));
+ villagersSellingList.put(Integer.valueOf(Item.rottenFlesh.itemID),
+ new Tuple(Integer.valueOf(36), Integer.valueOf(64)));
+ blacksmithSellingList.put(Integer.valueOf(Item.flintAndSteel.itemID),
+ new Tuple(Integer.valueOf(3), Integer.valueOf(4)));
+ blacksmithSellingList.put(Integer.valueOf(Item.shears.itemID),
+ new Tuple(Integer.valueOf(3), Integer.valueOf(4)));
+ blacksmithSellingList.put(Integer.valueOf(Item.swordIron.itemID),
+ new Tuple(Integer.valueOf(7), Integer.valueOf(11)));
+ blacksmithSellingList.put(Integer.valueOf(Item.swordDiamond.itemID),
+ new Tuple(Integer.valueOf(12), Integer.valueOf(14)));
+ blacksmithSellingList.put(Integer.valueOf(Item.axeIron.itemID),
+ new Tuple(Integer.valueOf(6), Integer.valueOf(8)));
+ blacksmithSellingList.put(Integer.valueOf(Item.axeDiamond.itemID),
+ new Tuple(Integer.valueOf(9), Integer.valueOf(12)));
+ blacksmithSellingList.put(Integer.valueOf(Item.pickaxeIron.itemID),
+ new Tuple(Integer.valueOf(7), Integer.valueOf(9)));
+ blacksmithSellingList.put(Integer.valueOf(Item.pickaxeDiamond.itemID),
+ new Tuple(Integer.valueOf(10), Integer.valueOf(12)));
+ blacksmithSellingList.put(Integer.valueOf(Item.shovelIron.itemID),
+ new Tuple(Integer.valueOf(4), Integer.valueOf(6)));
+ blacksmithSellingList.put(Integer.valueOf(Item.shovelDiamond.itemID),
+ new Tuple(Integer.valueOf(7), Integer.valueOf(8)));
+ blacksmithSellingList.put(Integer.valueOf(Item.hoeIron.itemID),
+ new Tuple(Integer.valueOf(4), Integer.valueOf(6)));
+ blacksmithSellingList.put(Integer.valueOf(Item.hoeDiamond.itemID),
+ new Tuple(Integer.valueOf(7), Integer.valueOf(8)));
+ blacksmithSellingList.put(Integer.valueOf(Item.bootsIron.itemID),
+ new Tuple(Integer.valueOf(4), Integer.valueOf(6)));
+ blacksmithSellingList.put(Integer.valueOf(Item.bootsDiamond.itemID),
+ new Tuple(Integer.valueOf(7), Integer.valueOf(8)));
+ blacksmithSellingList.put(Integer.valueOf(Item.helmetIron.itemID),
+ new Tuple(Integer.valueOf(4), Integer.valueOf(6)));
+ blacksmithSellingList.put(Integer.valueOf(Item.helmetDiamond.itemID),
+ new Tuple(Integer.valueOf(7), Integer.valueOf(8)));
+ blacksmithSellingList.put(Integer.valueOf(Item.plateIron.itemID),
+ new Tuple(Integer.valueOf(10), Integer.valueOf(14)));
+ blacksmithSellingList.put(Integer.valueOf(Item.plateDiamond.itemID),
+ new Tuple(Integer.valueOf(16), Integer.valueOf(19)));
+ blacksmithSellingList.put(Integer.valueOf(Item.legsIron.itemID),
+ new Tuple(Integer.valueOf(8), Integer.valueOf(10)));
+ blacksmithSellingList.put(Integer.valueOf(Item.legsDiamond.itemID),
+ new Tuple(Integer.valueOf(11), Integer.valueOf(14)));
+ blacksmithSellingList.put(Integer.valueOf(Item.bootsChain.itemID),
+ new Tuple(Integer.valueOf(5), Integer.valueOf(7)));
+ blacksmithSellingList.put(Integer.valueOf(Item.helmetChain.itemID),
+ new Tuple(Integer.valueOf(5), Integer.valueOf(7)));
+ blacksmithSellingList.put(Integer.valueOf(Item.plateChain.itemID),
+ new Tuple(Integer.valueOf(11), Integer.valueOf(15)));
+ blacksmithSellingList.put(Integer.valueOf(Item.legsChain.itemID),
+ new Tuple(Integer.valueOf(9), Integer.valueOf(11)));
+ blacksmithSellingList.put(Integer.valueOf(Item.bread.itemID),
+ new Tuple(Integer.valueOf(-4), Integer.valueOf(-2)));
+ blacksmithSellingList.put(Integer.valueOf(Item.melon.itemID),
+ new Tuple(Integer.valueOf(-8), Integer.valueOf(-4)));
+ blacksmithSellingList.put(Integer.valueOf(Item.appleRed.itemID),
+ new Tuple(Integer.valueOf(-8), Integer.valueOf(-4)));
+ blacksmithSellingList.put(Integer.valueOf(Item.cookie.itemID),
+ new Tuple(Integer.valueOf(-10), Integer.valueOf(-7)));
+ blacksmithSellingList.put(Integer.valueOf(Block.glass.blockID),
+ new Tuple(Integer.valueOf(-5), Integer.valueOf(-3)));
+ blacksmithSellingList.put(Integer.valueOf(Block.bookShelf.blockID),
+ new Tuple(Integer.valueOf(3), Integer.valueOf(4)));
+ blacksmithSellingList.put(Integer.valueOf(Item.plateLeather.itemID),
+ new Tuple(Integer.valueOf(4), Integer.valueOf(5)));
+ blacksmithSellingList.put(Integer.valueOf(Item.bootsLeather.itemID),
+ new Tuple(Integer.valueOf(2), Integer.valueOf(4)));
+ blacksmithSellingList.put(Integer.valueOf(Item.helmetLeather.itemID),
+ new Tuple(Integer.valueOf(2), Integer.valueOf(4)));
+ blacksmithSellingList.put(Integer.valueOf(Item.legsLeather.itemID),
+ new Tuple(Integer.valueOf(2), Integer.valueOf(4)));
+ blacksmithSellingList.put(Integer.valueOf(Item.saddle.itemID),
+ new Tuple(Integer.valueOf(6), Integer.valueOf(8)));
+ blacksmithSellingList.put(Integer.valueOf(Item.expBottle.itemID),
+ new Tuple(Integer.valueOf(-4), Integer.valueOf(-1)));
+ blacksmithSellingList.put(Integer.valueOf(Item.redstone.itemID),
+ new Tuple(Integer.valueOf(-4), Integer.valueOf(-1)));
+ blacksmithSellingList.put(Integer.valueOf(Item.compass.itemID),
+ new Tuple(Integer.valueOf(10), Integer.valueOf(12)));
+ blacksmithSellingList.put(Integer.valueOf(Item.pocketSundial.itemID),
+ new Tuple(Integer.valueOf(10), Integer.valueOf(12)));
+ blacksmithSellingList.put(Integer.valueOf(Block.glowStone.blockID),
+ new Tuple(Integer.valueOf(-3), Integer.valueOf(-1)));
+ blacksmithSellingList.put(Integer.valueOf(Item.porkCooked.itemID),
+ new Tuple(Integer.valueOf(-7), Integer.valueOf(-5)));
+ blacksmithSellingList.put(Integer.valueOf(Item.beefCooked.itemID),
+ new Tuple(Integer.valueOf(-7), Integer.valueOf(-5)));
+ blacksmithSellingList.put(Integer.valueOf(Item.chickenCooked.itemID),
+ new Tuple(Integer.valueOf(-8), Integer.valueOf(-6)));
+ blacksmithSellingList.put(Integer.valueOf(Item.eyeOfEnder.itemID),
+ new Tuple(Integer.valueOf(7), Integer.valueOf(11)));
+ blacksmithSellingList.put(Integer.valueOf(Item.arrow.itemID),
+ new Tuple(Integer.valueOf(-12), Integer.valueOf(-8)));
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityWaterMob.java b/sp-server/src/main/java/net/minecraft/src/EntityWaterMob.java
new file mode 100644
index 0000000..165df54
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityWaterMob.java
@@ -0,0 +1,60 @@
+package net.minecraft.src;
+
+public abstract class EntityWaterMob extends EntityCreature implements IAnimals {
+ public EntityWaterMob(World par1World) {
+ super(par1World);
+ }
+
+ public boolean canBreatheUnderwater() {
+ return true;
+ }
+
+ /**
+ * Checks if the entity's current position is a valid location to spawn this
+ * entity.
+ */
+ public boolean getCanSpawnHere() {
+ return this.worldObj.checkNoEntityCollision(this.boundingBox);
+ }
+
+ /**
+ * Get number of ticks, at least during which the living entity will be silent.
+ */
+ public int getTalkInterval() {
+ return 120;
+ }
+
+ /**
+ * Determines if an entity can be despawned, used on idle far away entities
+ */
+ protected boolean canDespawn() {
+ return true;
+ }
+
+ /**
+ * Get the experience points the entity currently has.
+ */
+ protected int getExperiencePoints(EntityPlayer par1EntityPlayer) {
+ return 1 + this.worldObj.rand.nextInt(3);
+ }
+
+ /**
+ * Gets called every tick from main Entity class
+ */
+ public void onEntityUpdate() {
+ int var1 = this.getAir();
+ super.onEntityUpdate();
+
+ if (this.isEntityAlive() && !this.isInsideOfMaterial(Material.water)) {
+ --var1;
+ this.setAir(var1);
+
+ if (this.getAir() == -20) {
+ this.setAir(0);
+ this.attackEntityFrom(DamageSource.drown, 2);
+ }
+ } else {
+ this.setAir(300);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityWeatherEffect.java b/sp-server/src/main/java/net/minecraft/src/EntityWeatherEffect.java
new file mode 100644
index 0000000..1d81075
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityWeatherEffect.java
@@ -0,0 +1,7 @@
+package net.minecraft.src;
+
+public abstract class EntityWeatherEffect extends Entity {
+ public EntityWeatherEffect(World par1World) {
+ super(par1World);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityWitch.java b/sp-server/src/main/java/net/minecraft/src/EntityWitch.java
new file mode 100644
index 0000000..b6debc7
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityWitch.java
@@ -0,0 +1,219 @@
+package net.minecraft.src;
+
+import java.util.Iterator;
+import java.util.List;
+
+public class EntityWitch extends EntityMob implements IRangedAttackMob {
+ /** List of items a witch should drop on death. */
+ private static final int[] witchDrops = new int[] { Item.lightStoneDust.itemID, Item.sugar.itemID,
+ Item.redstone.itemID, Item.spiderEye.itemID, Item.glassBottle.itemID, Item.gunpowder.itemID,
+ Item.stick.itemID, Item.stick.itemID };
+
+ /**
+ * Timer used as interval for a witch's attack, decremented every tick if
+ * aggressive and when reaches zero the witch will throw a potion at the target
+ * entity.
+ */
+ private int witchAttackTimer = 0;
+
+ public EntityWitch(World par1World) {
+ super(par1World);
+ this.texture = "/mob/villager/witch.png";
+ this.moveSpeed = 0.25F;
+ this.tasks.addTask(1, new EntityAISwimming(this));
+ this.tasks.addTask(2, new EntityAIArrowAttack(this, this.moveSpeed, 60, 10.0F));
+ this.tasks.addTask(2, new EntityAIWander(this, this.moveSpeed));
+ this.tasks.addTask(3, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F));
+ this.tasks.addTask(3, new EntityAILookIdle(this));
+ this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, false));
+ this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, EntityPlayer.class, 16.0F, 0, true));
+ }
+
+ protected void entityInit() {
+ super.entityInit();
+ this.getDataWatcher().addObject(21, Byte.valueOf((byte) 0));
+ }
+
+ /**
+ * Returns the sound this mob makes while it's alive.
+ */
+ protected String getLivingSound() {
+ return "mob.witch.idle";
+ }
+
+ /**
+ * Returns the sound this mob makes when it is hurt.
+ */
+ protected String getHurtSound() {
+ return "mob.witch.hurt";
+ }
+
+ /**
+ * Returns the sound this mob makes on death.
+ */
+ protected String getDeathSound() {
+ return "mob.witch.death";
+ }
+
+ /**
+ * Set whether this witch is aggressive at an entity.
+ */
+ public void setAggressive(boolean par1) {
+ this.getDataWatcher().updateObject(21, Byte.valueOf((byte) (par1 ? 1 : 0)));
+ }
+
+ /**
+ * Return whether this witch is aggressive at an entity.
+ */
+ public boolean getAggressive() {
+ return this.getDataWatcher().getWatchableObjectByte(21) == 1;
+ }
+
+ public int getMaxHealth() {
+ return 26;
+ }
+
+ /**
+ * Returns true if the newer Entity AI code should be run
+ */
+ public boolean isAIEnabled() {
+ return true;
+ }
+
+ /**
+ * Called frequently so the entity can update its state every tick as required.
+ * For example, zombies and skeletons use this to react to sunlight and start to
+ * burn.
+ */
+ public void onLivingUpdate() {
+ if (!this.worldObj.isRemote) {
+ if (this.getAggressive()) {
+ if (this.witchAttackTimer-- <= 0) {
+ this.setAggressive(false);
+ ItemStack var1 = this.getHeldItem();
+ this.setCurrentItemOrArmor(0, (ItemStack) null);
+
+ if (var1 != null && var1.itemID == Item.potion.itemID) {
+ List var2 = Item.potion.getEffects(var1);
+
+ if (var2 != null) {
+ Iterator var3 = var2.iterator();
+
+ while (var3.hasNext()) {
+ PotionEffect var4 = (PotionEffect) var3.next();
+ this.addPotionEffect(new PotionEffect(var4));
+ }
+ }
+ }
+ }
+ } else {
+ short var5 = -1;
+
+ if (this.rand.nextFloat() < 0.15F && this.isBurning() && !this.isPotionActive(Potion.fireResistance)) {
+ var5 = 16307;
+ } else if (this.rand.nextFloat() < 0.05F && this.health < this.getMaxHealth()) {
+ var5 = 16341;
+ } else if (this.rand.nextFloat() < 0.25F && this.getAttackTarget() != null
+ && !this.isPotionActive(Potion.moveSpeed)
+ && this.getAttackTarget().getDistanceSqToEntity(this) > 121.0D) {
+ var5 = 16274;
+ } else if (this.rand.nextFloat() < 0.25F && this.getAttackTarget() != null
+ && !this.isPotionActive(Potion.moveSpeed)
+ && this.getAttackTarget().getDistanceSqToEntity(this) > 121.0D) {
+ var5 = 16274;
+ }
+
+ if (var5 > -1) {
+ this.setCurrentItemOrArmor(0, new ItemStack(Item.potion, 1, var5));
+ this.witchAttackTimer = this.getHeldItem().getMaxItemUseDuration();
+ this.setAggressive(true);
+ }
+ }
+
+ if (this.rand.nextFloat() < 7.5E-4F) {
+ this.worldObj.setEntityState(this, (byte) 15);
+ }
+ }
+
+ super.onLivingUpdate();
+ }
+
+ /**
+ * Reduces damage, depending on potions
+ */
+ protected int applyPotionDamageCalculations(DamageSource par1DamageSource, int par2) {
+ par2 = super.applyPotionDamageCalculations(par1DamageSource, par2);
+
+ if (par1DamageSource.getEntity() == this) {
+ par2 = 0;
+ }
+
+ if (par1DamageSource.isMagicDamage()) {
+ par2 = (int) ((double) par2 * 0.15D);
+ }
+
+ return par2;
+ }
+
+ /**
+ * This method returns a value to be applied directly to entity speed, this
+ * factor is less than 1 when a slowdown potion effect is applied, more than 1
+ * when a haste potion effect is applied and 2 for fleeing entities.
+ */
+ public float getSpeedModifier() {
+ float var1 = super.getSpeedModifier();
+
+ if (this.getAggressive()) {
+ var1 *= 0.75F;
+ }
+
+ return var1;
+ }
+
+ /**
+ * Drop 0-2 items of this living's type
+ */
+ protected void dropFewItems(boolean par1, int par2) {
+ int var3 = this.rand.nextInt(3) + 1;
+
+ for (int var4 = 0; var4 < var3; ++var4) {
+ int var5 = this.rand.nextInt(3);
+ int var6 = witchDrops[this.rand.nextInt(witchDrops.length)];
+
+ if (par2 > 0) {
+ var5 += this.rand.nextInt(par2 + 1);
+ }
+
+ for (int var7 = 0; var7 < var5; ++var7) {
+ this.dropItem(var6, 1);
+ }
+ }
+ }
+
+ /**
+ * Attack the specified entity using a ranged attack.
+ */
+ public void attackEntityWithRangedAttack(EntityLiving par1EntityLiving, float par2) {
+ if (!this.getAggressive()) {
+ EntityPotion var3 = new EntityPotion(this.worldObj, this, 32732);
+ var3.rotationPitch -= -20.0F;
+ double var4 = par1EntityLiving.posX + par1EntityLiving.motionX - this.posX;
+ double var6 = par1EntityLiving.posY + (double) par1EntityLiving.getEyeHeight() - 1.100000023841858D
+ - this.posY;
+ double var8 = par1EntityLiving.posZ + par1EntityLiving.motionZ - this.posZ;
+ float var10 = MathHelper.sqrt_double(var4 * var4 + var8 * var8);
+
+ if (var10 >= 8.0F && !par1EntityLiving.isPotionActive(Potion.moveSlowdown)) {
+ var3.setPotionDamage(32698);
+ } else if (par1EntityLiving.getHealth() >= 8 && !par1EntityLiving.isPotionActive(Potion.poison)) {
+ var3.setPotionDamage(32660);
+ } else if (var10 <= 3.0F && !par1EntityLiving.isPotionActive(Potion.weakness)
+ && this.rand.nextFloat() < 0.25F) {
+ var3.setPotionDamage(32696);
+ }
+
+ var3.setThrowableHeading(var4, var6 + (double) (var10 * 0.2F), var8, 0.75F, 8.0F);
+ this.worldObj.spawnEntityInWorld(var3);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityWither.java b/sp-server/src/main/java/net/minecraft/src/EntityWither.java
new file mode 100644
index 0000000..a9ab794
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityWither.java
@@ -0,0 +1,539 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+public class EntityWither extends EntityMob implements IRangedAttackMob {
+ private float[] field_82220_d = new float[2];
+ private float[] field_82221_e = new float[2];
+ private float[] field_82217_f = new float[2];
+ private float[] field_82218_g = new float[2];
+ private int[] field_82223_h = new int[2];
+ private int[] field_82224_i = new int[2];
+ private int field_82222_j;
+
+ /** Selector used to determine the entities a wither boss should attack. */
+ private static final IEntitySelector attackEntitySelector = new EntityWitherAttackFilter();
+
+ public EntityWither(World par1World) {
+ super(par1World);
+ this.setEntityHealth(this.getMaxHealth());
+ this.texture = "/mob/wither.png";
+ this.setSize(0.9F, 4.0F);
+ this.isImmuneToFire = true;
+ this.moveSpeed = 0.6F;
+ this.getNavigator().setCanSwim(true);
+ this.tasks.addTask(0, new EntityAISwimming(this));
+ this.tasks.addTask(2, new EntityAIArrowAttack(this, this.moveSpeed, 40, 20.0F));
+ this.tasks.addTask(5, new EntityAIWander(this, this.moveSpeed));
+ this.tasks.addTask(6, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F));
+ this.tasks.addTask(7, new EntityAILookIdle(this));
+ this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, false));
+ this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, EntityLiving.class, 30.0F, 0, false,
+ false, attackEntitySelector));
+ this.experienceValue = 50;
+ }
+
+ protected void entityInit() {
+ super.entityInit();
+ this.dataWatcher.addObject(16, Integer.valueOf(100));
+ this.dataWatcher.addObject(17, Integer.valueOf(0));
+ this.dataWatcher.addObject(18, Integer.valueOf(0));
+ this.dataWatcher.addObject(19, Integer.valueOf(0));
+ this.dataWatcher.addObject(20, Integer.valueOf(0));
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ super.writeEntityToNBT(par1NBTTagCompound);
+ par1NBTTagCompound.setInteger("Invul", this.func_82212_n());
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ super.readEntityFromNBT(par1NBTTagCompound);
+ this.func_82215_s(par1NBTTagCompound.getInteger("Invul"));
+ this.dataWatcher.updateObject(16, Integer.valueOf(this.health));
+ }
+
+ /**
+ * Returns the sound this mob makes while it's alive.
+ */
+ protected String getLivingSound() {
+ return "mob.wither.idle";
+ }
+
+ /**
+ * Returns the sound this mob makes when it is hurt.
+ */
+ protected String getHurtSound() {
+ return "mob.wither.hurt";
+ }
+
+ /**
+ * Returns the sound this mob makes on death.
+ */
+ protected String getDeathSound() {
+ return "mob.wither.death";
+ }
+
+ /**
+ * Called frequently so the entity can update its state every tick as required.
+ * For example, zombies and skeletons use this to react to sunlight and start to
+ * burn.
+ */
+ public void onLivingUpdate() {
+ if (!this.worldObj.isRemote) {
+ this.dataWatcher.updateObject(16, Integer.valueOf(this.health));
+ }
+
+ this.motionY *= 0.6000000238418579D;
+ double var4;
+ double var6;
+ double var8;
+
+ if (!this.worldObj.isRemote && this.getWatchedTargetId(0) > 0) {
+ Entity var1 = this.worldObj.getEntityByID(this.getWatchedTargetId(0));
+
+ if (var1 != null) {
+ if (this.posY < var1.posY || !this.isArmored() && this.posY < var1.posY + 5.0D) {
+ if (this.motionY < 0.0D) {
+ this.motionY = 0.0D;
+ }
+
+ this.motionY += (0.5D - this.motionY) * 0.6000000238418579D;
+ }
+
+ double var2 = var1.posX - this.posX;
+ var4 = var1.posZ - this.posZ;
+ var6 = var2 * var2 + var4 * var4;
+
+ if (var6 > 9.0D) {
+ var8 = (double) MathHelper.sqrt_double(var6);
+ this.motionX += (var2 / var8 * 0.5D - this.motionX) * 0.6000000238418579D;
+ this.motionZ += (var4 / var8 * 0.5D - this.motionZ) * 0.6000000238418579D;
+ }
+ }
+ }
+
+ if (this.motionX * this.motionX + this.motionZ * this.motionZ > 0.05000000074505806D) {
+ this.rotationYaw = (float) Math.atan2(this.motionZ, this.motionX) * (180F / (float) Math.PI) - 90.0F;
+ }
+
+ super.onLivingUpdate();
+ int var20;
+
+ for (var20 = 0; var20 < 2; ++var20) {
+ this.field_82218_g[var20] = this.field_82221_e[var20];
+ this.field_82217_f[var20] = this.field_82220_d[var20];
+ }
+
+ int var21;
+
+ for (var20 = 0; var20 < 2; ++var20) {
+ var21 = this.getWatchedTargetId(var20 + 1);
+ Entity var3 = null;
+
+ if (var21 > 0) {
+ var3 = this.worldObj.getEntityByID(var21);
+ }
+
+ if (var3 != null) {
+ var4 = this.func_82214_u(var20 + 1);
+ var6 = this.func_82208_v(var20 + 1);
+ var8 = this.func_82213_w(var20 + 1);
+ double var10 = var3.posX - var4;
+ double var12 = var3.posY + (double) var3.getEyeHeight() - var6;
+ double var14 = var3.posZ - var8;
+ double var16 = (double) MathHelper.sqrt_double(var10 * var10 + var14 * var14);
+ float var18 = (float) (Math.atan2(var14, var10) * 180.0D / Math.PI) - 90.0F;
+ float var19 = (float) (-(Math.atan2(var12, var16) * 180.0D / Math.PI));
+ this.field_82220_d[var20] = this.func_82204_b(this.field_82220_d[var20], var19, 40.0F);
+ this.field_82221_e[var20] = this.func_82204_b(this.field_82221_e[var20], var18, 10.0F);
+ } else {
+ this.field_82221_e[var20] = this.func_82204_b(this.field_82221_e[var20], this.renderYawOffset, 10.0F);
+ }
+ }
+
+ boolean var22 = this.isArmored();
+
+ for (var21 = 0; var21 < 3; ++var21) {
+ double var23 = this.func_82214_u(var21);
+ double var5 = this.func_82208_v(var21);
+ double var7 = this.func_82213_w(var21);
+ this.worldObj.spawnParticle("smoke", var23 + this.rand.nextGaussian() * 0.30000001192092896D,
+ var5 + this.rand.nextGaussian() * 0.30000001192092896D,
+ var7 + this.rand.nextGaussian() * 0.30000001192092896D, 0.0D, 0.0D, 0.0D);
+
+ if (var22 && this.worldObj.rand.nextInt(4) == 0) {
+ this.worldObj.spawnParticle("mobSpell", var23 + this.rand.nextGaussian() * 0.30000001192092896D,
+ var5 + this.rand.nextGaussian() * 0.30000001192092896D,
+ var7 + this.rand.nextGaussian() * 0.30000001192092896D, 0.699999988079071D, 0.699999988079071D,
+ 0.5D);
+ }
+ }
+
+ if (this.func_82212_n() > 0) {
+ for (var21 = 0; var21 < 3; ++var21) {
+ this.worldObj.spawnParticle("mobSpell", this.posX + this.rand.nextGaussian() * 1.0D,
+ this.posY + (double) (this.rand.nextFloat() * 3.3F),
+ this.posZ + this.rand.nextGaussian() * 1.0D, 0.699999988079071D, 0.699999988079071D,
+ 0.8999999761581421D);
+ }
+ }
+ }
+
+ protected void updateAITasks() {
+ int var1;
+
+ if (this.func_82212_n() > 0) {
+ var1 = this.func_82212_n() - 1;
+
+ if (var1 <= 0) {
+ this.worldObj.newExplosion(this, this.posX, this.posY + (double) this.getEyeHeight(), this.posZ, 7.0F,
+ false, this.worldObj.getGameRules().getGameRuleBooleanValue("mobGriefing"));
+ this.worldObj.func_82739_e(1013, (int) this.posX, (int) this.posY, (int) this.posZ, 0);
+ }
+
+ this.func_82215_s(var1);
+
+ if (this.ticksExisted % 10 == 0) {
+ this.heal(10);
+ }
+ } else {
+ super.updateAITasks();
+ int var12;
+
+ for (var1 = 1; var1 < 3; ++var1) {
+ if (this.ticksExisted >= this.field_82223_h[var1 - 1]) {
+ this.field_82223_h[var1 - 1] = this.ticksExisted + 10 + this.rand.nextInt(10);
+
+ if (this.worldObj.difficultySetting >= 2) {
+ int var10001 = var1 - 1;
+ int var10003 = this.field_82224_i[var1 - 1];
+ this.field_82224_i[var10001] = this.field_82224_i[var1 - 1] + 1;
+
+ if (var10003 > 15) {
+ float var2 = 10.0F;
+ float var3 = 5.0F;
+ double var4 = MathHelper.getRandomDoubleInRange(this.rand, this.posX - (double) var2,
+ this.posX + (double) var2);
+ double var6 = MathHelper.getRandomDoubleInRange(this.rand, this.posY - (double) var3,
+ this.posY + (double) var3);
+ double var8 = MathHelper.getRandomDoubleInRange(this.rand, this.posZ - (double) var2,
+ this.posZ + (double) var2);
+ this.func_82209_a(var1 + 1, var4, var6, var8, true);
+ this.field_82224_i[var1 - 1] = 0;
+ }
+ }
+
+ var12 = this.getWatchedTargetId(var1);
+
+ if (var12 > 0) {
+ Entity var14 = this.worldObj.getEntityByID(var12);
+
+ if (var14 != null && var14.isEntityAlive() && this.getDistanceSqToEntity(var14) <= 900.0D
+ && this.canEntityBeSeen(var14)) {
+ this.func_82216_a(var1 + 1, (EntityLiving) var14);
+ this.field_82223_h[var1 - 1] = this.ticksExisted + 40 + this.rand.nextInt(20);
+ this.field_82224_i[var1 - 1] = 0;
+ } else {
+ this.func_82211_c(var1, 0);
+ }
+ } else {
+ List var13 = this.worldObj.selectEntitiesWithinAABB(EntityLiving.class,
+ this.boundingBox.expand(20.0D, 8.0D, 20.0D), attackEntitySelector);
+
+ for (int var16 = 0; var16 < 10 && !var13.isEmpty(); ++var16) {
+ EntityLiving var5 = (EntityLiving) var13.get(this.rand.nextInt(var13.size()));
+
+ if (var5 != this && var5.isEntityAlive() && this.canEntityBeSeen(var5)) {
+ if (var5 instanceof EntityPlayer) {
+ if (!((EntityPlayer) var5).capabilities.disableDamage) {
+ this.func_82211_c(var1, var5.entityId);
+ }
+ } else {
+ this.func_82211_c(var1, var5.entityId);
+ }
+
+ break;
+ }
+
+ var13.remove(var5);
+ }
+ }
+ }
+ }
+
+ if (this.getAttackTarget() != null) {
+ this.func_82211_c(0, this.getAttackTarget().entityId);
+ } else {
+ this.func_82211_c(0, 0);
+ }
+
+ if (this.field_82222_j > 0) {
+ --this.field_82222_j;
+
+ if (this.field_82222_j == 0 && this.worldObj.getGameRules().getGameRuleBooleanValue("mobGriefing")) {
+ var1 = MathHelper.floor_double(this.posY);
+ var12 = MathHelper.floor_double(this.posX);
+ int var15 = MathHelper.floor_double(this.posZ);
+ boolean var17 = false;
+
+ for (int var18 = -1; var18 <= 1; ++var18) {
+ for (int var19 = -1; var19 <= 1; ++var19) {
+ for (int var7 = 0; var7 <= 3; ++var7) {
+ int var20 = var12 + var18;
+ int var9 = var1 + var7;
+ int var10 = var15 + var19;
+ int var11 = this.worldObj.getBlockId(var20, var9, var10);
+
+ if (var11 > 0 && var11 != Block.bedrock.blockID && var11 != Block.endPortal.blockID
+ && var11 != Block.endPortalFrame.blockID) {
+ var17 = this.worldObj.destroyBlock(var20, var9, var10, true) || var17;
+ }
+ }
+ }
+ }
+
+ if (var17) {
+ this.worldObj.playAuxSFXAtEntity((EntityPlayer) null, 1012, (int) this.posX, (int) this.posY,
+ (int) this.posZ, 0);
+ }
+ }
+ }
+
+ if (this.ticksExisted % 20 == 0) {
+ this.heal(1);
+ }
+ }
+ }
+
+ public void func_82206_m() {
+ this.func_82215_s(220);
+ this.setEntityHealth(this.getMaxHealth() / 3);
+ }
+
+ /**
+ * Sets the Entity inside a web block.
+ */
+ public void setInWeb() {
+ }
+
+ /**
+ * Returns the current armor value as determined by a call to
+ * InventoryPlayer.getTotalArmorValue
+ */
+ public int getTotalArmorValue() {
+ return 4;
+ }
+
+ private double func_82214_u(int par1) {
+ if (par1 <= 0) {
+ return this.posX;
+ } else {
+ float var2 = (this.renderYawOffset + (float) (180 * (par1 - 1))) / 180.0F * (float) Math.PI;
+ float var3 = MathHelper.cos(var2);
+ return this.posX + (double) var3 * 1.3D;
+ }
+ }
+
+ private double func_82208_v(int par1) {
+ return par1 <= 0 ? this.posY + 3.0D : this.posY + 2.2D;
+ }
+
+ private double func_82213_w(int par1) {
+ if (par1 <= 0) {
+ return this.posZ;
+ } else {
+ float var2 = (this.renderYawOffset + (float) (180 * (par1 - 1))) / 180.0F * (float) Math.PI;
+ float var3 = MathHelper.sin(var2);
+ return this.posZ + (double) var3 * 1.3D;
+ }
+ }
+
+ private float func_82204_b(float par1, float par2, float par3) {
+ float var4 = MathHelper.wrapAngleTo180_float(par2 - par1);
+
+ if (var4 > par3) {
+ var4 = par3;
+ }
+
+ if (var4 < -par3) {
+ var4 = -par3;
+ }
+
+ return par1 + var4;
+ }
+
+ private void func_82216_a(int par1, EntityLiving par2EntityLiving) {
+ this.func_82209_a(par1, par2EntityLiving.posX,
+ par2EntityLiving.posY + (double) par2EntityLiving.getEyeHeight() * 0.5D, par2EntityLiving.posZ,
+ par1 == 0 && this.rand.nextFloat() < 0.001F);
+ }
+
+ private void func_82209_a(int par1, double par2, double par4, double par6, boolean par8) {
+ this.worldObj.playAuxSFXAtEntity((EntityPlayer) null, 1014, (int) this.posX, (int) this.posY, (int) this.posZ,
+ 0);
+ double var9 = this.func_82214_u(par1);
+ double var11 = this.func_82208_v(par1);
+ double var13 = this.func_82213_w(par1);
+ double var15 = par2 - var9;
+ double var17 = par4 - var11;
+ double var19 = par6 - var13;
+ EntityWitherSkull var21 = new EntityWitherSkull(this.worldObj, this, var15, var17, var19);
+
+ if (par8) {
+ var21.setInvulnerable(true);
+ }
+
+ var21.posY = var11;
+ var21.posX = var9;
+ var21.posZ = var13;
+ this.worldObj.spawnEntityInWorld(var21);
+ }
+
+ /**
+ * Attack the specified entity using a ranged attack.
+ */
+ public void attackEntityWithRangedAttack(EntityLiving par1EntityLiving, float par2) {
+ this.func_82216_a(0, par1EntityLiving);
+ }
+
+ /**
+ * Called when the entity is attacked.
+ */
+ public boolean attackEntityFrom(DamageSource par1DamageSource, int par2) {
+ if (this.isEntityInvulnerable()) {
+ return false;
+ } else if (par1DamageSource == DamageSource.drown) {
+ return false;
+ } else if (this.func_82212_n() > 0) {
+ return false;
+ } else {
+ Entity var3;
+
+ if (this.isArmored()) {
+ var3 = par1DamageSource.getSourceOfDamage();
+
+ if (var3 instanceof EntityArrow) {
+ return false;
+ }
+ }
+
+ var3 = par1DamageSource.getEntity();
+
+ if (var3 != null && !(var3 instanceof EntityPlayer) && var3 instanceof EntityLiving
+ && ((EntityLiving) var3).getCreatureAttribute() == this.getCreatureAttribute()) {
+ return false;
+ } else {
+ if (this.field_82222_j <= 0) {
+ this.field_82222_j = 20;
+ }
+
+ for (int var4 = 0; var4 < this.field_82224_i.length; ++var4) {
+ this.field_82224_i[var4] += 3;
+ }
+
+ return super.attackEntityFrom(par1DamageSource, par2);
+ }
+ }
+ }
+
+ /**
+ * Drop 0-2 items of this living's type
+ */
+ protected void dropFewItems(boolean par1, int par2) {
+ this.dropItem(Item.netherStar.itemID, 1);
+ }
+
+ /**
+ * Makes the entity despawn if requirements are reached
+ */
+ protected void despawnEntity() {
+ this.entityAge = 0;
+ }
+
+ /**
+ * Returns true if other Entities should be prevented from moving through this
+ * Entity.
+ */
+ public boolean canBeCollidedWith() {
+ return !this.isDead;
+ }
+
+ /**
+ * Returns the health points of the dragon.
+ */
+ public int getBossHealth() {
+ return this.dataWatcher.getWatchableObjectInt(16);
+ }
+
+ /**
+ * Called when the mob is falling. Calculates and applies fall damage.
+ */
+ protected void fall(float par1) {
+ }
+
+ /**
+ * adds a PotionEffect to the entity
+ */
+ public void addPotionEffect(PotionEffect par1PotionEffect) {
+ }
+
+ /**
+ * Returns true if the newer Entity AI code should be run
+ */
+ protected boolean isAIEnabled() {
+ return true;
+ }
+
+ public int getMaxHealth() {
+ return 300;
+ }
+
+ public int func_82212_n() {
+ return this.dataWatcher.getWatchableObjectInt(20);
+ }
+
+ public void func_82215_s(int par1) {
+ this.dataWatcher.updateObject(20, Integer.valueOf(par1));
+ }
+
+ /**
+ * Returns the target entity ID if present, or -1 if not @param par1 The target
+ * offset, should be from 0-2
+ */
+ public int getWatchedTargetId(int par1) {
+ return this.dataWatcher.getWatchableObjectInt(17 + par1);
+ }
+
+ public void func_82211_c(int par1, int par2) {
+ this.dataWatcher.updateObject(17 + par1, Integer.valueOf(par2));
+ }
+
+ /**
+ * Returns whether the wither is armored with its boss armor or not by checking
+ * whether its health is below half of its maximum.
+ */
+ public boolean isArmored() {
+ return this.getBossHealth() <= this.getMaxHealth() / 2;
+ }
+
+ /**
+ * Get this Entity's EnumCreatureAttribute
+ */
+ public EnumCreatureAttribute getCreatureAttribute() {
+ return EnumCreatureAttribute.UNDEAD;
+ }
+
+ /**
+ * Called when a player mounts an entity. e.g. mounts a pig, mounts a boat.
+ */
+ public void mountEntity(Entity par1Entity) {
+ this.ridingEntity = null;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityWitherAttackFilter.java b/sp-server/src/main/java/net/minecraft/src/EntityWitherAttackFilter.java
new file mode 100644
index 0000000..c972dcf
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityWitherAttackFilter.java
@@ -0,0 +1,11 @@
+package net.minecraft.src;
+
+final class EntityWitherAttackFilter implements IEntitySelector {
+ /**
+ * Return whether the specified entity is applicable to this filter.
+ */
+ public boolean isEntityApplicable(Entity par1Entity) {
+ return par1Entity instanceof EntityLiving
+ && ((EntityLiving) par1Entity).getCreatureAttribute() != EnumCreatureAttribute.UNDEAD;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityWitherSkull.java b/sp-server/src/main/java/net/minecraft/src/EntityWitherSkull.java
new file mode 100644
index 0000000..29bad5e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityWitherSkull.java
@@ -0,0 +1,113 @@
+package net.minecraft.src;
+
+public class EntityWitherSkull extends EntityFireball {
+ public EntityWitherSkull(World par1World) {
+ super(par1World);
+ this.setSize(0.3125F, 0.3125F);
+ }
+
+ public EntityWitherSkull(World par1World, EntityLiving par2EntityLiving, double par3, double par5, double par7) {
+ super(par1World, par2EntityLiving, par3, par5, par7);
+ this.setSize(0.3125F, 0.3125F);
+ }
+
+ /**
+ * Return the motion factor for this projectile. The factor is multiplied by the
+ * original motion.
+ */
+ protected float getMotionFactor() {
+ return this.isInvulnerable() ? 0.73F : super.getMotionFactor();
+ }
+
+ /**
+ * Returns true if the entity is on fire. Used by render to add the fire effect
+ * on rendering.
+ */
+ public boolean isBurning() {
+ return false;
+ }
+
+ public float func_82146_a(Explosion par1Explosion, World par2World, int par3, int par4, int par5, Block par6Block) {
+ float var7 = super.func_82146_a(par1Explosion, par2World, par3, par4, par5, par6Block);
+
+ if (this.isInvulnerable() && par6Block != Block.bedrock && par6Block != Block.endPortal
+ && par6Block != Block.endPortalFrame) {
+ var7 = Math.min(0.8F, var7);
+ }
+
+ return var7;
+ }
+
+ /**
+ * Called when this EntityFireball hits a block or entity.
+ */
+ protected void onImpact(MovingObjectPosition par1MovingObjectPosition) {
+ if (!this.worldObj.isRemote) {
+ if (par1MovingObjectPosition.entityHit != null) {
+ if (this.shootingEntity != null) {
+ if (par1MovingObjectPosition.entityHit
+ .attackEntityFrom(DamageSource.causeMobDamage(this.shootingEntity), 8)
+ && !par1MovingObjectPosition.entityHit.isEntityAlive()) {
+ this.shootingEntity.heal(5);
+ }
+ } else {
+ par1MovingObjectPosition.entityHit.attackEntityFrom(DamageSource.magic, 5);
+ }
+
+ if (par1MovingObjectPosition.entityHit instanceof EntityLiving) {
+ byte var2 = 0;
+
+ if (this.worldObj.difficultySetting > 1) {
+ if (this.worldObj.difficultySetting == 2) {
+ var2 = 10;
+ } else if (this.worldObj.difficultySetting == 3) {
+ var2 = 40;
+ }
+ }
+
+ if (var2 > 0) {
+ ((EntityLiving) par1MovingObjectPosition.entityHit)
+ .addPotionEffect(new PotionEffect(Potion.wither.id, 20 * var2, 1));
+ }
+ }
+ }
+
+ this.worldObj.newExplosion(this, this.posX, this.posY, this.posZ, 1.0F, false,
+ this.worldObj.getGameRules().getGameRuleBooleanValue("mobGriefing"));
+ this.setDead();
+ }
+ }
+
+ /**
+ * Returns true if other Entities should be prevented from moving through this
+ * Entity.
+ */
+ public boolean canBeCollidedWith() {
+ return false;
+ }
+
+ /**
+ * Called when the entity is attacked.
+ */
+ public boolean attackEntityFrom(DamageSource par1DamageSource, int par2) {
+ return false;
+ }
+
+ protected void entityInit() {
+ this.dataWatcher.addObject(10, Byte.valueOf((byte) 0));
+ }
+
+ /**
+ * Return whether this skull comes from an invulnerable (aura) wither boss.
+ */
+ public boolean isInvulnerable() {
+ return this.dataWatcher.getWatchableObjectByte(10) == 1;
+ }
+
+ /**
+ * Set whether this skull comes from an invulnerable (aura) wither boss.
+ */
+ public void setInvulnerable(boolean par1) {
+ this.dataWatcher.updateObject(10, Byte.valueOf((byte) (par1 ? 1 : 0)));
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityWolf.java b/sp-server/src/main/java/net/minecraft/src/EntityWolf.java
new file mode 100644
index 0000000..02094e2
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityWolf.java
@@ -0,0 +1,434 @@
+package net.minecraft.src;
+
+public class EntityWolf extends EntityTameable {
+ private float field_70926_e;
+ private float field_70924_f;
+
+ /** true is the wolf is wet else false */
+ private boolean isShaking;
+ private boolean field_70928_h;
+
+ /**
+ * This time increases while wolf is shaking and emitting water particles.
+ */
+ private float timeWolfIsShaking;
+ private float prevTimeWolfIsShaking;
+
+ public EntityWolf(World par1World) {
+ super(par1World);
+ this.texture = "/mob/wolf.png";
+ this.setSize(0.6F, 0.8F);
+ this.moveSpeed = 0.3F;
+ this.getNavigator().setAvoidsWater(true);
+ this.tasks.addTask(1, new EntityAISwimming(this));
+ this.tasks.addTask(2, this.aiSit);
+ this.tasks.addTask(3, new EntityAILeapAtTarget(this, 0.4F));
+ this.tasks.addTask(4, new EntityAIAttackOnCollide(this, this.moveSpeed, true));
+ this.tasks.addTask(5, new EntityAIFollowOwner(this, this.moveSpeed, 10.0F, 2.0F));
+ this.tasks.addTask(6, new EntityAIMate(this, this.moveSpeed));
+ this.tasks.addTask(7, new EntityAIWander(this, this.moveSpeed));
+ this.tasks.addTask(8, new EntityAIBeg(this, 8.0F));
+ this.tasks.addTask(9, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F));
+ this.tasks.addTask(9, new EntityAILookIdle(this));
+ this.targetTasks.addTask(1, new EntityAIOwnerHurtByTarget(this));
+ this.targetTasks.addTask(2, new EntityAIOwnerHurtTarget(this));
+ this.targetTasks.addTask(3, new EntityAIHurtByTarget(this, true));
+ this.targetTasks.addTask(4, new EntityAITargetNonTamed(this, EntitySheep.class, 16.0F, 200, false));
+ }
+
+ /**
+ * Returns true if the newer Entity AI code should be run
+ */
+ public boolean isAIEnabled() {
+ return true;
+ }
+
+ /**
+ * Sets the active target the Task system uses for tracking
+ */
+ public void setAttackTarget(EntityLiving par1EntityLiving) {
+ super.setAttackTarget(par1EntityLiving);
+
+ if (par1EntityLiving instanceof EntityPlayer) {
+ this.setAngry(true);
+ }
+ }
+
+ /**
+ * main AI tick function, replaces updateEntityActionState
+ */
+ protected void updateAITick() {
+ this.dataWatcher.updateObject(18, Integer.valueOf(this.getHealth()));
+ }
+
+ public int getMaxHealth() {
+ return this.isTamed() ? 20 : 8;
+ }
+
+ protected void entityInit() {
+ super.entityInit();
+ this.dataWatcher.addObject(18, Integer.valueOf(this.getHealth()));
+ this.dataWatcher.addObject(19, Byte.valueOf((byte) 0));
+ this.dataWatcher.addObject(20, Byte.valueOf((byte) BlockCloth.getBlockFromDye(1)));
+ }
+
+ /**
+ * Plays step sound at given x, y, z for the entity
+ */
+ protected void playStepSound(int par1, int par2, int par3, int par4) {
+ this.playSound("mob.wolf.step", 0.15F, 1.0F);
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ super.writeEntityToNBT(par1NBTTagCompound);
+ par1NBTTagCompound.setBoolean("Angry", this.isAngry());
+ par1NBTTagCompound.setByte("CollarColor", (byte) this.getCollarColor());
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ super.readEntityFromNBT(par1NBTTagCompound);
+ this.setAngry(par1NBTTagCompound.getBoolean("Angry"));
+
+ if (par1NBTTagCompound.hasKey("CollarColor")) {
+ this.setCollarColor(par1NBTTagCompound.getByte("CollarColor"));
+ }
+ }
+
+ /**
+ * Determines if an entity can be despawned, used on idle far away entities
+ */
+ protected boolean canDespawn() {
+ return this.isAngry() && !this.isTamed();
+ }
+
+ /**
+ * Returns the sound this mob makes while it's alive.
+ */
+ protected String getLivingSound() {
+ return this
+ .isAngry()
+ ? "mob.wolf.growl"
+ : (this.rand.nextInt(3) == 0
+ ? (this.isTamed() && this.dataWatcher.getWatchableObjectInt(18) < 10 ? "mob.wolf.whine"
+ : "mob.wolf.panting")
+ : "mob.wolf.bark");
+ }
+
+ /**
+ * Returns the sound this mob makes when it is hurt.
+ */
+ protected String getHurtSound() {
+ return "mob.wolf.hurt";
+ }
+
+ /**
+ * Returns the sound this mob makes on death.
+ */
+ protected String getDeathSound() {
+ return "mob.wolf.death";
+ }
+
+ /**
+ * Returns the volume for the sounds this mob makes.
+ */
+ protected float getSoundVolume() {
+ return 0.4F;
+ }
+
+ /**
+ * Returns the item ID for the item the mob drops on death.
+ */
+ protected int getDropItemId() {
+ return -1;
+ }
+
+ /**
+ * Called frequently so the entity can update its state every tick as required.
+ * For example, zombies and skeletons use this to react to sunlight and start to
+ * burn.
+ */
+ public void onLivingUpdate() {
+ super.onLivingUpdate();
+
+ if (!this.worldObj.isRemote && this.isShaking && !this.field_70928_h && !this.hasPath() && this.onGround) {
+ this.field_70928_h = true;
+ this.timeWolfIsShaking = 0.0F;
+ this.prevTimeWolfIsShaking = 0.0F;
+ this.worldObj.setEntityState(this, (byte) 8);
+ }
+ }
+
+ /**
+ * Called to update the entity's position/logic.
+ */
+ public void onUpdate() {
+ super.onUpdate();
+ this.field_70924_f = this.field_70926_e;
+
+ if (this.func_70922_bv()) {
+ this.field_70926_e += (1.0F - this.field_70926_e) * 0.4F;
+ } else {
+ this.field_70926_e += (0.0F - this.field_70926_e) * 0.4F;
+ }
+
+ if (this.func_70922_bv()) {
+ this.numTicksToChaseTarget = 10;
+ }
+
+ if (this.isWet()) {
+ this.isShaking = true;
+ this.field_70928_h = false;
+ this.timeWolfIsShaking = 0.0F;
+ this.prevTimeWolfIsShaking = 0.0F;
+ } else if ((this.isShaking || this.field_70928_h) && this.field_70928_h) {
+ if (this.timeWolfIsShaking == 0.0F) {
+ this.playSound("mob.wolf.shake", this.getSoundVolume(),
+ (this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F + 1.0F);
+ }
+
+ this.prevTimeWolfIsShaking = this.timeWolfIsShaking;
+ this.timeWolfIsShaking += 0.05F;
+
+ if (this.prevTimeWolfIsShaking >= 2.0F) {
+ this.isShaking = false;
+ this.field_70928_h = false;
+ this.prevTimeWolfIsShaking = 0.0F;
+ this.timeWolfIsShaking = 0.0F;
+ }
+
+ if (this.timeWolfIsShaking > 0.4F) {
+ float var1 = (float) this.boundingBox.minY;
+ int var2 = (int) (MathHelper.sin((this.timeWolfIsShaking - 0.4F) * (float) Math.PI) * 7.0F);
+
+ for (int var3 = 0; var3 < var2; ++var3) {
+ float var4 = (this.rand.nextFloat() * 2.0F - 1.0F) * this.width * 0.5F;
+ float var5 = (this.rand.nextFloat() * 2.0F - 1.0F) * this.width * 0.5F;
+ this.worldObj.spawnParticle("splash", this.posX + (double) var4, (double) (var1 + 0.8F),
+ this.posZ + (double) var5, this.motionX, this.motionY, this.motionZ);
+ }
+ }
+ }
+ }
+
+ public float getEyeHeight() {
+ return this.height * 0.8F;
+ }
+
+ /**
+ * The speed it takes to move the entityliving's rotationPitch through the
+ * faceEntity method. This is only currently use in wolves.
+ */
+ public int getVerticalFaceSpeed() {
+ return this.isSitting() ? 20 : super.getVerticalFaceSpeed();
+ }
+
+ /**
+ * Called when the entity is attacked.
+ */
+ public boolean attackEntityFrom(DamageSource par1DamageSource, int par2) {
+ if (this.isEntityInvulnerable()) {
+ return false;
+ } else {
+ Entity var3 = par1DamageSource.getEntity();
+ this.aiSit.setSitting(false);
+
+ if (var3 != null && !(var3 instanceof EntityPlayer) && !(var3 instanceof EntityArrow)) {
+ par2 = (par2 + 1) / 2;
+ }
+
+ return super.attackEntityFrom(par1DamageSource, par2);
+ }
+ }
+
+ public boolean attackEntityAsMob(Entity par1Entity) {
+ int var2 = this.isTamed() ? 4 : 2;
+ return par1Entity.attackEntityFrom(DamageSource.causeMobDamage(this), var2);
+ }
+
+ /**
+ * Called when a player interacts with a mob. e.g. gets milk from a cow, gets
+ * into the saddle on a pig.
+ */
+ public boolean interact(EntityPlayer par1EntityPlayer) {
+ ItemStack var2 = par1EntityPlayer.inventory.getCurrentItem();
+
+ if (this.isTamed()) {
+ if (var2 != null) {
+ if (Item.itemsList[var2.itemID] instanceof ItemFood) {
+ ItemFood var3 = (ItemFood) Item.itemsList[var2.itemID];
+
+ if (var3.isWolfsFavoriteMeat() && this.dataWatcher.getWatchableObjectInt(18) < 20) {
+ if (!par1EntityPlayer.capabilities.isCreativeMode) {
+ --var2.stackSize;
+ }
+
+ this.heal(var3.getHealAmount());
+
+ if (var2.stackSize <= 0) {
+ par1EntityPlayer.inventory.setInventorySlotContents(par1EntityPlayer.inventory.currentItem,
+ (ItemStack) null);
+ }
+
+ return true;
+ }
+ } else if (var2.itemID == Item.dyePowder.itemID) {
+ int var4 = BlockCloth.getBlockFromDye(var2.getItemDamage());
+
+ if (var4 != this.getCollarColor()) {
+ this.setCollarColor(var4);
+
+ if (!par1EntityPlayer.capabilities.isCreativeMode && --var2.stackSize <= 0) {
+ par1EntityPlayer.inventory.setInventorySlotContents(par1EntityPlayer.inventory.currentItem,
+ (ItemStack) null);
+ }
+
+ return true;
+ }
+ }
+ }
+
+ if (par1EntityPlayer.username.equalsIgnoreCase(this.getOwnerName()) && !this.worldObj.isRemote
+ && !this.isBreedingItem(var2)) {
+ this.aiSit.setSitting(!this.isSitting());
+ this.isJumping = false;
+ this.setPathToEntity((PathEntity) null);
+ }
+ } else if (var2 != null && var2.itemID == Item.bone.itemID && !this.isAngry()) {
+ if (!par1EntityPlayer.capabilities.isCreativeMode) {
+ --var2.stackSize;
+ }
+
+ if (var2.stackSize <= 0) {
+ par1EntityPlayer.inventory.setInventorySlotContents(par1EntityPlayer.inventory.currentItem,
+ (ItemStack) null);
+ }
+
+ if (!this.worldObj.isRemote) {
+ if (this.rand.nextInt(3) == 0) {
+ this.setTamed(true);
+ this.setPathToEntity((PathEntity) null);
+ this.setAttackTarget((EntityLiving) null);
+ this.aiSit.setSitting(true);
+ this.setEntityHealth(20);
+ this.setOwner(par1EntityPlayer.username);
+ this.playTameEffect(true);
+ this.worldObj.setEntityState(this, (byte) 7);
+ } else {
+ this.playTameEffect(false);
+ this.worldObj.setEntityState(this, (byte) 6);
+ }
+ }
+
+ return true;
+ }
+
+ return super.interact(par1EntityPlayer);
+ }
+
+ /**
+ * Checks if the parameter is an item which this animal can be fed to breed it
+ * (wheat, carrots or seeds depending on the animal type)
+ */
+ public boolean isBreedingItem(ItemStack par1ItemStack) {
+ return par1ItemStack == null ? false
+ : (!(Item.itemsList[par1ItemStack.itemID] instanceof ItemFood) ? false
+ : ((ItemFood) Item.itemsList[par1ItemStack.itemID]).isWolfsFavoriteMeat());
+ }
+
+ /**
+ * Will return how many at most can spawn in a chunk at once.
+ */
+ public int getMaxSpawnedInChunk() {
+ return 8;
+ }
+
+ /**
+ * Determines whether this wolf is angry or not.
+ */
+ public boolean isAngry() {
+ return (this.dataWatcher.getWatchableObjectByte(16) & 2) != 0;
+ }
+
+ /**
+ * Sets whether this wolf is angry or not.
+ */
+ public void setAngry(boolean par1) {
+ byte var2 = this.dataWatcher.getWatchableObjectByte(16);
+
+ if (par1) {
+ this.dataWatcher.updateObject(16, Byte.valueOf((byte) (var2 | 2)));
+ } else {
+ this.dataWatcher.updateObject(16, Byte.valueOf((byte) (var2 & -3)));
+ }
+ }
+
+ /**
+ * Return this wolf's collar color.
+ */
+ public int getCollarColor() {
+ return this.dataWatcher.getWatchableObjectByte(20) & 15;
+ }
+
+ /**
+ * Set this wolf's collar color.
+ */
+ public void setCollarColor(int par1) {
+ this.dataWatcher.updateObject(20, Byte.valueOf((byte) (par1 & 15)));
+ }
+
+ /**
+ * This function is used when two same-species animals in 'love mode' breed to
+ * generate the new baby animal.
+ */
+ public EntityWolf spawnBabyAnimal(EntityAgeable par1EntityAgeable) {
+ EntityWolf var2 = new EntityWolf(this.worldObj);
+ String var3 = this.getOwnerName();
+
+ if (var3 != null && var3.trim().length() > 0) {
+ var2.setOwner(var3);
+ var2.setTamed(true);
+ }
+
+ return var2;
+ }
+
+ public void func_70918_i(boolean par1) {
+ byte var2 = this.dataWatcher.getWatchableObjectByte(19);
+
+ if (par1) {
+ this.dataWatcher.updateObject(19, Byte.valueOf((byte) 1));
+ } else {
+ this.dataWatcher.updateObject(19, Byte.valueOf((byte) 0));
+ }
+ }
+
+ /**
+ * Returns true if the mob is currently able to mate with the specified mob.
+ */
+ public boolean canMateWith(EntityAnimal par1EntityAnimal) {
+ if (par1EntityAnimal == this) {
+ return false;
+ } else if (!this.isTamed()) {
+ return false;
+ } else if (!(par1EntityAnimal instanceof EntityWolf)) {
+ return false;
+ } else {
+ EntityWolf var2 = (EntityWolf) par1EntityAnimal;
+ return !var2.isTamed() ? false : (var2.isSitting() ? false : this.isInLove() && var2.isInLove());
+ }
+ }
+
+ public boolean func_70922_bv() {
+ return this.dataWatcher.getWatchableObjectByte(19) == 1;
+ }
+
+ public EntityAgeable createChild(EntityAgeable par1EntityAgeable) {
+ return this.spawnBabyAnimal(par1EntityAgeable);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityXPOrb.java b/sp-server/src/main/java/net/minecraft/src/EntityXPOrb.java
new file mode 100644
index 0000000..3469682
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityXPOrb.java
@@ -0,0 +1,230 @@
+package net.minecraft.src;
+
+public class EntityXPOrb extends Entity {
+ /**
+ * A constantly increasing value that RenderXPOrb uses to control the colour
+ * shifting (Green / yellow)
+ */
+ public int xpColor;
+
+ /** The age of the XP orb in ticks. */
+ public int xpOrbAge = 0;
+ public int field_70532_c;
+
+ /** The health of this XP orb. */
+ private int xpOrbHealth = 5;
+
+ /** This is how much XP this orb has. */
+ private int xpValue;
+
+ /** The closest EntityPlayer to this orb. */
+ private EntityPlayer closestPlayer;
+
+ /** Threshold color for tracking players */
+ private int xpTargetColor;
+
+ public EntityXPOrb(World par1World, double par2, double par4, double par6, int par8) {
+ super(par1World);
+ this.setSize(0.5F, 0.5F);
+ this.yOffset = this.height / 2.0F;
+ this.setPosition(par2, par4, par6);
+ this.rotationYaw = (float) (Math.random() * 360.0D);
+ this.motionX = (double) ((float) (Math.random() * 0.20000000298023224D - 0.10000000149011612D) * 2.0F);
+ this.motionY = (double) ((float) (Math.random() * 0.2D) * 2.0F);
+ this.motionZ = (double) ((float) (Math.random() * 0.20000000298023224D - 0.10000000149011612D) * 2.0F);
+ this.xpValue = par8;
+ }
+
+ /**
+ * returns if this entity triggers Block.onEntityWalking on the blocks they walk
+ * on. used for spiders and wolves to prevent them from trampling crops
+ */
+ protected boolean canTriggerWalking() {
+ return false;
+ }
+
+ public EntityXPOrb(World par1World) {
+ super(par1World);
+ this.setSize(0.25F, 0.25F);
+ this.yOffset = this.height / 2.0F;
+ }
+
+ protected void entityInit() {
+ }
+
+ /**
+ * Called to update the entity's position/logic.
+ */
+ public void onUpdate() {
+ super.onUpdate();
+
+ if (this.field_70532_c > 0) {
+ --this.field_70532_c;
+ }
+
+ this.prevPosX = this.posX;
+ this.prevPosY = this.posY;
+ this.prevPosZ = this.posZ;
+ this.motionY -= 0.029999999329447746D;
+
+ if (this.worldObj.getBlockMaterial(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY),
+ MathHelper.floor_double(this.posZ)) == Material.lava) {
+ this.motionY = 0.20000000298023224D;
+ this.motionX = (double) ((this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F);
+ this.motionZ = (double) ((this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F);
+ this.playSound("random.fizz", 0.4F, 2.0F + this.rand.nextFloat() * 0.4F);
+ }
+
+ this.pushOutOfBlocks(this.posX, (this.boundingBox.minY + this.boundingBox.maxY) / 2.0D, this.posZ);
+ double var1 = 8.0D;
+
+ if (this.xpTargetColor < this.xpColor - 20 + this.entityId % 100) {
+ if (this.closestPlayer == null || this.closestPlayer.getDistanceSqToEntity(this) > var1 * var1) {
+ this.closestPlayer = this.worldObj.getClosestPlayerToEntity(this, var1);
+ }
+
+ this.xpTargetColor = this.xpColor;
+ }
+
+ if (this.closestPlayer != null) {
+ double var3 = (this.closestPlayer.posX - this.posX) / var1;
+ double var5 = (this.closestPlayer.posY + (double) this.closestPlayer.getEyeHeight() - this.posY) / var1;
+ double var7 = (this.closestPlayer.posZ - this.posZ) / var1;
+ double var9 = Math.sqrt(var3 * var3 + var5 * var5 + var7 * var7);
+ double var11 = 1.0D - var9;
+
+ if (var11 > 0.0D) {
+ var11 *= var11;
+ this.motionX += var3 / var9 * var11 * 0.1D;
+ this.motionY += var5 / var9 * var11 * 0.1D;
+ this.motionZ += var7 / var9 * var11 * 0.1D;
+ }
+ }
+
+ this.moveEntity(this.motionX, this.motionY, this.motionZ);
+ float var13 = 0.98F;
+
+ if (this.onGround) {
+ var13 = 0.58800006F;
+ int var4 = this.worldObj.getBlockId(MathHelper.floor_double(this.posX),
+ MathHelper.floor_double(this.boundingBox.minY) - 1, MathHelper.floor_double(this.posZ));
+
+ if (var4 > 0) {
+ var13 = Block.blocksList[var4].slipperiness * 0.98F;
+ }
+ }
+
+ this.motionX *= (double) var13;
+ this.motionY *= 0.9800000190734863D;
+ this.motionZ *= (double) var13;
+
+ if (this.onGround) {
+ this.motionY *= -0.8999999761581421D;
+ }
+
+ ++this.xpColor;
+ ++this.xpOrbAge;
+
+ if (this.xpOrbAge >= 6000) {
+ this.setDead();
+ }
+ }
+
+ /**
+ * Returns if this entity is in water and will end up adding the waters velocity
+ * to the entity
+ */
+ public boolean handleWaterMovement() {
+ return this.worldObj.handleMaterialAcceleration(this.boundingBox, Material.water, this);
+ }
+
+ /**
+ * Will deal the specified amount of damage to the entity if the entity isn't
+ * immune to fire damage. Args: amountDamage
+ */
+ protected void dealFireDamage(int par1) {
+ this.attackEntityFrom(DamageSource.inFire, par1);
+ }
+
+ /**
+ * Called when the entity is attacked.
+ */
+ public boolean attackEntityFrom(DamageSource par1DamageSource, int par2) {
+ if (this.isEntityInvulnerable()) {
+ return false;
+ } else {
+ this.setBeenAttacked();
+ this.xpOrbHealth -= par2;
+
+ if (this.xpOrbHealth <= 0) {
+ this.setDead();
+ }
+
+ return false;
+ }
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ par1NBTTagCompound.setShort("Health", (short) ((byte) this.xpOrbHealth));
+ par1NBTTagCompound.setShort("Age", (short) this.xpOrbAge);
+ par1NBTTagCompound.setShort("Value", (short) this.xpValue);
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ this.xpOrbHealth = par1NBTTagCompound.getShort("Health") & 255;
+ this.xpOrbAge = par1NBTTagCompound.getShort("Age");
+ this.xpValue = par1NBTTagCompound.getShort("Value");
+ }
+
+ /**
+ * Called by a player entity when they collide with an entity
+ */
+ public void onCollideWithPlayer(EntityPlayer par1EntityPlayer) {
+ if (!this.worldObj.isRemote) {
+ if (this.field_70532_c == 0 && par1EntityPlayer.xpCooldown == 0) {
+ par1EntityPlayer.xpCooldown = 2;
+ this.playSound("random.orb", 0.1F,
+ 0.5F * ((this.rand.nextFloat() - this.rand.nextFloat()) * 0.7F + 1.8F));
+ par1EntityPlayer.onItemPickup(this, 1);
+ par1EntityPlayer.addExperience(this.xpValue);
+ this.setDead();
+ }
+ }
+ }
+
+ /**
+ * Returns the XP value of this XP orb.
+ */
+ public int getXpValue() {
+ return this.xpValue;
+ }
+
+ /**
+ * Get a fragment of the maximum experience points value for the supplied value
+ * of experience points value.
+ */
+ public static int getXPSplit(int par0) {
+ return par0 >= 2477 ? 2477
+ : (par0 >= 1237 ? 1237
+ : (par0 >= 617 ? 617
+ : (par0 >= 307 ? 307
+ : (par0 >= 149 ? 149
+ : (par0 >= 73 ? 73
+ : (par0 >= 37 ? 37
+ : (par0 >= 17 ? 17
+ : (par0 >= 7 ? 7 : (par0 >= 3 ? 3 : 1)))))))));
+ }
+
+ /**
+ * If returns false, the item will not inflict any damage against entities.
+ */
+ public boolean canAttackWithItem() {
+ return false;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EntityZombie.java b/sp-server/src/main/java/net/minecraft/src/EntityZombie.java
new file mode 100644
index 0000000..c1b3597
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EntityZombie.java
@@ -0,0 +1,440 @@
+package net.minecraft.src;
+
+import java.util.Calendar;
+
+public class EntityZombie extends EntityMob {
+ /**
+ * Ticker used to determine the time remaining for this zombie to convert into a
+ * villager when cured.
+ */
+ private int conversionTime = 0;
+
+ public EntityZombie(World par1World) {
+ super(par1World);
+ this.texture = "/mob/zombie.png";
+ this.moveSpeed = 0.23F;
+ this.getNavigator().setBreakDoors(true);
+ this.tasks.addTask(0, new EntityAISwimming(this));
+ this.tasks.addTask(1, new EntityAIBreakDoor(this));
+ this.tasks.addTask(2, new EntityAIAttackOnCollide(this, EntityPlayer.class, this.moveSpeed, false));
+ this.tasks.addTask(3, new EntityAIAttackOnCollide(this, EntityVillager.class, this.moveSpeed, true));
+ this.tasks.addTask(4, new EntityAIMoveTwardsRestriction(this, this.moveSpeed));
+ this.tasks.addTask(5, new EntityAIMoveThroughVillage(this, this.moveSpeed, false));
+ this.tasks.addTask(6, new EntityAIWander(this, this.moveSpeed));
+ this.tasks.addTask(7, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F));
+ this.tasks.addTask(7, new EntityAILookIdle(this));
+ this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, true));
+ this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, EntityPlayer.class, 16.0F, 0, true));
+ this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, EntityVillager.class, 16.0F, 0, false));
+ }
+
+ protected int func_96121_ay() {
+ return 40;
+ }
+
+ /**
+ * This method returns a value to be applied directly to entity speed, this
+ * factor is less than 1 when a slowdown potion effect is applied, more than 1
+ * when a haste potion effect is applied and 2 for fleeing entities.
+ */
+ public float getSpeedModifier() {
+ return super.getSpeedModifier() * (this.isChild() ? 1.5F : 1.0F);
+ }
+
+ protected void entityInit() {
+ super.entityInit();
+ this.getDataWatcher().addObject(12, Byte.valueOf((byte) 0));
+ this.getDataWatcher().addObject(13, Byte.valueOf((byte) 0));
+ this.getDataWatcher().addObject(14, Byte.valueOf((byte) 0));
+ }
+
+ public int getMaxHealth() {
+ return 20;
+ }
+
+ /**
+ * Returns the current armor value as determined by a call to
+ * InventoryPlayer.getTotalArmorValue
+ */
+ public int getTotalArmorValue() {
+ int var1 = super.getTotalArmorValue() + 2;
+
+ if (var1 > 20) {
+ var1 = 20;
+ }
+
+ return var1;
+ }
+
+ /**
+ * Returns true if the newer Entity AI code should be run
+ */
+ protected boolean isAIEnabled() {
+ return true;
+ }
+
+ /**
+ * If Animal, checks if the age timer is negative
+ */
+ public boolean isChild() {
+ return this.getDataWatcher().getWatchableObjectByte(12) == 1;
+ }
+
+ /**
+ * Set whether this zombie is a child.
+ */
+ public void setChild(boolean par1) {
+ this.getDataWatcher().updateObject(12, Byte.valueOf((byte) 1));
+ }
+
+ /**
+ * Return whether this zombie is a villager.
+ */
+ public boolean isVillager() {
+ return this.getDataWatcher().getWatchableObjectByte(13) == 1;
+ }
+
+ /**
+ * Set whether this zombie is a villager.
+ */
+ public void setVillager(boolean par1) {
+ this.getDataWatcher().updateObject(13, Byte.valueOf((byte) (par1 ? 1 : 0)));
+ }
+
+ /**
+ * Called frequently so the entity can update its state every tick as required.
+ * For example, zombies and skeletons use this to react to sunlight and start to
+ * burn.
+ */
+ public void onLivingUpdate() {
+ if (this.worldObj.isDaytime() && !this.worldObj.isRemote && !this.isChild()) {
+ float var1 = this.getBrightness(1.0F);
+
+ if (var1 > 0.5F && this.rand.nextFloat() * 30.0F < (var1 - 0.4F) * 2.0F
+ && this.worldObj.canBlockSeeTheSky(MathHelper.floor_double(this.posX),
+ MathHelper.floor_double(this.posY), MathHelper.floor_double(this.posZ))) {
+ boolean var2 = true;
+ ItemStack var3 = this.getEquipmentInSlot(4);
+
+ if (var3 != null) {
+ if (var3.isItemStackDamageable()) {
+ var3.setItemDamage(var3.getItemDamageForDisplay() + this.rand.nextInt(2));
+
+ if (var3.getItemDamageForDisplay() >= var3.getMaxDamage()) {
+ this.renderBrokenItemStack(var3);
+ this.setCurrentItemOrArmor(4, (ItemStack) null);
+ }
+ }
+
+ var2 = false;
+ }
+
+ if (var2) {
+ this.setFire(8);
+ }
+ }
+ }
+
+ super.onLivingUpdate();
+ }
+
+ /**
+ * Called to update the entity's position/logic.
+ */
+ public void onUpdate() {
+ if (!this.worldObj.isRemote && this.isConverting()) {
+ int var1 = this.getConversionTimeBoost();
+ this.conversionTime -= var1;
+
+ if (this.conversionTime <= 0) {
+ this.convertToVillager();
+ }
+ }
+
+ super.onUpdate();
+ }
+
+ public boolean attackEntityAsMob(Entity par1Entity) {
+ boolean var2 = super.attackEntityAsMob(par1Entity);
+
+ if (var2 && this.getHeldItem() == null && this.isBurning()
+ && this.rand.nextFloat() < (float) this.worldObj.difficultySetting * 0.3F) {
+ par1Entity.setFire(2 * this.worldObj.difficultySetting);
+ }
+
+ return var2;
+ }
+
+ /**
+ * Returns the amount of damage a mob should deal.
+ */
+ public int getAttackStrength(Entity par1Entity) {
+ ItemStack var2 = this.getHeldItem();
+ float var3 = (float) (this.getMaxHealth() - this.getHealth()) / (float) this.getMaxHealth();
+ int var4 = 3 + MathHelper.floor_float(var3 * 4.0F);
+
+ if (var2 != null) {
+ var4 += var2.getDamageVsEntity(this);
+ }
+
+ return var4;
+ }
+
+ /**
+ * Returns the sound this mob makes while it's alive.
+ */
+ protected String getLivingSound() {
+ return "mob.zombie.say";
+ }
+
+ /**
+ * Returns the sound this mob makes when it is hurt.
+ */
+ protected String getHurtSound() {
+ return "mob.zombie.hurt";
+ }
+
+ /**
+ * Returns the sound this mob makes on death.
+ */
+ protected String getDeathSound() {
+ return "mob.zombie.death";
+ }
+
+ /**
+ * Plays step sound at given x, y, z for the entity
+ */
+ protected void playStepSound(int par1, int par2, int par3, int par4) {
+ this.playSound("mob.zombie.step", 0.15F, 1.0F);
+ }
+
+ /**
+ * Returns the item ID for the item the mob drops on death.
+ */
+ protected int getDropItemId() {
+ return Item.rottenFlesh.itemID;
+ }
+
+ /**
+ * Get this Entity's EnumCreatureAttribute
+ */
+ public EnumCreatureAttribute getCreatureAttribute() {
+ return EnumCreatureAttribute.UNDEAD;
+ }
+
+ protected void dropRareDrop(int par1) {
+ switch (this.rand.nextInt(3)) {
+ case 0:
+ this.dropItem(Item.ingotIron.itemID, 1);
+ break;
+
+ case 1:
+ this.dropItem(Item.carrot.itemID, 1);
+ break;
+
+ case 2:
+ this.dropItem(Item.potato.itemID, 1);
+ }
+ }
+
+ /**
+ * Makes entity wear random armor based on difficulty
+ */
+ protected void addRandomArmor() {
+ super.addRandomArmor();
+
+ if (this.rand.nextFloat() < (this.worldObj.difficultySetting == 3 ? 0.05F : 0.01F)) {
+ int var1 = this.rand.nextInt(3);
+
+ if (var1 == 0) {
+ this.setCurrentItemOrArmor(0, new ItemStack(Item.swordIron));
+ } else {
+ this.setCurrentItemOrArmor(0, new ItemStack(Item.shovelIron));
+ }
+ }
+ }
+
+ /**
+ * (abstract) Protected helper method to write subclass entity data to NBT.
+ */
+ public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
+ super.writeEntityToNBT(par1NBTTagCompound);
+
+ if (this.isChild()) {
+ par1NBTTagCompound.setBoolean("IsBaby", true);
+ }
+
+ if (this.isVillager()) {
+ par1NBTTagCompound.setBoolean("IsVillager", true);
+ }
+
+ par1NBTTagCompound.setInteger("ConversionTime", this.isConverting() ? this.conversionTime : -1);
+ }
+
+ /**
+ * (abstract) Protected helper method to read subclass entity data from NBT.
+ */
+ public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
+ super.readEntityFromNBT(par1NBTTagCompound);
+
+ if (par1NBTTagCompound.getBoolean("IsBaby")) {
+ this.setChild(true);
+ }
+
+ if (par1NBTTagCompound.getBoolean("IsVillager")) {
+ this.setVillager(true);
+ }
+
+ if (par1NBTTagCompound.hasKey("ConversionTime") && par1NBTTagCompound.getInteger("ConversionTime") > -1) {
+ this.startConversion(par1NBTTagCompound.getInteger("ConversionTime"));
+ }
+ }
+
+ /**
+ * This method gets called when the entity kills another one.
+ */
+ public void onKillEntity(EntityLiving par1EntityLiving) {
+ super.onKillEntity(par1EntityLiving);
+
+ if (this.worldObj.difficultySetting >= 2 && par1EntityLiving instanceof EntityVillager) {
+ if (this.worldObj.difficultySetting == 2 && this.rand.nextBoolean()) {
+ return;
+ }
+
+ EntityZombie var2 = new EntityZombie(this.worldObj);
+ var2.func_82149_j(par1EntityLiving);
+ this.worldObj.removeEntity(par1EntityLiving);
+ var2.initCreature();
+ var2.setVillager(true);
+
+ if (par1EntityLiving.isChild()) {
+ var2.setChild(true);
+ }
+
+ this.worldObj.spawnEntityInWorld(var2);
+ this.worldObj.playAuxSFXAtEntity((EntityPlayer) null, 1016, (int) this.posX, (int) this.posY,
+ (int) this.posZ, 0);
+ }
+ }
+
+ /**
+ * Initialize this creature.
+ */
+ public void initCreature() {
+ this.setCanPickUpLoot(this.rand.nextFloat() < pickUpLootProability[this.worldObj.difficultySetting]);
+
+ if (this.worldObj.rand.nextFloat() < 0.05F) {
+ this.setVillager(true);
+ }
+
+ this.addRandomArmor();
+ this.func_82162_bC();
+
+ if (this.getEquipmentInSlot(4) == null) {
+ Calendar var1 = this.worldObj.getCurrentDate();
+
+ if (var1.get(2) + 1 == 10 && var1.get(5) == 31 && this.rand.nextFloat() < 0.25F) {
+ this.setCurrentItemOrArmor(4,
+ new ItemStack(this.rand.nextFloat() < 0.1F ? Block.pumpkinLantern : Block.pumpkin));
+ this.equipmentDropChances[4] = 0.0F;
+ }
+ }
+ }
+
+ /**
+ * Called when a player interacts with a mob. e.g. gets milk from a cow, gets
+ * into the saddle on a pig.
+ */
+ public boolean interact(EntityPlayer par1EntityPlayer) {
+ ItemStack var2 = par1EntityPlayer.getCurrentEquippedItem();
+
+ if (var2 != null && var2.getItem() == Item.appleGold && var2.getItemDamage() == 0 && this.isVillager()
+ && this.isPotionActive(Potion.weakness)) {
+ if (!par1EntityPlayer.capabilities.isCreativeMode) {
+ --var2.stackSize;
+ }
+
+ if (var2.stackSize <= 0) {
+ par1EntityPlayer.inventory.setInventorySlotContents(par1EntityPlayer.inventory.currentItem,
+ (ItemStack) null);
+ }
+
+ if (!this.worldObj.isRemote) {
+ this.startConversion(this.rand.nextInt(2401) + 3600);
+ }
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Starts converting this zombie into a villager. The zombie converts into a
+ * villager after the specified time in ticks.
+ */
+ protected void startConversion(int par1) {
+ this.conversionTime = par1;
+ this.getDataWatcher().updateObject(14, Byte.valueOf((byte) 1));
+ this.removePotionEffect(Potion.weakness.id);
+ this.addPotionEffect(
+ new PotionEffect(Potion.damageBoost.id, par1, Math.min(this.worldObj.difficultySetting - 1, 0)));
+ this.worldObj.setEntityState(this, (byte) 16);
+ }
+
+ /**
+ * Returns whether this zombie is in the process of converting to a villager
+ */
+ public boolean isConverting() {
+ return this.getDataWatcher().getWatchableObjectByte(14) == 1;
+ }
+
+ /**
+ * Convert this zombie into a villager.
+ */
+ protected void convertToVillager() {
+ EntityVillager var1 = new EntityVillager(this.worldObj);
+ var1.func_82149_j(this);
+ var1.initCreature();
+ var1.func_82187_q();
+
+ if (this.isChild()) {
+ var1.setGrowingAge(-24000);
+ }
+
+ this.worldObj.removeEntity(this);
+ this.worldObj.spawnEntityInWorld(var1);
+ var1.addPotionEffect(new PotionEffect(Potion.confusion.id, 200, 0));
+ this.worldObj.playAuxSFXAtEntity((EntityPlayer) null, 1017, (int) this.posX, (int) this.posY, (int) this.posZ,
+ 0);
+ }
+
+ /**
+ * Return the amount of time decremented from conversionTime every tick.
+ */
+ protected int getConversionTimeBoost() {
+ int var1 = 1;
+
+ if (this.rand.nextFloat() < 0.01F) {
+ int var2 = 0;
+
+ for (int var3 = (int) this.posX - 4; var3 < (int) this.posX + 4 && var2 < 14; ++var3) {
+ for (int var4 = (int) this.posY - 4; var4 < (int) this.posY + 4 && var2 < 14; ++var4) {
+ for (int var5 = (int) this.posZ - 4; var5 < (int) this.posZ + 4 && var2 < 14; ++var5) {
+ int var6 = this.worldObj.getBlockId(var3, var4, var5);
+
+ if (var6 == Block.fenceIron.blockID || var6 == Block.bed.blockID) {
+ if (this.rand.nextFloat() < 0.3F) {
+ ++var1;
+ }
+
+ ++var2;
+ }
+ }
+ }
+ }
+ }
+
+ return var1;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EnumAction.java b/sp-server/src/main/java/net/minecraft/src/EnumAction.java
new file mode 100644
index 0000000..20076ba
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EnumAction.java
@@ -0,0 +1,5 @@
+package net.minecraft.src;
+
+public enum EnumAction {
+ none, eat, drink, block, bow;
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EnumArmorMaterial.java b/sp-server/src/main/java/net/minecraft/src/EnumArmorMaterial.java
new file mode 100644
index 0000000..6354d80
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EnumArmorMaterial.java
@@ -0,0 +1,62 @@
+package net.minecraft.src;
+
+public enum EnumArmorMaterial {
+ CLOTH(5, new int[] { 1, 3, 2, 1 }, 15), CHAIN(15, new int[] { 2, 5, 4, 1 }, 12),
+ IRON(15, new int[] { 2, 6, 5, 2 }, 9), GOLD(7, new int[] { 2, 5, 3, 1 }, 25),
+ DIAMOND(33, new int[] { 3, 8, 6, 3 }, 10);
+
+ /**
+ * Holds the maximum damage factor (each piece multiply this by it's own value)
+ * of the material, this is the item damage (how much can absorb before breaks)
+ */
+ private int maxDamageFactor;
+
+ /**
+ * Holds the damage reduction (each 1 points is half a shield on gui) of each
+ * piece of armor (helmet, plate, legs and boots)
+ */
+ private int[] damageReductionAmountArray;
+
+ /** Return the enchantability factor of the material */
+ private int enchantability;
+
+ private EnumArmorMaterial(int par3, int[] par4ArrayOfInteger, int par5) {
+ this.maxDamageFactor = par3;
+ this.damageReductionAmountArray = par4ArrayOfInteger;
+ this.enchantability = par5;
+ }
+
+ /**
+ * Returns the durability for a armor slot of for this type.
+ */
+ public int getDurability(int par1) {
+ return ItemArmor.getMaxDamageArray()[par1] * this.maxDamageFactor;
+ }
+
+ /**
+ * Return the damage reduction (each 1 point is a half a shield on gui) of the
+ * piece index passed (0 = helmet, 1 = plate, 2 = legs and 3 = boots)
+ */
+ public int getDamageReductionAmount(int par1) {
+ return this.damageReductionAmountArray[par1];
+ }
+
+ /**
+ * Return the enchantability factor of the material.
+ */
+ public int getEnchantability() {
+ return this.enchantability;
+ }
+
+ /**
+ * Return the crafting material for this armor material, used to determine the
+ * item that can be used to repair an armor piece with an anvil
+ */
+ public int getArmorCraftingMaterial() {
+ return this == CLOTH ? Item.leather.itemID
+ : (this == CHAIN ? Item.ingotIron.itemID
+ : (this == GOLD ? Item.ingotGold.itemID
+ : (this == IRON ? Item.ingotIron.itemID
+ : (this == DIAMOND ? Item.diamond.itemID : 0))));
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EnumArt.java b/sp-server/src/main/java/net/minecraft/src/EnumArt.java
new file mode 100644
index 0000000..7c74df5
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EnumArt.java
@@ -0,0 +1,32 @@
+package net.minecraft.src;
+
+public enum EnumArt {
+ Kebab("Kebab", 16, 16, 0, 0), Aztec("Aztec", 16, 16, 16, 0), Alban("Alban", 16, 16, 32, 0),
+ Aztec2("Aztec2", 16, 16, 48, 0), Bomb("Bomb", 16, 16, 64, 0), Plant("Plant", 16, 16, 80, 0),
+ Wasteland("Wasteland", 16, 16, 96, 0), Pool("Pool", 32, 16, 0, 32), Courbet("Courbet", 32, 16, 32, 32),
+ Sea("Sea", 32, 16, 64, 32), Sunset("Sunset", 32, 16, 96, 32), Creebet("Creebet", 32, 16, 128, 32),
+ Wanderer("Wanderer", 16, 32, 0, 64), Graham("Graham", 16, 32, 16, 64), Match("Match", 32, 32, 0, 128),
+ Bust("Bust", 32, 32, 32, 128), Stage("Stage", 32, 32, 64, 128), Void("Void", 32, 32, 96, 128),
+ SkullAndRoses("SkullAndRoses", 32, 32, 128, 128), Wither("Wither", 32, 32, 160, 128),
+ Fighters("Fighters", 64, 32, 0, 96), Pointer("Pointer", 64, 64, 0, 192), Pigscene("Pigscene", 64, 64, 64, 192),
+ BurningSkull("BurningSkull", 64, 64, 128, 192), Skeleton("Skeleton", 64, 48, 192, 64),
+ DonkeyKong("DonkeyKong", 64, 48, 192, 112);
+
+ /** Holds the maximum length of paintings art title. */
+ public static final int maxArtTitleLength = "SkullAndRoses".length();
+
+ /** Painting Title. */
+ public final String title;
+ public final int sizeX;
+ public final int sizeY;
+ public final int offsetX;
+ public final int offsetY;
+
+ private EnumArt(String par3Str, int par4, int par5, int par6, int par7) {
+ this.title = par3Str;
+ this.sizeX = par4;
+ this.sizeY = par5;
+ this.offsetX = par6;
+ this.offsetY = par7;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EnumChatFormatting.java b/sp-server/src/main/java/net/minecraft/src/EnumChatFormatting.java
new file mode 100644
index 0000000..60ed6cd
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EnumChatFormatting.java
@@ -0,0 +1,82 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+public enum EnumChatFormatting {
+ BLACK('0'), DARK_BLUE('1'), DARK_GREEN('2'), DARK_AQUA('3'), DARK_RED('4'), DARK_PURPLE('5'), GOLD('6'), GRAY('7'),
+ DARK_GRAY('8'), BLUE('9'), GREEN('a'), AQUA('b'), RED('c'), LIGHT_PURPLE('d'), YELLOW('e'), WHITE('f'),
+ OBFUSCATED('k', true), BOLD('l', true), STRIKETHROUGH('m', true), UNDERLINE('n', true), ITALIC('o', true),
+ RESET('r');
+
+ private static final Map field_96321_w = new HashMap();
+ private static final Map field_96331_x = new HashMap();
+ private static final Pattern field_96330_y = Pattern.compile("(?i)" + String.valueOf('\u00a7') + "[0-9A-FK-OR]");
+ private final char field_96329_z;
+ private final boolean field_96303_A;
+ private final String field_96304_B;
+
+ private EnumChatFormatting(char par3) {
+ this(par3, false);
+ }
+
+ private EnumChatFormatting(char par3, boolean par4) {
+ this.field_96329_z = par3;
+ this.field_96303_A = par4;
+ this.field_96304_B = "\u00a7" + par3;
+ }
+
+ public char func_96298_a() {
+ return this.field_96329_z;
+ }
+
+ public boolean func_96301_b() {
+ return this.field_96303_A;
+ }
+
+ public boolean func_96302_c() {
+ return !this.field_96303_A && this != RESET;
+ }
+
+ public String func_96297_d() {
+ return this.name().toLowerCase();
+ }
+
+ public String toString() {
+ return this.field_96304_B;
+ }
+
+ public static EnumChatFormatting func_96300_b(String par0Str) {
+ return par0Str == null ? null : (EnumChatFormatting) field_96331_x.get(par0Str.toLowerCase());
+ }
+
+ public static Collection func_96296_a(boolean par0, boolean par1) {
+ ArrayList var2 = new ArrayList();
+ EnumChatFormatting[] var3 = values();
+ int var4 = var3.length;
+
+ for (int var5 = 0; var5 < var4; ++var5) {
+ EnumChatFormatting var6 = var3[var5];
+
+ if ((!var6.func_96302_c() || par0) && (!var6.func_96301_b() || par1)) {
+ var2.add(var6.func_96297_d());
+ }
+ }
+
+ return var2;
+ }
+
+ static {
+ EnumChatFormatting[] var0 = values();
+ int var1 = var0.length;
+
+ for (int var2 = 0; var2 < var1; ++var2) {
+ EnumChatFormatting var3 = var0[var2];
+ field_96321_w.put(Character.valueOf(var3.func_96298_a()), var3);
+ field_96331_x.put(var3.func_96297_d(), var3);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EnumCreatureAttribute.java b/sp-server/src/main/java/net/minecraft/src/EnumCreatureAttribute.java
new file mode 100644
index 0000000..0bceccb
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EnumCreatureAttribute.java
@@ -0,0 +1,5 @@
+package net.minecraft.src;
+
+public enum EnumCreatureAttribute {
+ UNDEFINED, UNDEAD, ARTHROPOD;
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EnumCreatureType.java b/sp-server/src/main/java/net/minecraft/src/EnumCreatureType.java
new file mode 100644
index 0000000..fb50b7f
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EnumCreatureType.java
@@ -0,0 +1,55 @@
+package net.minecraft.src;
+
+public enum EnumCreatureType {
+ monster(IMob.class, 70, Material.air, false, false), creature(EntityAnimal.class, 10, Material.air, true, true),
+ ambient(EntityAmbientCreature.class, 15, Material.air, true, false),
+ waterCreature(EntityWaterMob.class, 5, Material.water, true, false);
+
+ /**
+ * The root class of creatures associated with this EnumCreatureType (IMobs for
+ * aggressive creatures, EntityAnimals for friendly ones)
+ */
+ private final Class creatureClass;
+ private final int maxNumberOfCreature;
+ private final Material creatureMaterial;
+
+ /** A flag indicating whether this creature type is peaceful. */
+ private final boolean isPeacefulCreature;
+
+ /** Whether this creature type is an animal. */
+ private final boolean isAnimal;
+
+ private EnumCreatureType(Class par3Class, int par4, Material par5Material, boolean par6, boolean par7) {
+ this.creatureClass = par3Class;
+ this.maxNumberOfCreature = par4;
+ this.creatureMaterial = par5Material;
+ this.isPeacefulCreature = par6;
+ this.isAnimal = par7;
+ }
+
+ public Class getCreatureClass() {
+ return this.creatureClass;
+ }
+
+ public int getMaxNumberOfCreature() {
+ return this.maxNumberOfCreature;
+ }
+
+ public Material getCreatureMaterial() {
+ return this.creatureMaterial;
+ }
+
+ /**
+ * Gets whether or not this creature type is peaceful.
+ */
+ public boolean getPeacefulCreature() {
+ return this.isPeacefulCreature;
+ }
+
+ /**
+ * Return whether this creature type is an animal.
+ */
+ public boolean getAnimal() {
+ return this.isAnimal;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EnumDoor.java b/sp-server/src/main/java/net/minecraft/src/EnumDoor.java
new file mode 100644
index 0000000..4b90a8b
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EnumDoor.java
@@ -0,0 +1,5 @@
+package net.minecraft.src;
+
+public enum EnumDoor {
+ OPENING, WOOD_DOOR, GRATES, IRON_DOOR;
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EnumDoorHelper.java b/sp-server/src/main/java/net/minecraft/src/EnumDoorHelper.java
new file mode 100644
index 0000000..04e543e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EnumDoorHelper.java
@@ -0,0 +1,31 @@
+package net.minecraft.src;
+
+class EnumDoorHelper {
+ static final int[] doorEnum = new int[EnumDoor.values().length];
+
+ static {
+ try {
+ doorEnum[EnumDoor.OPENING.ordinal()] = 1;
+ } catch (NoSuchFieldError var4) {
+ ;
+ }
+
+ try {
+ doorEnum[EnumDoor.WOOD_DOOR.ordinal()] = 2;
+ } catch (NoSuchFieldError var3) {
+ ;
+ }
+
+ try {
+ doorEnum[EnumDoor.GRATES.ordinal()] = 3;
+ } catch (NoSuchFieldError var2) {
+ ;
+ }
+
+ try {
+ doorEnum[EnumDoor.IRON_DOOR.ordinal()] = 4;
+ } catch (NoSuchFieldError var1) {
+ ;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EnumEnchantmentType.java b/sp-server/src/main/java/net/minecraft/src/EnumEnchantmentType.java
new file mode 100644
index 0000000..c854746
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EnumEnchantmentType.java
@@ -0,0 +1,29 @@
+package net.minecraft.src;
+
+public enum EnumEnchantmentType {
+ all, armor, armor_feet, armor_legs, armor_torso, armor_head, weapon, digger, bow;
+
+ /**
+ * Return true if the item passed can be enchanted by a enchantment of this
+ * type.
+ */
+ public boolean canEnchantItem(Item par1Item) {
+ if (this == all) {
+ return true;
+ } else if (par1Item instanceof ItemArmor) {
+ if (this == armor) {
+ return true;
+ } else {
+ ItemArmor var2 = (ItemArmor) par1Item;
+ return var2.armorType == 0 ? this == armor_head
+ : (var2.armorType == 2 ? this == armor_legs
+ : (var2.armorType == 1 ? this == armor_torso
+ : (var2.armorType == 3 ? this == armor_feet : false)));
+ }
+ } else {
+ return par1Item instanceof ItemSword ? this == weapon
+ : (par1Item instanceof ItemTool ? this == digger
+ : (par1Item instanceof ItemBow ? this == bow : false));
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EnumEntitySize.java b/sp-server/src/main/java/net/minecraft/src/EnumEntitySize.java
new file mode 100644
index 0000000..e84cb60
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EnumEntitySize.java
@@ -0,0 +1,70 @@
+package net.minecraft.src;
+
+public enum EnumEntitySize {
+ SIZE_1, SIZE_2, SIZE_3, SIZE_4, SIZE_5, SIZE_6;
+
+ public int multiplyBy32AndRound(double par1) {
+ double var3 = par1 - ((double) MathHelper.floor_double(par1) + 0.5D);
+
+ switch (EnumEntitySizeHelper.field_96565_a[this.ordinal()]) {
+ case 1:
+ if (var3 < 0.0D) {
+ if (var3 < -0.3125D) {
+ return MathHelper.ceiling_double_int(par1 * 32.0D);
+ }
+ } else if (var3 < 0.3125D) {
+ return MathHelper.ceiling_double_int(par1 * 32.0D);
+ }
+
+ return MathHelper.floor_double(par1 * 32.0D);
+
+ case 2:
+ if (var3 < 0.0D) {
+ if (var3 < -0.3125D) {
+ return MathHelper.floor_double(par1 * 32.0D);
+ }
+ } else if (var3 < 0.3125D) {
+ return MathHelper.floor_double(par1 * 32.0D);
+ }
+
+ return MathHelper.ceiling_double_int(par1 * 32.0D);
+
+ case 3:
+ if (var3 > 0.0D) {
+ return MathHelper.floor_double(par1 * 32.0D);
+ }
+
+ return MathHelper.ceiling_double_int(par1 * 32.0D);
+
+ case 4:
+ if (var3 < 0.0D) {
+ if (var3 < -0.1875D) {
+ return MathHelper.ceiling_double_int(par1 * 32.0D);
+ }
+ } else if (var3 < 0.1875D) {
+ return MathHelper.ceiling_double_int(par1 * 32.0D);
+ }
+
+ return MathHelper.floor_double(par1 * 32.0D);
+
+ case 5:
+ if (var3 < 0.0D) {
+ if (var3 < -0.1875D) {
+ return MathHelper.floor_double(par1 * 32.0D);
+ }
+ } else if (var3 < 0.1875D) {
+ return MathHelper.floor_double(par1 * 32.0D);
+ }
+
+ return MathHelper.ceiling_double_int(par1 * 32.0D);
+
+ case 6:
+ default:
+ if (var3 > 0.0D) {
+ return MathHelper.ceiling_double_int(par1 * 32.0D);
+ } else {
+ return MathHelper.floor_double(par1 * 32.0D);
+ }
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EnumEntitySizeHelper.java b/sp-server/src/main/java/net/minecraft/src/EnumEntitySizeHelper.java
new file mode 100644
index 0000000..428c06c
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EnumEntitySizeHelper.java
@@ -0,0 +1,43 @@
+package net.minecraft.src;
+
+class EnumEntitySizeHelper {
+ static final int[] field_96565_a = new int[EnumEntitySize.values().length];
+
+ static {
+ try {
+ field_96565_a[EnumEntitySize.SIZE_1.ordinal()] = 1;
+ } catch (NoSuchFieldError var6) {
+ ;
+ }
+
+ try {
+ field_96565_a[EnumEntitySize.SIZE_2.ordinal()] = 2;
+ } catch (NoSuchFieldError var5) {
+ ;
+ }
+
+ try {
+ field_96565_a[EnumEntitySize.SIZE_3.ordinal()] = 3;
+ } catch (NoSuchFieldError var4) {
+ ;
+ }
+
+ try {
+ field_96565_a[EnumEntitySize.SIZE_4.ordinal()] = 4;
+ } catch (NoSuchFieldError var3) {
+ ;
+ }
+
+ try {
+ field_96565_a[EnumEntitySize.SIZE_5.ordinal()] = 5;
+ } catch (NoSuchFieldError var2) {
+ ;
+ }
+
+ try {
+ field_96565_a[EnumEntitySize.SIZE_6.ordinal()] = 6;
+ } catch (NoSuchFieldError var1) {
+ ;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EnumFacing.java b/sp-server/src/main/java/net/minecraft/src/EnumFacing.java
new file mode 100644
index 0000000..fe4065e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EnumFacing.java
@@ -0,0 +1,61 @@
+package net.minecraft.src;
+
+public enum EnumFacing {
+ DOWN(0, 1, 0, -1, 0), UP(1, 0, 0, 1, 0), NORTH(2, 3, 0, 0, -1), SOUTH(3, 2, 0, 0, 1), EAST(4, 5, -1, 0, 0),
+ WEST(5, 4, 1, 0, 0);
+
+ /** Face order for D-U-N-S-E-W. */
+ private final int order_a;
+
+ /** Face order for U-D-S-N-W-E. */
+ private final int order_b;
+ private final int frontOffsetX;
+ private final int frontOffsetY;
+ private final int frontOffsetZ;
+
+ /** List of all values in EnumFacing. Order is D-U-N-S-E-W. */
+ private static final EnumFacing[] faceList = new EnumFacing[6];
+
+ private EnumFacing(int par3, int par4, int par5, int par6, int par7) {
+ this.order_a = par3;
+ this.order_b = par4;
+ this.frontOffsetX = par5;
+ this.frontOffsetY = par6;
+ this.frontOffsetZ = par7;
+ }
+
+ /**
+ * Returns a offset that addresses the block in front of this facing.
+ */
+ public int getFrontOffsetX() {
+ return this.frontOffsetX;
+ }
+
+ public int getFrontOffsetY() {
+ return this.frontOffsetY;
+ }
+
+ /**
+ * Returns a offset that addresses the block in front of this facing.
+ */
+ public int getFrontOffsetZ() {
+ return this.frontOffsetZ;
+ }
+
+ /**
+ * Returns the facing that represents the block in front of it.
+ */
+ public static EnumFacing getFront(int par0) {
+ return faceList[par0 % faceList.length];
+ }
+
+ static {
+ EnumFacing[] var0 = values();
+ int var1 = var0.length;
+
+ for (int var2 = 0; var2 < var1; ++var2) {
+ EnumFacing var3 = var0[var2];
+ faceList[var3.order_a] = var3;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EnumGameType.java b/sp-server/src/main/java/net/minecraft/src/EnumGameType.java
new file mode 100644
index 0000000..6d00253
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EnumGameType.java
@@ -0,0 +1,78 @@
+package net.minecraft.src;
+
+public enum EnumGameType {
+ NOT_SET(-1, ""), SURVIVAL(0, "survival"), CREATIVE(1, "creative"), ADVENTURE(2, "adventure");
+
+ int id;
+ String name;
+
+ private EnumGameType(int par3, String par4Str) {
+ this.id = par3;
+ this.name = par4Str;
+ }
+
+ /**
+ * Returns the ID of this game type
+ */
+ public int getID() {
+ return this.id;
+ }
+
+ /**
+ * Returns the name of this game type
+ */
+ public String getName() {
+ return this.name;
+ }
+
+ /**
+ * Configures the player capabilities based on the game type
+ */
+ public void configurePlayerCapabilities(PlayerCapabilities par1PlayerCapabilities) {
+ if (this == CREATIVE) {
+ par1PlayerCapabilities.allowFlying = true;
+ par1PlayerCapabilities.isCreativeMode = true;
+ par1PlayerCapabilities.disableDamage = true;
+ } else {
+ par1PlayerCapabilities.allowFlying = false;
+ par1PlayerCapabilities.isCreativeMode = false;
+ par1PlayerCapabilities.disableDamage = false;
+ par1PlayerCapabilities.isFlying = false;
+ }
+
+ par1PlayerCapabilities.allowEdit = !this.isAdventure();
+ }
+
+ /**
+ * Returns true if this is the ADVENTURE game type
+ */
+ public boolean isAdventure() {
+ return this == ADVENTURE;
+ }
+
+ /**
+ * Returns true if this is the CREATIVE game type
+ */
+ public boolean isCreative() {
+ return this == CREATIVE;
+ }
+
+ /**
+ * Returns the game type with the specified ID, or SURVIVAL if none found. Args:
+ * id
+ */
+ public static EnumGameType getByID(int par0) {
+ EnumGameType[] var1 = values();
+ int var2 = var1.length;
+
+ for (int var3 = 0; var3 < var2; ++var3) {
+ EnumGameType var4 = var1[var3];
+
+ if (var4.id == par0) {
+ return var4;
+ }
+ }
+
+ return SURVIVAL;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EnumMobType.java b/sp-server/src/main/java/net/minecraft/src/EnumMobType.java
new file mode 100644
index 0000000..cc82f4e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EnumMobType.java
@@ -0,0 +1,5 @@
+package net.minecraft.src;
+
+public enum EnumMobType {
+ everything, mobs, players;
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EnumMovingObjectType.java b/sp-server/src/main/java/net/minecraft/src/EnumMovingObjectType.java
new file mode 100644
index 0000000..bdda685
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EnumMovingObjectType.java
@@ -0,0 +1,5 @@
+package net.minecraft.src;
+
+public enum EnumMovingObjectType {
+ TILE, ENTITY;
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EnumSkyBlock.java b/sp-server/src/main/java/net/minecraft/src/EnumSkyBlock.java
new file mode 100644
index 0000000..881fc7b
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EnumSkyBlock.java
@@ -0,0 +1,11 @@
+package net.minecraft.src;
+
+public enum EnumSkyBlock {
+ Sky(15), Block(0);
+
+ public final int defaultLightValue;
+
+ private EnumSkyBlock(int par3) {
+ this.defaultLightValue = par3;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EnumStatus.java b/sp-server/src/main/java/net/minecraft/src/EnumStatus.java
new file mode 100644
index 0000000..d999efa
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EnumStatus.java
@@ -0,0 +1,5 @@
+package net.minecraft.src;
+
+public enum EnumStatus {
+ OK, NOT_POSSIBLE_HERE, NOT_POSSIBLE_NOW, TOO_FAR_AWAY, OTHER_PROBLEM, NOT_SAFE;
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/EnumToolMaterial.java b/sp-server/src/main/java/net/minecraft/src/EnumToolMaterial.java
new file mode 100644
index 0000000..9f06754
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/EnumToolMaterial.java
@@ -0,0 +1,88 @@
+package net.minecraft.src;
+
+public enum EnumToolMaterial {
+ WOOD(0, 59, 2.0F, 0, 15), STONE(1, 131, 4.0F, 1, 5), IRON(2, 250, 6.0F, 2, 14), EMERALD(3, 1561, 8.0F, 3, 10),
+ GOLD(0, 32, 12.0F, 0, 22);
+
+ /**
+ * The level of material this tool can harvest (3 = DIAMOND, 2 = IRON, 1 =
+ * STONE, 0 = IRON/GOLD)
+ */
+ private final int harvestLevel;
+
+ /**
+ * The number of uses this material allows. (wood = 59, stone = 131, iron = 250,
+ * diamond = 1561, gold = 32)
+ */
+ private final int maxUses;
+
+ /**
+ * The strength of this tool material against blocks which it is effective
+ * against.
+ */
+ private final float efficiencyOnProperMaterial;
+
+ /** Damage versus entities. */
+ private final int damageVsEntity;
+
+ /** Defines the natural enchantability factor of the material. */
+ private final int enchantability;
+
+ private EnumToolMaterial(int par3, int par4, float par5, int par6, int par7) {
+ this.harvestLevel = par3;
+ this.maxUses = par4;
+ this.efficiencyOnProperMaterial = par5;
+ this.damageVsEntity = par6;
+ this.enchantability = par7;
+ }
+
+ /**
+ * The number of uses this material allows. (wood = 59, stone = 131, iron = 250,
+ * diamond = 1561, gold = 32)
+ */
+ public int getMaxUses() {
+ return this.maxUses;
+ }
+
+ /**
+ * The strength of this tool material against blocks which it is effective
+ * against.
+ */
+ public float getEfficiencyOnProperMaterial() {
+ return this.efficiencyOnProperMaterial;
+ }
+
+ /**
+ * Returns the damage against a given entity.
+ */
+ public int getDamageVsEntity() {
+ return this.damageVsEntity;
+ }
+
+ /**
+ * The level of material this tool can harvest (3 = DIAMOND, 2 = IRON, 1 =
+ * STONE, 0 = IRON/GOLD)
+ */
+ public int getHarvestLevel() {
+ return this.harvestLevel;
+ }
+
+ /**
+ * Return the natural enchantability factor of the material.
+ */
+ public int getEnchantability() {
+ return this.enchantability;
+ }
+
+ /**
+ * Return the crafting material for this tool material, used to determine the
+ * item that can be used to repair a tool with an anvil
+ */
+ public int getToolCraftingMaterial() {
+ return this == WOOD ? Block.planks.blockID
+ : (this == STONE ? Block.cobblestone.blockID
+ : (this == GOLD ? Item.ingotGold.itemID
+ : (this == IRON ? Item.ingotIron.itemID
+ : (this == EMERALD ? Item.diamond.itemID : 0))));
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Explosion.java b/sp-server/src/main/java/net/minecraft/src/Explosion.java
new file mode 100644
index 0000000..d4d3951
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Explosion.java
@@ -0,0 +1,240 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class Explosion {
+ /** whether or not the explosion sets fire to blocks around it */
+ public boolean isFlaming = false;
+
+ /** whether or not this explosion spawns smoke particles */
+ public boolean isSmoking = true;
+ private int field_77289_h = 16;
+ private EaglercraftRandom explosionRNG = new EaglercraftRandom();
+ private World worldObj;
+ public double explosionX;
+ public double explosionY;
+ public double explosionZ;
+ public Entity exploder;
+ public float explosionSize;
+
+ /** A list of ChunkPositions of blocks affected by this explosion */
+ public List affectedBlockPositions = new ArrayList();
+ private Map field_77288_k = new HashMap();
+
+ public Explosion(World par1World, Entity par2Entity, double par3, double par5, double par7, float par9) {
+ this.worldObj = par1World;
+ this.exploder = par2Entity;
+ this.explosionSize = par9;
+ this.explosionX = par3;
+ this.explosionY = par5;
+ this.explosionZ = par7;
+ }
+
+ /**
+ * Does the first part of the explosion (destroy blocks)
+ */
+ public void doExplosionA() {
+ float var1 = this.explosionSize;
+ HashSet var2 = new HashSet();
+ int var3;
+ int var4;
+ int var5;
+ double var15;
+ double var17;
+ double var19;
+
+ for (var3 = 0; var3 < this.field_77289_h; ++var3) {
+ for (var4 = 0; var4 < this.field_77289_h; ++var4) {
+ for (var5 = 0; var5 < this.field_77289_h; ++var5) {
+ if (var3 == 0 || var3 == this.field_77289_h - 1 || var4 == 0 || var4 == this.field_77289_h - 1
+ || var5 == 0 || var5 == this.field_77289_h - 1) {
+ double var6 = (double) ((float) var3 / ((float) this.field_77289_h - 1.0F) * 2.0F - 1.0F);
+ double var8 = (double) ((float) var4 / ((float) this.field_77289_h - 1.0F) * 2.0F - 1.0F);
+ double var10 = (double) ((float) var5 / ((float) this.field_77289_h - 1.0F) * 2.0F - 1.0F);
+ double var12 = Math.sqrt(var6 * var6 + var8 * var8 + var10 * var10);
+ var6 /= var12;
+ var8 /= var12;
+ var10 /= var12;
+ float var14 = this.explosionSize * (0.7F + this.worldObj.rand.nextFloat() * 0.6F);
+ var15 = this.explosionX;
+ var17 = this.explosionY;
+ var19 = this.explosionZ;
+
+ for (float var21 = 0.3F; var14 > 0.0F; var14 -= var21 * 0.75F) {
+ int var22 = MathHelper.floor_double(var15);
+ int var23 = MathHelper.floor_double(var17);
+ int var24 = MathHelper.floor_double(var19);
+ int var25 = this.worldObj.getBlockId(var22, var23, var24);
+
+ if (var25 > 0) {
+ Block var26 = Block.blocksList[var25];
+ float var27 = this.exploder != null
+ ? this.exploder.func_82146_a(this, this.worldObj, var22, var23, var24, var26)
+ : var26.getExplosionResistance(this.exploder);
+ var14 -= (var27 + 0.3F) * var21;
+ }
+
+ if (var14 > 0.0F && (this.exploder == null || this.exploder.func_96091_a(this,
+ this.worldObj, var22, var23, var24, var25, var14))) {
+ var2.add(new ChunkPosition(var22, var23, var24));
+ }
+
+ var15 += var6 * (double) var21;
+ var17 += var8 * (double) var21;
+ var19 += var10 * (double) var21;
+ }
+ }
+ }
+ }
+ }
+
+ this.affectedBlockPositions.addAll(var2);
+ this.explosionSize *= 2.0F;
+ var3 = MathHelper.floor_double(this.explosionX - (double) this.explosionSize - 1.0D);
+ var4 = MathHelper.floor_double(this.explosionX + (double) this.explosionSize + 1.0D);
+ var5 = MathHelper.floor_double(this.explosionY - (double) this.explosionSize - 1.0D);
+ int var29 = MathHelper.floor_double(this.explosionY + (double) this.explosionSize + 1.0D);
+ int var7 = MathHelper.floor_double(this.explosionZ - (double) this.explosionSize - 1.0D);
+ int var30 = MathHelper.floor_double(this.explosionZ + (double) this.explosionSize + 1.0D);
+ List var9 = this.worldObj.getEntitiesWithinAABBExcludingEntity(this.exploder, AxisAlignedBB.getAABBPool()
+ .getAABB((double) var3, (double) var5, (double) var7, (double) var4, (double) var29, (double) var30));
+ Vec3 var31 = this.worldObj.getWorldVec3Pool().getVecFromPool(this.explosionX, this.explosionY, this.explosionZ);
+
+ for (int var11 = 0; var11 < var9.size(); ++var11) {
+ Entity var32 = (Entity) var9.get(var11);
+ double var13 = var32.getDistance(this.explosionX, this.explosionY, this.explosionZ)
+ / (double) this.explosionSize;
+
+ if (var13 <= 1.0D) {
+ var15 = var32.posX - this.explosionX;
+ var17 = var32.posY + (double) var32.getEyeHeight() - this.explosionY;
+ var19 = var32.posZ - this.explosionZ;
+ double var33 = (double) MathHelper.sqrt_double(var15 * var15 + var17 * var17 + var19 * var19);
+
+ if (var33 != 0.0D) {
+ var15 /= var33;
+ var17 /= var33;
+ var19 /= var33;
+ double var34 = (double) this.worldObj.getBlockDensity(var31, var32.boundingBox);
+ double var35 = (1.0D - var13) * var34;
+ var32.attackEntityFrom(DamageSource.setExplosionSource(this),
+ (int) ((var35 * var35 + var35) / 2.0D * 8.0D * (double) this.explosionSize + 1.0D));
+ double var36 = EnchantmentProtection.func_92092_a(var32, var35);
+ var32.motionX += var15 * var36;
+ var32.motionY += var17 * var36;
+ var32.motionZ += var19 * var36;
+
+ if (var32 instanceof EntityPlayer) {
+ this.field_77288_k.put((EntityPlayer) var32, this.worldObj.getWorldVec3Pool()
+ .getVecFromPool(var15 * var35, var17 * var35, var19 * var35));
+ }
+ }
+ }
+ }
+
+ this.explosionSize = var1;
+ }
+
+ /**
+ * Does the second part of the explosion (sound, particles, drop spawn)
+ */
+ public void doExplosionB(boolean par1) {
+ this.worldObj.playSoundEffect(this.explosionX, this.explosionY, this.explosionZ, "random.explode", 4.0F,
+ (1.0F + (this.worldObj.rand.nextFloat() - this.worldObj.rand.nextFloat()) * 0.2F) * 0.7F);
+
+ if (this.explosionSize >= 2.0F && this.isSmoking) {
+ this.worldObj.spawnParticle("hugeexplosion", this.explosionX, this.explosionY, this.explosionZ, 1.0D, 0.0D,
+ 0.0D);
+ } else {
+ this.worldObj.spawnParticle("largeexplode", this.explosionX, this.explosionY, this.explosionZ, 1.0D, 0.0D,
+ 0.0D);
+ }
+
+ Iterator var2;
+ ChunkPosition var3;
+ int var4;
+ int var5;
+ int var6;
+ int var7;
+
+ if (this.isSmoking) {
+ var2 = this.affectedBlockPositions.iterator();
+
+ while (var2.hasNext()) {
+ var3 = (ChunkPosition) var2.next();
+ var4 = var3.x;
+ var5 = var3.y;
+ var6 = var3.z;
+ var7 = this.worldObj.getBlockId(var4, var5, var6);
+
+ if (par1) {
+ double var8 = (double) ((float) var4 + this.worldObj.rand.nextFloat());
+ double var10 = (double) ((float) var5 + this.worldObj.rand.nextFloat());
+ double var12 = (double) ((float) var6 + this.worldObj.rand.nextFloat());
+ double var14 = var8 - this.explosionX;
+ double var16 = var10 - this.explosionY;
+ double var18 = var12 - this.explosionZ;
+ double var20 = (double) MathHelper.sqrt_double(var14 * var14 + var16 * var16 + var18 * var18);
+ var14 /= var20;
+ var16 /= var20;
+ var18 /= var20;
+ double var22 = 0.5D / (var20 / (double) this.explosionSize + 0.1D);
+ var22 *= (double) (this.worldObj.rand.nextFloat() * this.worldObj.rand.nextFloat() + 0.3F);
+ var14 *= var22;
+ var16 *= var22;
+ var18 *= var22;
+ this.worldObj.spawnParticle("explode", (var8 + this.explosionX * 1.0D) / 2.0D,
+ (var10 + this.explosionY * 1.0D) / 2.0D, (var12 + this.explosionZ * 1.0D) / 2.0D, var14,
+ var16, var18);
+ this.worldObj.spawnParticle("smoke", var8, var10, var12, var14, var16, var18);
+ }
+
+ if (var7 > 0) {
+ Block var24 = Block.blocksList[var7];
+
+ if (var24.canDropFromExplosion(this)) {
+ var24.dropBlockAsItemWithChance(this.worldObj, var4, var5, var6,
+ this.worldObj.getBlockMetadata(var4, var5, var6), 1.0F / this.explosionSize, 0);
+ }
+
+ this.worldObj.setBlock(var4, var5, var6, 0, 0, 3);
+ var24.onBlockDestroyedByExplosion(this.worldObj, var4, var5, var6, this);
+ }
+ }
+ }
+
+ if (this.isFlaming) {
+ var2 = this.affectedBlockPositions.iterator();
+
+ while (var2.hasNext()) {
+ var3 = (ChunkPosition) var2.next();
+ var4 = var3.x;
+ var5 = var3.y;
+ var6 = var3.z;
+ var7 = this.worldObj.getBlockId(var4, var5, var6);
+ int var25 = this.worldObj.getBlockId(var4, var5 - 1, var6);
+
+ if (var7 == 0 && Block.opaqueCubeLookup[var25] && this.explosionRNG.nextInt(3) == 0) {
+ this.worldObj.setBlock(var4, var5, var6, Block.fire.blockID);
+ }
+ }
+ }
+ }
+
+ public Map func_77277_b() {
+ return this.field_77288_k;
+ }
+
+ public EntityLiving func_94613_c() {
+ return this.exploder == null ? null
+ : (this.exploder instanceof EntityTNTPrimed ? ((EntityTNTPrimed) this.exploder).getTntPlacedBy()
+ : (this.exploder instanceof EntityLiving ? (EntityLiving) this.exploder : null));
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ExtendedBlockStorage.java b/sp-server/src/main/java/net/minecraft/src/ExtendedBlockStorage.java
new file mode 100644
index 0000000..ba9e3ac
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ExtendedBlockStorage.java
@@ -0,0 +1,276 @@
+package net.minecraft.src;
+
+public class ExtendedBlockStorage {
+ /**
+ * Contains the bottom-most Y block represented by this ExtendedBlockStorage.
+ * Typically a multiple of 16.
+ */
+ private int yBase;
+
+ /**
+ * A total count of the number of non-air blocks in this block storage's Chunk.
+ */
+ private int blockRefCount;
+
+ /**
+ * Contains the number of blocks in this block storage's parent chunk that
+ * require random ticking. Used to cull the Chunk from random tick updates for
+ * performance reasons.
+ */
+ private int tickRefCount;
+
+ /**
+ * Contains the least significant 8 bits of each block ID belonging to this
+ * block storage's parent Chunk.
+ */
+ private byte[] blockLSBArray;
+
+ /**
+ * Contains the most significant 4 bits of each block ID belonging to this block
+ * storage's parent Chunk.
+ */
+ private NibbleArray blockMSBArray;
+
+ /**
+ * Stores the metadata associated with blocks in this ExtendedBlockStorage.
+ */
+ private NibbleArray blockMetadataArray;
+
+ /** The NibbleArray containing a block of Block-light data. */
+ private NibbleArray blocklightArray;
+
+ /** The NibbleArray containing a block of Sky-light data. */
+ private NibbleArray skylightArray;
+
+ public ExtendedBlockStorage(int par1, boolean par2) {
+ this.yBase = par1;
+ this.blockLSBArray = new byte[4096];
+ this.blockMetadataArray = new NibbleArray(this.blockLSBArray.length, 4);
+ this.blocklightArray = new NibbleArray(this.blockLSBArray.length, 4);
+
+ if (par2) {
+ this.skylightArray = new NibbleArray(this.blockLSBArray.length, 4);
+ }
+ }
+
+ /**
+ * Returns the extended block ID for a location in a chunk, merged from a byte
+ * array and a NibbleArray to form a full 12-bit block ID.
+ */
+ public int getExtBlockID(int par1, int par2, int par3) {
+ int var4 = this.blockLSBArray[par2 << 8 | par3 << 4 | par1] & 255;
+ return this.blockMSBArray != null ? this.blockMSBArray.get(par1, par2, par3) << 8 | var4 : var4;
+ }
+
+ /**
+ * Sets the extended block ID for a location in a chunk, splitting bits 11..8
+ * into a NibbleArray and bits 7..0 into a byte array. Also performs reference
+ * counting to determine whether or not to broadly cull this Chunk from the
+ * random-update tick list.
+ */
+ public void setExtBlockID(int par1, int par2, int par3, int par4) {
+ int var5 = this.blockLSBArray[par2 << 8 | par3 << 4 | par1] & 255;
+
+ if (this.blockMSBArray != null) {
+ var5 |= this.blockMSBArray.get(par1, par2, par3) << 8;
+ }
+
+ if (var5 == 0 && par4 != 0) {
+ ++this.blockRefCount;
+
+ if (Block.blocksList[par4] != null && Block.blocksList[par4].getTickRandomly()) {
+ ++this.tickRefCount;
+ }
+ } else if (var5 != 0 && par4 == 0) {
+ --this.blockRefCount;
+
+ if (Block.blocksList[var5] != null && Block.blocksList[var5].getTickRandomly()) {
+ --this.tickRefCount;
+ }
+ } else if (Block.blocksList[var5] != null && Block.blocksList[var5].getTickRandomly()
+ && (Block.blocksList[par4] == null || !Block.blocksList[par4].getTickRandomly())) {
+ --this.tickRefCount;
+ } else if ((Block.blocksList[var5] == null || !Block.blocksList[var5].getTickRandomly())
+ && Block.blocksList[par4] != null && Block.blocksList[par4].getTickRandomly()) {
+ ++this.tickRefCount;
+ }
+
+ this.blockLSBArray[par2 << 8 | par3 << 4 | par1] = (byte) (par4 & 255);
+
+ if (par4 > 255) {
+ if (this.blockMSBArray == null) {
+ this.blockMSBArray = new NibbleArray(this.blockLSBArray.length, 4);
+ }
+
+ this.blockMSBArray.set(par1, par2, par3, (par4 & 3840) >> 8);
+ } else if (this.blockMSBArray != null) {
+ this.blockMSBArray.set(par1, par2, par3, 0);
+ }
+ }
+
+ /**
+ * Returns the metadata associated with the block at the given coordinates in
+ * this ExtendedBlockStorage.
+ */
+ public int getExtBlockMetadata(int par1, int par2, int par3) {
+ return this.blockMetadataArray.get(par1, par2, par3);
+ }
+
+ /**
+ * Sets the metadata of the Block at the given coordinates in this
+ * ExtendedBlockStorage to the given metadata.
+ */
+ public void setExtBlockMetadata(int par1, int par2, int par3, int par4) {
+ this.blockMetadataArray.set(par1, par2, par3, par4);
+ }
+
+ /**
+ * Returns whether or not this block storage's Chunk is fully empty, based on
+ * its internal reference count.
+ */
+ public boolean isEmpty() {
+ return this.blockRefCount == 0;
+ }
+
+ /**
+ * Returns whether or not this block storage's Chunk will require random
+ * ticking, used to avoid looping through random block ticks when there are no
+ * blocks that would randomly tick.
+ */
+ public boolean getNeedsRandomTick() {
+ return this.tickRefCount > 0;
+ }
+
+ /**
+ * Returns the Y location of this ExtendedBlockStorage.
+ */
+ public int getYLocation() {
+ return this.yBase;
+ }
+
+ /**
+ * Sets the saved Sky-light value in the extended block storage structure.
+ */
+ public void setExtSkylightValue(int par1, int par2, int par3, int par4) {
+ this.skylightArray.set(par1, par2, par3, par4);
+ }
+
+ /**
+ * Gets the saved Sky-light value in the extended block storage structure.
+ */
+ public int getExtSkylightValue(int par1, int par2, int par3) {
+ return this.skylightArray.get(par1, par2, par3);
+ }
+
+ /**
+ * Sets the saved Block-light value in the extended block storage structure.
+ */
+ public void setExtBlocklightValue(int par1, int par2, int par3, int par4) {
+ this.blocklightArray.set(par1, par2, par3, par4);
+ }
+
+ /**
+ * Gets the saved Block-light value in the extended block storage structure.
+ */
+ public int getExtBlocklightValue(int par1, int par2, int par3) {
+ return this.blocklightArray.get(par1, par2, par3);
+ }
+
+ public void removeInvalidBlocks() {
+ this.blockRefCount = 0;
+ this.tickRefCount = 0;
+
+ for (int var1 = 0; var1 < 16; ++var1) {
+ for (int var2 = 0; var2 < 16; ++var2) {
+ for (int var3 = 0; var3 < 16; ++var3) {
+ int var4 = this.getExtBlockID(var1, var2, var3);
+
+ if (var4 > 0) {
+ if (Block.blocksList[var4] == null) {
+ this.blockLSBArray[var2 << 8 | var3 << 4 | var1] = 0;
+
+ if (this.blockMSBArray != null) {
+ this.blockMSBArray.set(var1, var2, var3, 0);
+ }
+ } else {
+ ++this.blockRefCount;
+
+ if (Block.blocksList[var4].getTickRandomly()) {
+ ++this.tickRefCount;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public byte[] getBlockLSBArray() {
+ return this.blockLSBArray;
+ }
+
+ /**
+ * Returns the block ID MSB (bits 11..8) array for this storage array's Chunk.
+ */
+ public NibbleArray getBlockMSBArray() {
+ return this.blockMSBArray;
+ }
+
+ public NibbleArray getMetadataArray() {
+ return this.blockMetadataArray;
+ }
+
+ /**
+ * Returns the NibbleArray instance containing Block-light data.
+ */
+ public NibbleArray getBlocklightArray() {
+ return this.blocklightArray;
+ }
+
+ /**
+ * Returns the NibbleArray instance containing Sky-light data.
+ */
+ public NibbleArray getSkylightArray() {
+ return this.skylightArray;
+ }
+
+ /**
+ * Sets the array of block ID least significant bits for this
+ * ExtendedBlockStorage.
+ */
+ public void setBlockLSBArray(byte[] par1ArrayOfByte) {
+ this.blockLSBArray = par1ArrayOfByte;
+ }
+
+ /**
+ * Sets the array of blockID most significant bits (blockMSBArray) for this
+ * ExtendedBlockStorage.
+ */
+ public void setBlockMSBArray(NibbleArray par1NibbleArray) {
+ this.blockMSBArray = par1NibbleArray;
+ }
+
+ /**
+ * Sets the NibbleArray of block metadata (blockMetadataArray) for this
+ * ExtendedBlockStorage.
+ */
+ public void setBlockMetadataArray(NibbleArray par1NibbleArray) {
+ this.blockMetadataArray = par1NibbleArray;
+ }
+
+ /**
+ * Sets the NibbleArray instance used for Block-light values in this particular
+ * storage block.
+ */
+ public void setBlocklightArray(NibbleArray par1NibbleArray) {
+ this.blocklightArray = par1NibbleArray;
+ }
+
+ /**
+ * Sets the NibbleArray instance used for Sky-light values in this particular
+ * storage block.
+ */
+ public void setSkylightArray(NibbleArray par1NibbleArray) {
+ this.skylightArray = par1NibbleArray;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Facing.java b/sp-server/src/main/java/net/minecraft/src/Facing.java
new file mode 100644
index 0000000..7db4e10
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Facing.java
@@ -0,0 +1,24 @@
+package net.minecraft.src;
+
+public class Facing {
+ /**
+ * Converts a side to the opposite side. This is the same as XOR'ing it with 1.
+ */
+ public static final int[] oppositeSide = new int[] { 1, 0, 3, 2, 5, 4 };
+
+ /**
+ * gives the offset required for this axis to get the block at that side.
+ */
+ public static final int[] offsetsXForSide = new int[] { 0, 0, 0, 0, -1, 1 };
+
+ /**
+ * gives the offset required for this axis to get the block at that side.
+ */
+ public static final int[] offsetsYForSide = new int[] { -1, 1, 0, 0, 0, 0 };
+
+ /**
+ * gives the offset required for this axis to get the block at that side.
+ */
+ public static final int[] offsetsZForSide = new int[] { 0, 0, -1, 1, 0, 0 };
+ public static final String[] facings = new String[] { "DOWN", "UP", "NORTH", "SOUTH", "WEST", "EAST" };
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/FilterIMob.java b/sp-server/src/main/java/net/minecraft/src/FilterIMob.java
new file mode 100644
index 0000000..2ed6500
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/FilterIMob.java
@@ -0,0 +1,10 @@
+package net.minecraft.src;
+
+final class FilterIMob implements IEntitySelector {
+ /**
+ * Return whether the specified entity is applicable to this filter.
+ */
+ public boolean isEntityApplicable(Entity par1Entity) {
+ return par1Entity instanceof IMob;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/FlatGeneratorInfo.java b/sp-server/src/main/java/net/minecraft/src/FlatGeneratorInfo.java
new file mode 100644
index 0000000..5671eed
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/FlatGeneratorInfo.java
@@ -0,0 +1,263 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+public class FlatGeneratorInfo {
+ /** List of layers on this preset. */
+ private final List flatLayers = new ArrayList();
+
+ /** List of world features enabled on this preset. */
+ private final Map worldFeatures = new HashMap();
+ private int biomeToUse = 0;
+
+ /**
+ * Return the biome used on this preset.
+ */
+ public int getBiome() {
+ return this.biomeToUse;
+ }
+
+ /**
+ * Set the biome used on this preset.
+ */
+ public void setBiome(int par1) {
+ this.biomeToUse = par1;
+ }
+
+ /**
+ * Return the list of world features enabled on this preset.
+ */
+ public Map getWorldFeatures() {
+ return this.worldFeatures;
+ }
+
+ /**
+ * Return the list of layers on this preset.
+ */
+ public List getFlatLayers() {
+ return this.flatLayers;
+ }
+
+ public void func_82645_d() {
+ int var1 = 0;
+ FlatLayerInfo var3;
+
+ for (Iterator var2 = this.flatLayers.iterator(); var2.hasNext(); var1 += var3.getLayerCount()) {
+ var3 = (FlatLayerInfo) var2.next();
+ var3.setMinY(var1);
+ }
+ }
+
+ public String toString() {
+ StringBuilder var1 = new StringBuilder();
+ var1.append(2);
+ var1.append(";");
+ int var2;
+
+ for (var2 = 0; var2 < this.flatLayers.size(); ++var2) {
+ if (var2 > 0) {
+ var1.append(",");
+ }
+
+ var1.append(((FlatLayerInfo) this.flatLayers.get(var2)).toString());
+ }
+
+ var1.append(";");
+ var1.append(this.biomeToUse);
+
+ if (!this.worldFeatures.isEmpty()) {
+ var1.append(";");
+ var2 = 0;
+ Iterator var3 = this.worldFeatures.entrySet().iterator();
+
+ while (var3.hasNext()) {
+ Entry var4 = (Entry) var3.next();
+
+ if (var2++ > 0) {
+ var1.append(",");
+ }
+
+ var1.append(((String) var4.getKey()).toLowerCase());
+ Map var5 = (Map) var4.getValue();
+
+ if (!var5.isEmpty()) {
+ var1.append("(");
+ int var6 = 0;
+ Iterator var7 = var5.entrySet().iterator();
+
+ while (var7.hasNext()) {
+ Entry var8 = (Entry) var7.next();
+
+ if (var6++ > 0) {
+ var1.append(" ");
+ }
+
+ var1.append((String) var8.getKey());
+ var1.append("=");
+ var1.append((String) var8.getValue());
+ }
+
+ var1.append(")");
+ }
+ }
+ } else {
+ var1.append(";");
+ }
+
+ return var1.toString();
+ }
+
+ private static FlatLayerInfo func_82646_a(String par0Str, int par1) {
+ String[] var2 = par0Str.split("x", 2);
+ int var3 = 1;
+ int var5 = 0;
+
+ if (var2.length == 2) {
+ try {
+ var3 = Integer.parseInt(var2[0]);
+
+ if (par1 + var3 >= 256) {
+ var3 = 256 - par1;
+ }
+
+ if (var3 < 0) {
+ var3 = 0;
+ }
+ } catch (Throwable var7) {
+ return null;
+ }
+ }
+
+ int var4;
+
+ try {
+ String var6 = var2[var2.length - 1];
+ var2 = var6.split(":", 2);
+ var4 = Integer.parseInt(var2[0]);
+
+ if (var2.length > 1) {
+ var5 = Integer.parseInt(var2[1]);
+ }
+
+ if (Block.blocksList[var4] == null) {
+ var4 = 0;
+ var5 = 0;
+ }
+
+ if (var5 < 0 || var5 > 15) {
+ var5 = 0;
+ }
+ } catch (Throwable var8) {
+ return null;
+ }
+
+ FlatLayerInfo var9 = new FlatLayerInfo(var3, var4, var5);
+ var9.setMinY(par1);
+ return var9;
+ }
+
+ private static List func_82652_b(String par0Str) {
+ if (par0Str != null && par0Str.length() >= 1) {
+ ArrayList var1 = new ArrayList();
+ String[] var2 = par0Str.split(",");
+ int var3 = 0;
+ String[] var4 = var2;
+ int var5 = var2.length;
+
+ for (int var6 = 0; var6 < var5; ++var6) {
+ String var7 = var4[var6];
+ FlatLayerInfo var8 = func_82646_a(var7, var3);
+
+ if (var8 == null) {
+ return null;
+ }
+
+ var1.add(var8);
+ var3 += var8.getLayerCount();
+ }
+
+ return var1;
+ } else {
+ return null;
+ }
+ }
+
+ public static FlatGeneratorInfo createFlatGeneratorFromString(String par0Str) {
+ if (par0Str == null) {
+ return getDefaultFlatGenerator();
+ } else {
+ String[] var1 = par0Str.split(";", -1);
+ int var2 = var1.length == 1 ? 0 : MathHelper.parseIntWithDefault(var1[0], 0);
+
+ if (var2 >= 0 && var2 <= 2) {
+ FlatGeneratorInfo var3 = new FlatGeneratorInfo();
+ int var4 = var1.length == 1 ? 0 : 1;
+ List var5 = func_82652_b(var1[var4++]);
+
+ if (var5 != null && !var5.isEmpty()) {
+ var3.getFlatLayers().addAll(var5);
+ var3.func_82645_d();
+ int var6 = BiomeGenBase.plains.biomeID;
+
+ if (var2 > 0 && var1.length > var4) {
+ var6 = MathHelper.parseIntWithDefault(var1[var4++], var6);
+ }
+
+ var3.setBiome(var6);
+
+ if (var2 > 0 && var1.length > var4) {
+ String[] var7 = var1[var4++].toLowerCase().split(",");
+ String[] var8 = var7;
+ int var9 = var7.length;
+
+ for (int var10 = 0; var10 < var9; ++var10) {
+ String var11 = var8[var10];
+ String[] var12 = var11.split("\\(", 2);
+ HashMap var13 = new HashMap();
+
+ if (var12[0].length() > 0) {
+ var3.getWorldFeatures().put(var12[0], var13);
+
+ if (var12.length > 1 && var12[1].endsWith(")") && var12[1].length() > 1) {
+ String[] var14 = var12[1].substring(0, var12[1].length() - 1).split(" ");
+
+ for (int var15 = 0; var15 < var14.length; ++var15) {
+ String[] var16 = var14[var15].split("=", 2);
+
+ if (var16.length == 2) {
+ var13.put(var16[0], var16[1]);
+ }
+ }
+ }
+ }
+ }
+ } else {
+ var3.getWorldFeatures().put("village", new HashMap());
+ }
+
+ return var3;
+ } else {
+ return getDefaultFlatGenerator();
+ }
+ } else {
+ return getDefaultFlatGenerator();
+ }
+ }
+ }
+
+ public static FlatGeneratorInfo getDefaultFlatGenerator() {
+ FlatGeneratorInfo var0 = new FlatGeneratorInfo();
+ var0.setBiome(BiomeGenBase.plains.biomeID);
+ var0.getFlatLayers().add(new FlatLayerInfo(1, Block.bedrock.blockID));
+ var0.getFlatLayers().add(new FlatLayerInfo(2, Block.dirt.blockID));
+ var0.getFlatLayers().add(new FlatLayerInfo(1, Block.grass.blockID));
+ var0.func_82645_d();
+ var0.getWorldFeatures().put("village", new HashMap());
+ return var0;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/FlatLayerInfo.java b/sp-server/src/main/java/net/minecraft/src/FlatLayerInfo.java
new file mode 100644
index 0000000..545e183
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/FlatLayerInfo.java
@@ -0,0 +1,76 @@
+package net.minecraft.src;
+
+public class FlatLayerInfo {
+ /** Amount of layers for this set of layers. */
+ private int layerCount;
+
+ /** Block type used on this set of layers. */
+ private int layerFillBlock;
+
+ /** Block metadata used on this set of laeyrs. */
+ private int layerFillBlockMeta;
+ private int layerMinimumY;
+
+ public FlatLayerInfo(int par1, int par2) {
+ this.layerCount = 1;
+ this.layerFillBlock = 0;
+ this.layerFillBlockMeta = 0;
+ this.layerMinimumY = 0;
+ this.layerCount = par1;
+ this.layerFillBlock = par2;
+ }
+
+ public FlatLayerInfo(int par1, int par2, int par3) {
+ this(par1, par2);
+ this.layerFillBlockMeta = par3;
+ }
+
+ /**
+ * Return the amount of layers for this set of layers.
+ */
+ public int getLayerCount() {
+ return this.layerCount;
+ }
+
+ /**
+ * Return the block type used on this set of layers.
+ */
+ public int getFillBlock() {
+ return this.layerFillBlock;
+ }
+
+ /**
+ * Return the block metadata used on this set of layers.
+ */
+ public int getFillBlockMeta() {
+ return this.layerFillBlockMeta;
+ }
+
+ /**
+ * Return the minimum Y coordinate for this layer, set during generation.
+ */
+ public int getMinY() {
+ return this.layerMinimumY;
+ }
+
+ /**
+ * Set the minimum Y coordinate for this layer.
+ */
+ public void setMinY(int par1) {
+ this.layerMinimumY = par1;
+ }
+
+ public String toString() {
+ String var1 = Integer.toString(this.layerFillBlock);
+
+ if (this.layerCount > 1) {
+ var1 = this.layerCount + "x" + var1;
+ }
+
+ if (this.layerFillBlockMeta > 0) {
+ var1 = var1 + ":" + this.layerFillBlockMeta;
+ }
+
+ return var1;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/FoodStats.java b/sp-server/src/main/java/net/minecraft/src/FoodStats.java
new file mode 100644
index 0000000..c70979f
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/FoodStats.java
@@ -0,0 +1,121 @@
+package net.minecraft.src;
+
+public class FoodStats {
+ /** The player's food level. */
+ private int foodLevel = 20;
+
+ /** The player's food saturation. */
+ private float foodSaturationLevel = 5.0F;
+
+ /** The player's food exhaustion. */
+ private float foodExhaustionLevel;
+
+ /** The player's food timer value. */
+ private int foodTimer = 0;
+ private int prevFoodLevel = 20;
+
+ /**
+ * Args: int foodLevel, float foodSaturationModifier
+ */
+ public void addStats(int par1, float par2) {
+ this.foodLevel = Math.min(par1 + this.foodLevel, 20);
+ this.foodSaturationLevel = Math.min(this.foodSaturationLevel + (float) par1 * par2 * 2.0F,
+ (float) this.foodLevel);
+ }
+
+ /**
+ * Eat some food.
+ */
+ public void addStats(ItemFood par1ItemFood) {
+ this.addStats(par1ItemFood.getHealAmount(), par1ItemFood.getSaturationModifier());
+ }
+
+ /**
+ * Handles the food game logic.
+ */
+ public void onUpdate(EntityPlayer par1EntityPlayer) {
+ int var2 = par1EntityPlayer.worldObj.difficultySetting;
+ this.prevFoodLevel = this.foodLevel;
+
+ if (this.foodExhaustionLevel > 4.0F) {
+ this.foodExhaustionLevel -= 4.0F;
+
+ if (this.foodSaturationLevel > 0.0F) {
+ this.foodSaturationLevel = Math.max(this.foodSaturationLevel - 1.0F, 0.0F);
+ } else if (var2 > 0) {
+ this.foodLevel = Math.max(this.foodLevel - 1, 0);
+ }
+ }
+
+ if (this.foodLevel >= 18 && par1EntityPlayer.shouldHeal()) {
+ ++this.foodTimer;
+
+ if (this.foodTimer >= 80) {
+ par1EntityPlayer.heal(1);
+ this.foodTimer = 0;
+ }
+ } else if (this.foodLevel <= 0) {
+ ++this.foodTimer;
+
+ if (this.foodTimer >= 80) {
+ if (par1EntityPlayer.getHealth() > 10 || var2 >= 3 || par1EntityPlayer.getHealth() > 1 && var2 >= 2) {
+ par1EntityPlayer.attackEntityFrom(DamageSource.starve, 1);
+ }
+
+ this.foodTimer = 0;
+ }
+ } else {
+ this.foodTimer = 0;
+ }
+ }
+
+ /**
+ * Reads the food data for the player.
+ */
+ public void readNBT(NBTTagCompound par1NBTTagCompound) {
+ if (par1NBTTagCompound.hasKey("foodLevel")) {
+ this.foodLevel = par1NBTTagCompound.getInteger("foodLevel");
+ this.foodTimer = par1NBTTagCompound.getInteger("foodTickTimer");
+ this.foodSaturationLevel = par1NBTTagCompound.getFloat("foodSaturationLevel");
+ this.foodExhaustionLevel = par1NBTTagCompound.getFloat("foodExhaustionLevel");
+ }
+ }
+
+ /**
+ * Writes the food data for the player.
+ */
+ public void writeNBT(NBTTagCompound par1NBTTagCompound) {
+ par1NBTTagCompound.setInteger("foodLevel", this.foodLevel);
+ par1NBTTagCompound.setInteger("foodTickTimer", this.foodTimer);
+ par1NBTTagCompound.setFloat("foodSaturationLevel", this.foodSaturationLevel);
+ par1NBTTagCompound.setFloat("foodExhaustionLevel", this.foodExhaustionLevel);
+ }
+
+ /**
+ * Get the player's food level.
+ */
+ public int getFoodLevel() {
+ return this.foodLevel;
+ }
+
+ /**
+ * Get whether the player must eat food.
+ */
+ public boolean needFood() {
+ return this.foodLevel < 20;
+ }
+
+ /**
+ * adds input to foodExhaustionLevel to a max of 40
+ */
+ public void addExhaustion(float par1) {
+ this.foodExhaustionLevel = Math.min(this.foodExhaustionLevel + par1, 40.0F);
+ }
+
+ /**
+ * Get the player's food saturation level.
+ */
+ public float getSaturationLevel() {
+ return this.foodSaturationLevel;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/FurnaceRecipes.java b/sp-server/src/main/java/net/minecraft/src/FurnaceRecipes.java
new file mode 100644
index 0000000..2cdfa4e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/FurnaceRecipes.java
@@ -0,0 +1,66 @@
+package net.minecraft.src;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class FurnaceRecipes {
+ private static final FurnaceRecipes smeltingBase = new FurnaceRecipes();
+
+ /** The list of smelting results. */
+ private Map smeltingList = new HashMap();
+ private Map experienceList = new HashMap();
+
+ /**
+ * Used to call methods addSmelting and getSmeltingResult.
+ */
+ public static final FurnaceRecipes smelting() {
+ return smeltingBase;
+ }
+
+ private FurnaceRecipes() {
+ this.addSmelting(Block.oreIron.blockID, new ItemStack(Item.ingotIron), 0.7F);
+ this.addSmelting(Block.oreGold.blockID, new ItemStack(Item.ingotGold), 1.0F);
+ this.addSmelting(Block.oreDiamond.blockID, new ItemStack(Item.diamond), 1.0F);
+ this.addSmelting(Block.sand.blockID, new ItemStack(Block.glass), 0.1F);
+ this.addSmelting(Item.porkRaw.itemID, new ItemStack(Item.porkCooked), 0.35F);
+ this.addSmelting(Item.beefRaw.itemID, new ItemStack(Item.beefCooked), 0.35F);
+ this.addSmelting(Item.chickenRaw.itemID, new ItemStack(Item.chickenCooked), 0.35F);
+ this.addSmelting(Item.fishRaw.itemID, new ItemStack(Item.fishCooked), 0.35F);
+ this.addSmelting(Block.cobblestone.blockID, new ItemStack(Block.stone), 0.1F);
+ this.addSmelting(Item.clay.itemID, new ItemStack(Item.brick), 0.3F);
+ this.addSmelting(Block.cactus.blockID, new ItemStack(Item.dyePowder, 1, 2), 0.2F);
+ this.addSmelting(Block.wood.blockID, new ItemStack(Item.coal, 1, 1), 0.15F);
+ this.addSmelting(Block.oreEmerald.blockID, new ItemStack(Item.emerald), 1.0F);
+ this.addSmelting(Item.potato.itemID, new ItemStack(Item.bakedPotato), 0.35F);
+ this.addSmelting(Block.netherrack.blockID, new ItemStack(Item.netherrackBrick), 0.1F);
+ this.addSmelting(Block.oreCoal.blockID, new ItemStack(Item.coal), 0.1F);
+ this.addSmelting(Block.oreRedstone.blockID, new ItemStack(Item.redstone), 0.7F);
+ this.addSmelting(Block.oreLapis.blockID, new ItemStack(Item.dyePowder, 1, 4), 0.2F);
+ this.addSmelting(Block.oreNetherQuartz.blockID, new ItemStack(Item.netherQuartz), 0.2F);
+ }
+
+ /**
+ * Adds a smelting recipe.
+ */
+ public void addSmelting(int par1, ItemStack par2ItemStack, float par3) {
+ this.smeltingList.put(Integer.valueOf(par1), par2ItemStack);
+ this.experienceList.put(Integer.valueOf(par2ItemStack.itemID), Float.valueOf(par3));
+ }
+
+ /**
+ * Returns the smelting result of an item.
+ */
+ public ItemStack getSmeltingResult(int par1) {
+ return (ItemStack) this.smeltingList.get(Integer.valueOf(par1));
+ }
+
+ public Map getSmeltingList() {
+ return this.smeltingList;
+ }
+
+ public float getExperience(int par1) {
+ return this.experienceList.containsKey(Integer.valueOf(par1))
+ ? ((Float) this.experienceList.get(Integer.valueOf(par1))).floatValue()
+ : 0.0F;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/GameRuleValue.java b/sp-server/src/main/java/net/minecraft/src/GameRuleValue.java
new file mode 100644
index 0000000..50eb3de
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/GameRuleValue.java
@@ -0,0 +1,48 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.NoCatchParse;
+
+class GameRuleValue {
+ private String valueString;
+ private boolean valueBoolean;
+ private int valueInteger;
+ private double valueDouble;
+
+ public GameRuleValue(String par1Str) {
+ this.setValue(par1Str);
+ }
+
+ /**
+ * Set this game rule value.
+ */
+ public void setValue(String par1Str) {
+ this.valueString = par1Str;
+ this.valueBoolean = Boolean.parseBoolean(par1Str);
+
+ this.valueInteger = NoCatchParse.parseInt(par1Str);
+
+ if(this.valueInteger == NoCatchParse.INT_EXCEPTION) {
+ this.valueInteger = 0;
+ }
+
+ this.valueDouble = NoCatchParse.parseDouble(par1Str);
+
+ if(this.valueDouble == NoCatchParse.DOUBLE_EXCEPTION) {
+ this.valueDouble = 0.0d;
+ }
+ }
+
+ /**
+ * Gets the GameRule's value as String.
+ */
+ public String getGameRuleStringValue() {
+ return this.valueString;
+ }
+
+ /**
+ * Gets the GameRule's value as boolean.
+ */
+ public boolean getGameRuleBooleanValue() {
+ return this.valueBoolean;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/GameRules.java b/sp-server/src/main/java/net/minecraft/src/GameRules.java
new file mode 100644
index 0000000..40b09d8
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/GameRules.java
@@ -0,0 +1,97 @@
+package net.minecraft.src;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.TreeMap;
+
+public class GameRules {
+ private TreeMap theGameRules = new TreeMap();
+
+ public GameRules() {
+ this.addGameRule("doFireTick", "true");
+ this.addGameRule("mobGriefing", "true");
+ this.addGameRule("keepInventory", "false");
+ this.addGameRule("doMobSpawning", "true");
+ this.addGameRule("doMobLoot", "true");
+ this.addGameRule("doTileDrops", "true");
+ this.addGameRule("commandBlockOutput", "true");
+ }
+
+ /**
+ * Define a game rule and its default value.
+ */
+ public void addGameRule(String par1Str, String par2Str) {
+ this.theGameRules.put(par1Str, new GameRuleValue(par2Str));
+ }
+
+ public void setOrCreateGameRule(String par1Str, String par2Str) {
+ GameRuleValue var3 = (GameRuleValue) this.theGameRules.get(par1Str);
+
+ if (var3 != null) {
+ var3.setValue(par2Str);
+ } else {
+ this.addGameRule(par1Str, par2Str);
+ }
+ }
+
+ /**
+ * Gets the string Game Rule value.
+ */
+ public String getGameRuleStringValue(String par1Str) {
+ GameRuleValue var2 = (GameRuleValue) this.theGameRules.get(par1Str);
+ return var2 != null ? var2.getGameRuleStringValue() : "";
+ }
+
+ /**
+ * Gets the boolean Game Rule value.
+ */
+ public boolean getGameRuleBooleanValue(String par1Str) {
+ GameRuleValue var2 = (GameRuleValue) this.theGameRules.get(par1Str);
+ return var2 != null ? var2.getGameRuleBooleanValue() : false;
+ }
+
+ /**
+ * Return the defined game rules as NBT.
+ */
+ public NBTTagCompound writeGameRulesToNBT() {
+ NBTTagCompound var1 = new NBTTagCompound("GameRules");
+ Iterator var2 = this.theGameRules.keySet().iterator();
+
+ while (var2.hasNext()) {
+ String var3 = (String) var2.next();
+ GameRuleValue var4 = (GameRuleValue) this.theGameRules.get(var3);
+ var1.setString(var3, var4.getGameRuleStringValue());
+ }
+
+ return var1;
+ }
+
+ /**
+ * Set defined game rules from NBT.
+ */
+ public void readGameRulesFromNBT(NBTTagCompound par1NBTTagCompound) {
+ Collection var2 = par1NBTTagCompound.getTags();
+ Iterator var3 = var2.iterator();
+
+ while (var3.hasNext()) {
+ NBTBase var4 = (NBTBase) var3.next();
+ String var5 = var4.getName();
+ String var6 = par1NBTTagCompound.getString(var4.getName());
+ this.setOrCreateGameRule(var5, var6);
+ }
+ }
+
+ /**
+ * Return the defined game rules.
+ */
+ public String[] getRules() {
+ return (String[]) this.theGameRules.keySet().toArray(new String[0]);
+ }
+
+ /**
+ * Return whether the specified game rule is defined.
+ */
+ public boolean hasRule(String par1Str) {
+ return this.theGameRules.containsKey(par1Str);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/GenLayer.java b/sp-server/src/main/java/net/minecraft/src/GenLayer.java
new file mode 100644
index 0000000..0162de9
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/GenLayer.java
@@ -0,0 +1,141 @@
+package net.minecraft.src;
+
+public abstract class GenLayer {
+ /** seed from World#getWorldSeed that is used in the LCG prng */
+ private long worldGenSeed;
+
+ /** parent GenLayer that was provided via the constructor */
+ protected GenLayer parent;
+
+ /**
+ * final part of the LCG prng that uses the chunk X, Z coords along with the
+ * other two seeds to generate pseudorandom numbers
+ */
+ private long chunkSeed;
+
+ /** base seed to the LCG prng provided via the constructor */
+ private long baseSeed;
+
+ /**
+ * the first array item is a linked list of the bioms, the second is the zoom
+ * function, the third is the same as the first.
+ */
+ public static GenLayer[] initializeAllBiomeGenerators(long par0, WorldType par2WorldType) {
+ GenLayerIsland var3 = new GenLayerIsland(1L);
+ GenLayerFuzzyZoom var9 = new GenLayerFuzzyZoom(2000L, var3);
+ GenLayerAddIsland var10 = new GenLayerAddIsland(1L, var9);
+ GenLayerZoom var11 = new GenLayerZoom(2001L, var10);
+ var10 = new GenLayerAddIsland(2L, var11);
+ GenLayerAddSnow var12 = new GenLayerAddSnow(2L, var10);
+ var11 = new GenLayerZoom(2002L, var12);
+ var10 = new GenLayerAddIsland(3L, var11);
+ var11 = new GenLayerZoom(2003L, var10);
+ var10 = new GenLayerAddIsland(4L, var11);
+ GenLayerAddMushroomIsland var15 = new GenLayerAddMushroomIsland(5L, var10);
+ byte var4 = 4;
+
+ if (par2WorldType == WorldType.LARGE_BIOMES) {
+ var4 = 6;
+ }
+
+ GenLayer var5 = GenLayerZoom.magnify(1000L, var15, 0);
+ GenLayerRiverInit var13 = new GenLayerRiverInit(100L, var5);
+ var5 = GenLayerZoom.magnify(1000L, var13, var4 + 2);
+ GenLayerRiver var14 = new GenLayerRiver(1L, var5);
+ GenLayerSmooth var16 = new GenLayerSmooth(1000L, var14);
+ GenLayer var6 = GenLayerZoom.magnify(1000L, var15, 0);
+ GenLayerBiome var17 = new GenLayerBiome(200L, var6, par2WorldType);
+ var6 = GenLayerZoom.magnify(1000L, var17, 2);
+ Object var18 = new GenLayerHills(1000L, var6);
+
+ for (int var7 = 0; var7 < var4; ++var7) {
+ var18 = new GenLayerZoom((long) (1000 + var7), (GenLayer) var18);
+
+ if (var7 == 0) {
+ var18 = new GenLayerAddIsland(3L, (GenLayer) var18);
+ }
+
+ if (var7 == 1) {
+ var18 = new GenLayerShore(1000L, (GenLayer) var18);
+ }
+
+ if (var7 == 1) {
+ var18 = new GenLayerSwampRivers(1000L, (GenLayer) var18);
+ }
+ }
+
+ GenLayerSmooth var19 = new GenLayerSmooth(1000L, (GenLayer) var18);
+ GenLayerRiverMix var20 = new GenLayerRiverMix(100L, var19, var16);
+ GenLayerVoronoiZoom var8 = new GenLayerVoronoiZoom(10L, var20);
+ var20.initWorldGenSeed(par0);
+ var8.initWorldGenSeed(par0);
+ return new GenLayer[] { var20, var8, var20 };
+ }
+
+ public GenLayer(long par1) {
+ this.baseSeed = par1;
+ this.baseSeed *= this.baseSeed * 6364136223846793005L + 1442695040888963407L;
+ this.baseSeed += par1;
+ this.baseSeed *= this.baseSeed * 6364136223846793005L + 1442695040888963407L;
+ this.baseSeed += par1;
+ this.baseSeed *= this.baseSeed * 6364136223846793005L + 1442695040888963407L;
+ this.baseSeed += par1;
+ }
+
+ /**
+ * Initialize layer's local worldGenSeed based on its own baseSeed and the
+ * world's global seed (passed in as an argument).
+ */
+ public void initWorldGenSeed(long par1) {
+ this.worldGenSeed = par1;
+
+ if (this.parent != null) {
+ this.parent.initWorldGenSeed(par1);
+ }
+
+ this.worldGenSeed *= this.worldGenSeed * 6364136223846793005L + 1442695040888963407L;
+ this.worldGenSeed += this.baseSeed;
+ this.worldGenSeed *= this.worldGenSeed * 6364136223846793005L + 1442695040888963407L;
+ this.worldGenSeed += this.baseSeed;
+ this.worldGenSeed *= this.worldGenSeed * 6364136223846793005L + 1442695040888963407L;
+ this.worldGenSeed += this.baseSeed;
+ }
+
+ /**
+ * Initialize layer's current chunkSeed based on the local worldGenSeed and the
+ * (x,z) chunk coordinates.
+ */
+ public void initChunkSeed(long par1, long par3) {
+ this.chunkSeed = this.worldGenSeed;
+ this.chunkSeed *= this.chunkSeed * 6364136223846793005L + 1442695040888963407L;
+ this.chunkSeed += par1;
+ this.chunkSeed *= this.chunkSeed * 6364136223846793005L + 1442695040888963407L;
+ this.chunkSeed += par3;
+ this.chunkSeed *= this.chunkSeed * 6364136223846793005L + 1442695040888963407L;
+ this.chunkSeed += par1;
+ this.chunkSeed *= this.chunkSeed * 6364136223846793005L + 1442695040888963407L;
+ this.chunkSeed += par3;
+ }
+
+ /**
+ * returns a LCG pseudo random number from [0, x). Args: int x
+ */
+ protected int nextInt(int par1) {
+ int var2 = (int) ((this.chunkSeed >> 24) % (long) par1);
+
+ if (var2 < 0) {
+ var2 += par1;
+ }
+
+ this.chunkSeed *= this.chunkSeed * 6364136223846793005L + 1442695040888963407L;
+ this.chunkSeed += this.worldGenSeed;
+ return var2;
+ }
+
+ /**
+ * Returns a list of integer values generated by this layer. These may be
+ * interpreted as temperatures, rainfall amounts, or biomeList[] indices based
+ * on the particular GenLayer subclass.
+ */
+ public abstract int[] getInts(int var1, int var2, int var3, int var4);
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/GenLayerAddIsland.java b/sp-server/src/main/java/net/minecraft/src/GenLayerAddIsland.java
new file mode 100644
index 0000000..021f47b
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/GenLayerAddIsland.java
@@ -0,0 +1,76 @@
+package net.minecraft.src;
+
+public class GenLayerAddIsland extends GenLayer {
+ public GenLayerAddIsland(long par1, GenLayer par3GenLayer) {
+ super(par1);
+ this.parent = par3GenLayer;
+ }
+
+ /**
+ * Returns a list of integer values generated by this layer. These may be
+ * interpreted as temperatures, rainfall amounts, or biomeList[] indices based
+ * on the particular GenLayer subclass.
+ */
+ public int[] getInts(int par1, int par2, int par3, int par4) {
+ int var5 = par1 - 1;
+ int var6 = par2 - 1;
+ int var7 = par3 + 2;
+ int var8 = par4 + 2;
+ int[] var9 = this.parent.getInts(var5, var6, var7, var8);
+ int[] var10 = IntCache.getIntCache(par3 * par4);
+
+ for (int var11 = 0; var11 < par4; ++var11) {
+ for (int var12 = 0; var12 < par3; ++var12) {
+ int var13 = var9[var12 + 0 + (var11 + 0) * var7];
+ int var14 = var9[var12 + 2 + (var11 + 0) * var7];
+ int var15 = var9[var12 + 0 + (var11 + 2) * var7];
+ int var16 = var9[var12 + 2 + (var11 + 2) * var7];
+ int var17 = var9[var12 + 1 + (var11 + 1) * var7];
+ this.initChunkSeed((long) (var12 + par1), (long) (var11 + par2));
+
+ if (var17 == 0 && (var13 != 0 || var14 != 0 || var15 != 0 || var16 != 0)) {
+ int var18 = 1;
+ int var19 = 1;
+
+ if (var13 != 0 && this.nextInt(var18++) == 0) {
+ var19 = var13;
+ }
+
+ if (var14 != 0 && this.nextInt(var18++) == 0) {
+ var19 = var14;
+ }
+
+ if (var15 != 0 && this.nextInt(var18++) == 0) {
+ var19 = var15;
+ }
+
+ if (var16 != 0 && this.nextInt(var18++) == 0) {
+ var19 = var16;
+ }
+
+ if (this.nextInt(3) == 0) {
+ var10[var12 + var11 * par3] = var19;
+ } else if (var19 == BiomeGenBase.icePlains.biomeID) {
+ var10[var12 + var11 * par3] = BiomeGenBase.frozenOcean.biomeID;
+ } else {
+ var10[var12 + var11 * par3] = 0;
+ }
+ } else if (var17 > 0 && (var13 == 0 || var14 == 0 || var15 == 0 || var16 == 0)) {
+ if (this.nextInt(5) == 0) {
+ if (var17 == BiomeGenBase.icePlains.biomeID) {
+ var10[var12 + var11 * par3] = BiomeGenBase.frozenOcean.biomeID;
+ } else {
+ var10[var12 + var11 * par3] = 0;
+ }
+ } else {
+ var10[var12 + var11 * par3] = var17;
+ }
+ } else {
+ var10[var12 + var11 * par3] = var17;
+ }
+ }
+ }
+
+ return var10;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/GenLayerAddMushroomIsland.java b/sp-server/src/main/java/net/minecraft/src/GenLayerAddMushroomIsland.java
new file mode 100644
index 0000000..549db3b
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/GenLayerAddMushroomIsland.java
@@ -0,0 +1,41 @@
+package net.minecraft.src;
+
+public class GenLayerAddMushroomIsland extends GenLayer {
+ public GenLayerAddMushroomIsland(long par1, GenLayer par3GenLayer) {
+ super(par1);
+ this.parent = par3GenLayer;
+ }
+
+ /**
+ * Returns a list of integer values generated by this layer. These may be
+ * interpreted as temperatures, rainfall amounts, or biomeList[] indices based
+ * on the particular GenLayer subclass.
+ */
+ public int[] getInts(int par1, int par2, int par3, int par4) {
+ int var5 = par1 - 1;
+ int var6 = par2 - 1;
+ int var7 = par3 + 2;
+ int var8 = par4 + 2;
+ int[] var9 = this.parent.getInts(var5, var6, var7, var8);
+ int[] var10 = IntCache.getIntCache(par3 * par4);
+
+ for (int var11 = 0; var11 < par4; ++var11) {
+ for (int var12 = 0; var12 < par3; ++var12) {
+ int var13 = var9[var12 + 0 + (var11 + 0) * var7];
+ int var14 = var9[var12 + 2 + (var11 + 0) * var7];
+ int var15 = var9[var12 + 0 + (var11 + 2) * var7];
+ int var16 = var9[var12 + 2 + (var11 + 2) * var7];
+ int var17 = var9[var12 + 1 + (var11 + 1) * var7];
+ this.initChunkSeed((long) (var12 + par1), (long) (var11 + par2));
+
+ if (var17 == 0 && var13 == 0 && var14 == 0 && var15 == 0 && var16 == 0 && this.nextInt(100) == 0) {
+ var10[var12 + var11 * par3] = BiomeGenBase.mushroomIsland.biomeID;
+ } else {
+ var10[var12 + var11 * par3] = var17;
+ }
+ }
+ }
+
+ return var10;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/GenLayerAddSnow.java b/sp-server/src/main/java/net/minecraft/src/GenLayerAddSnow.java
new file mode 100644
index 0000000..902ee11
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/GenLayerAddSnow.java
@@ -0,0 +1,45 @@
+package net.minecraft.src;
+
+public class GenLayerAddSnow extends GenLayer {
+ public GenLayerAddSnow(long par1, GenLayer par3GenLayer) {
+ super(par1);
+ this.parent = par3GenLayer;
+ }
+
+ /**
+ * Returns a list of integer values generated by this layer. These may be
+ * interpreted as temperatures, rainfall amounts, or biomeList[] indices based
+ * on the particular GenLayer subclass.
+ */
+ public int[] getInts(int par1, int par2, int par3, int par4) {
+ int var5 = par1 - 1;
+ int var6 = par2 - 1;
+ int var7 = par3 + 2;
+ int var8 = par4 + 2;
+ int[] var9 = this.parent.getInts(var5, var6, var7, var8);
+ int[] var10 = IntCache.getIntCache(par3 * par4);
+
+ for (int var11 = 0; var11 < par4; ++var11) {
+ for (int var12 = 0; var12 < par3; ++var12) {
+ int var13 = var9[var12 + 1 + (var11 + 1) * var7];
+ this.initChunkSeed((long) (var12 + par1), (long) (var11 + par2));
+
+ if (var13 == 0) {
+ var10[var12 + var11 * par3] = 0;
+ } else {
+ int var14 = this.nextInt(5);
+
+ if (var14 == 0) {
+ var14 = BiomeGenBase.icePlains.biomeID;
+ } else {
+ var14 = 1;
+ }
+
+ var10[var12 + var11 * par3] = var14;
+ }
+ }
+ }
+
+ return var10;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/GenLayerBiome.java b/sp-server/src/main/java/net/minecraft/src/GenLayerBiome.java
new file mode 100644
index 0000000..8cc27be
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/GenLayerBiome.java
@@ -0,0 +1,53 @@
+package net.minecraft.src;
+
+public class GenLayerBiome extends GenLayer {
+ /** this sets all the biomes that are allowed to appear in the overworld */
+ private BiomeGenBase[] allowedBiomes;
+
+ public GenLayerBiome(long par1, GenLayer par3GenLayer, WorldType par4WorldType) {
+ super(par1);
+ this.allowedBiomes = new BiomeGenBase[] { BiomeGenBase.desert, BiomeGenBase.forest, BiomeGenBase.extremeHills,
+ BiomeGenBase.swampland, BiomeGenBase.plains, BiomeGenBase.taiga, BiomeGenBase.jungle };
+ this.parent = par3GenLayer;
+
+ if (par4WorldType == WorldType.DEFAULT_1_1) {
+ this.allowedBiomes = new BiomeGenBase[] { BiomeGenBase.desert, BiomeGenBase.forest,
+ BiomeGenBase.extremeHills, BiomeGenBase.swampland, BiomeGenBase.plains, BiomeGenBase.taiga };
+ }
+ }
+
+ /**
+ * Returns a list of integer values generated by this layer. These may be
+ * interpreted as temperatures, rainfall amounts, or biomeList[] indices based
+ * on the particular GenLayer subclass.
+ */
+ public int[] getInts(int par1, int par2, int par3, int par4) {
+ int[] var5 = this.parent.getInts(par1, par2, par3, par4);
+ int[] var6 = IntCache.getIntCache(par3 * par4);
+
+ for (int var7 = 0; var7 < par4; ++var7) {
+ for (int var8 = 0; var8 < par3; ++var8) {
+ this.initChunkSeed((long) (var8 + par1), (long) (var7 + par2));
+ int var9 = var5[var8 + var7 * par3];
+
+ if (var9 == 0) {
+ var6[var8 + var7 * par3] = 0;
+ } else if (var9 == BiomeGenBase.mushroomIsland.biomeID) {
+ var6[var8 + var7 * par3] = var9;
+ } else if (var9 == 1) {
+ var6[var8 + var7 * par3] = this.allowedBiomes[this.nextInt(this.allowedBiomes.length)].biomeID;
+ } else {
+ int var10 = this.allowedBiomes[this.nextInt(this.allowedBiomes.length)].biomeID;
+
+ if (var10 == BiomeGenBase.taiga.biomeID) {
+ var6[var8 + var7 * par3] = var10;
+ } else {
+ var6[var8 + var7 * par3] = BiomeGenBase.icePlains.biomeID;
+ }
+ }
+ }
+ }
+
+ return var6;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/GenLayerFuzzyZoom.java b/sp-server/src/main/java/net/minecraft/src/GenLayerFuzzyZoom.java
new file mode 100644
index 0000000..7b3bb56
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/GenLayerFuzzyZoom.java
@@ -0,0 +1,66 @@
+package net.minecraft.src;
+
+public class GenLayerFuzzyZoom extends GenLayer {
+ public GenLayerFuzzyZoom(long par1, GenLayer par3GenLayer) {
+ super(par1);
+ super.parent = par3GenLayer;
+ }
+
+ /**
+ * Returns a list of integer values generated by this layer. These may be
+ * interpreted as temperatures, rainfall amounts, or biomeList[] indices based
+ * on the particular GenLayer subclass.
+ */
+ public int[] getInts(int par1, int par2, int par3, int par4) {
+ int var5 = par1 >> 1;
+ int var6 = par2 >> 1;
+ int var7 = (par3 >> 1) + 3;
+ int var8 = (par4 >> 1) + 3;
+ int[] var9 = this.parent.getInts(var5, var6, var7, var8);
+ int[] var10 = IntCache.getIntCache(var7 * 2 * var8 * 2);
+ int var11 = var7 << 1;
+ int var13;
+
+ for (int var12 = 0; var12 < var8 - 1; ++var12) {
+ var13 = var12 << 1;
+ int var14 = var13 * var11;
+ int var15 = var9[0 + (var12 + 0) * var7];
+ int var16 = var9[0 + (var12 + 1) * var7];
+
+ for (int var17 = 0; var17 < var7 - 1; ++var17) {
+ this.initChunkSeed((long) (var17 + var5 << 1), (long) (var12 + var6 << 1));
+ int var18 = var9[var17 + 1 + (var12 + 0) * var7];
+ int var19 = var9[var17 + 1 + (var12 + 1) * var7];
+ var10[var14] = var15;
+ var10[var14++ + var11] = this.choose(var15, var16);
+ var10[var14] = this.choose(var15, var18);
+ var10[var14++ + var11] = this.choose(var15, var18, var16, var19);
+ var15 = var18;
+ var16 = var19;
+ }
+ }
+
+ int[] var20 = IntCache.getIntCache(par3 * par4);
+
+ for (var13 = 0; var13 < par4; ++var13) {
+ System.arraycopy(var10, (var13 + (par2 & 1)) * (var7 << 1) + (par1 & 1), var20, var13 * par3, par3);
+ }
+
+ return var20;
+ }
+
+ /**
+ * randomly choose between the two args
+ */
+ protected int choose(int par1, int par2) {
+ return this.nextInt(2) == 0 ? par1 : par2;
+ }
+
+ /**
+ * randomly choose between the four args
+ */
+ protected int choose(int par1, int par2, int par3, int par4) {
+ int var5 = this.nextInt(4);
+ return var5 == 0 ? par1 : (var5 == 1 ? par2 : (var5 == 2 ? par3 : par4));
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/GenLayerHills.java b/sp-server/src/main/java/net/minecraft/src/GenLayerHills.java
new file mode 100644
index 0000000..bfa0c74
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/GenLayerHills.java
@@ -0,0 +1,62 @@
+package net.minecraft.src;
+
+public class GenLayerHills extends GenLayer {
+ public GenLayerHills(long par1, GenLayer par3GenLayer) {
+ super(par1);
+ this.parent = par3GenLayer;
+ }
+
+ /**
+ * Returns a list of integer values generated by this layer. These may be
+ * interpreted as temperatures, rainfall amounts, or biomeList[] indices based
+ * on the particular GenLayer subclass.
+ */
+ public int[] getInts(int par1, int par2, int par3, int par4) {
+ int[] var5 = this.parent.getInts(par1 - 1, par2 - 1, par3 + 2, par4 + 2);
+ int[] var6 = IntCache.getIntCache(par3 * par4);
+
+ for (int var7 = 0; var7 < par4; ++var7) {
+ for (int var8 = 0; var8 < par3; ++var8) {
+ this.initChunkSeed((long) (var8 + par1), (long) (var7 + par2));
+ int var9 = var5[var8 + 1 + (var7 + 1) * (par3 + 2)];
+
+ if (this.nextInt(3) == 0) {
+ int var10 = var9;
+
+ if (var9 == BiomeGenBase.desert.biomeID) {
+ var10 = BiomeGenBase.desertHills.biomeID;
+ } else if (var9 == BiomeGenBase.forest.biomeID) {
+ var10 = BiomeGenBase.forestHills.biomeID;
+ } else if (var9 == BiomeGenBase.taiga.biomeID) {
+ var10 = BiomeGenBase.taigaHills.biomeID;
+ } else if (var9 == BiomeGenBase.plains.biomeID) {
+ var10 = BiomeGenBase.forest.biomeID;
+ } else if (var9 == BiomeGenBase.icePlains.biomeID) {
+ var10 = BiomeGenBase.iceMountains.biomeID;
+ } else if (var9 == BiomeGenBase.jungle.biomeID) {
+ var10 = BiomeGenBase.jungleHills.biomeID;
+ }
+
+ if (var10 == var9) {
+ var6[var8 + var7 * par3] = var9;
+ } else {
+ int var11 = var5[var8 + 1 + (var7 + 1 - 1) * (par3 + 2)];
+ int var12 = var5[var8 + 1 + 1 + (var7 + 1) * (par3 + 2)];
+ int var13 = var5[var8 + 1 - 1 + (var7 + 1) * (par3 + 2)];
+ int var14 = var5[var8 + 1 + (var7 + 1 + 1) * (par3 + 2)];
+
+ if (var11 == var9 && var12 == var9 && var13 == var9 && var14 == var9) {
+ var6[var8 + var7 * par3] = var10;
+ } else {
+ var6[var8 + var7 * par3] = var9;
+ }
+ }
+ } else {
+ var6[var8 + var7 * par3] = var9;
+ }
+ }
+ }
+
+ return var6;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/GenLayerIsland.java b/sp-server/src/main/java/net/minecraft/src/GenLayerIsland.java
new file mode 100644
index 0000000..40e815a
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/GenLayerIsland.java
@@ -0,0 +1,29 @@
+package net.minecraft.src;
+
+public class GenLayerIsland extends GenLayer {
+ public GenLayerIsland(long par1) {
+ super(par1);
+ }
+
+ /**
+ * Returns a list of integer values generated by this layer. These may be
+ * interpreted as temperatures, rainfall amounts, or biomeList[] indices based
+ * on the particular GenLayer subclass.
+ */
+ public int[] getInts(int par1, int par2, int par3, int par4) {
+ int[] var5 = IntCache.getIntCache(par3 * par4);
+
+ for (int var6 = 0; var6 < par4; ++var6) {
+ for (int var7 = 0; var7 < par3; ++var7) {
+ this.initChunkSeed((long) (par1 + var7), (long) (par2 + var6));
+ var5[var7 + var6 * par3] = this.nextInt(10) == 0 ? 1 : 0;
+ }
+ }
+
+ if (par1 > -par3 && par1 <= 0 && par2 > -par4 && par2 <= 0) {
+ var5[-par1 + -par2 * par3] = 1;
+ }
+
+ return var5;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/GenLayerRiver.java b/sp-server/src/main/java/net/minecraft/src/GenLayerRiver.java
new file mode 100644
index 0000000..56b8081
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/GenLayerRiver.java
@@ -0,0 +1,41 @@
+package net.minecraft.src;
+
+public class GenLayerRiver extends GenLayer {
+ public GenLayerRiver(long par1, GenLayer par3GenLayer) {
+ super(par1);
+ super.parent = par3GenLayer;
+ }
+
+ /**
+ * Returns a list of integer values generated by this layer. These may be
+ * interpreted as temperatures, rainfall amounts, or biomeList[] indices based
+ * on the particular GenLayer subclass.
+ */
+ public int[] getInts(int par1, int par2, int par3, int par4) {
+ int var5 = par1 - 1;
+ int var6 = par2 - 1;
+ int var7 = par3 + 2;
+ int var8 = par4 + 2;
+ int[] var9 = this.parent.getInts(var5, var6, var7, var8);
+ int[] var10 = IntCache.getIntCache(par3 * par4);
+
+ for (int var11 = 0; var11 < par4; ++var11) {
+ for (int var12 = 0; var12 < par3; ++var12) {
+ int var13 = var9[var12 + 0 + (var11 + 1) * var7];
+ int var14 = var9[var12 + 2 + (var11 + 1) * var7];
+ int var15 = var9[var12 + 1 + (var11 + 0) * var7];
+ int var16 = var9[var12 + 1 + (var11 + 2) * var7];
+ int var17 = var9[var12 + 1 + (var11 + 1) * var7];
+
+ if (var17 != 0 && var13 != 0 && var14 != 0 && var15 != 0 && var16 != 0 && var17 == var13
+ && var17 == var15 && var17 == var14 && var17 == var16) {
+ var10[var12 + var11 * par3] = -1;
+ } else {
+ var10[var12 + var11 * par3] = BiomeGenBase.river.biomeID;
+ }
+ }
+ }
+
+ return var10;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/GenLayerRiverInit.java b/sp-server/src/main/java/net/minecraft/src/GenLayerRiverInit.java
new file mode 100644
index 0000000..fa994a4
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/GenLayerRiverInit.java
@@ -0,0 +1,27 @@
+package net.minecraft.src;
+
+public class GenLayerRiverInit extends GenLayer {
+ public GenLayerRiverInit(long par1, GenLayer par3GenLayer) {
+ super(par1);
+ this.parent = par3GenLayer;
+ }
+
+ /**
+ * Returns a list of integer values generated by this layer. These may be
+ * interpreted as temperatures, rainfall amounts, or biomeList[] indices based
+ * on the particular GenLayer subclass.
+ */
+ public int[] getInts(int par1, int par2, int par3, int par4) {
+ int[] var5 = this.parent.getInts(par1, par2, par3, par4);
+ int[] var6 = IntCache.getIntCache(par3 * par4);
+
+ for (int var7 = 0; var7 < par4; ++var7) {
+ for (int var8 = 0; var8 < par3; ++var8) {
+ this.initChunkSeed((long) (var8 + par1), (long) (var7 + par2));
+ var6[var8 + var7 * par3] = var5[var8 + var7 * par3] > 0 ? this.nextInt(2) + 2 : 0;
+ }
+ }
+
+ return var6;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/GenLayerRiverMix.java b/sp-server/src/main/java/net/minecraft/src/GenLayerRiverMix.java
new file mode 100644
index 0000000..14c51d3
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/GenLayerRiverMix.java
@@ -0,0 +1,52 @@
+package net.minecraft.src;
+
+public class GenLayerRiverMix extends GenLayer {
+ private GenLayer biomePatternGeneratorChain;
+ private GenLayer riverPatternGeneratorChain;
+
+ public GenLayerRiverMix(long par1, GenLayer par3GenLayer, GenLayer par4GenLayer) {
+ super(par1);
+ this.biomePatternGeneratorChain = par3GenLayer;
+ this.riverPatternGeneratorChain = par4GenLayer;
+ }
+
+ /**
+ * Initialize layer's local worldGenSeed based on its own baseSeed and the
+ * world's global seed (passed in as an argument).
+ */
+ public void initWorldGenSeed(long par1) {
+ this.biomePatternGeneratorChain.initWorldGenSeed(par1);
+ this.riverPatternGeneratorChain.initWorldGenSeed(par1);
+ super.initWorldGenSeed(par1);
+ }
+
+ /**
+ * Returns a list of integer values generated by this layer. These may be
+ * interpreted as temperatures, rainfall amounts, or biomeList[] indices based
+ * on the particular GenLayer subclass.
+ */
+ public int[] getInts(int par1, int par2, int par3, int par4) {
+ int[] var5 = this.biomePatternGeneratorChain.getInts(par1, par2, par3, par4);
+ int[] var6 = this.riverPatternGeneratorChain.getInts(par1, par2, par3, par4);
+ int[] var7 = IntCache.getIntCache(par3 * par4);
+
+ for (int var8 = 0; var8 < par3 * par4; ++var8) {
+ if (var5[var8] == BiomeGenBase.ocean.biomeID) {
+ var7[var8] = var5[var8];
+ } else if (var6[var8] >= 0) {
+ if (var5[var8] == BiomeGenBase.icePlains.biomeID) {
+ var7[var8] = BiomeGenBase.frozenRiver.biomeID;
+ } else if (var5[var8] != BiomeGenBase.mushroomIsland.biomeID
+ && var5[var8] != BiomeGenBase.mushroomIslandShore.biomeID) {
+ var7[var8] = var6[var8];
+ } else {
+ var7[var8] = BiomeGenBase.mushroomIslandShore.biomeID;
+ }
+ } else {
+ var7[var8] = var5[var8];
+ }
+ }
+
+ return var7;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/GenLayerShore.java b/sp-server/src/main/java/net/minecraft/src/GenLayerShore.java
new file mode 100644
index 0000000..6e5f4fe
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/GenLayerShore.java
@@ -0,0 +1,73 @@
+package net.minecraft.src;
+
+public class GenLayerShore extends GenLayer {
+ public GenLayerShore(long par1, GenLayer par3GenLayer) {
+ super(par1);
+ this.parent = par3GenLayer;
+ }
+
+ /**
+ * Returns a list of integer values generated by this layer. These may be
+ * interpreted as temperatures, rainfall amounts, or biomeList[] indices based
+ * on the particular GenLayer subclass.
+ */
+ public int[] getInts(int par1, int par2, int par3, int par4) {
+ int[] var5 = this.parent.getInts(par1 - 1, par2 - 1, par3 + 2, par4 + 2);
+ int[] var6 = IntCache.getIntCache(par3 * par4);
+
+ for (int var7 = 0; var7 < par4; ++var7) {
+ for (int var8 = 0; var8 < par3; ++var8) {
+ this.initChunkSeed((long) (var8 + par1), (long) (var7 + par2));
+ int var9 = var5[var8 + 1 + (var7 + 1) * (par3 + 2)];
+ int var10;
+ int var11;
+ int var12;
+ int var13;
+
+ if (var9 == BiomeGenBase.mushroomIsland.biomeID) {
+ var10 = var5[var8 + 1 + (var7 + 1 - 1) * (par3 + 2)];
+ var11 = var5[var8 + 1 + 1 + (var7 + 1) * (par3 + 2)];
+ var12 = var5[var8 + 1 - 1 + (var7 + 1) * (par3 + 2)];
+ var13 = var5[var8 + 1 + (var7 + 1 + 1) * (par3 + 2)];
+
+ if (var10 != BiomeGenBase.ocean.biomeID && var11 != BiomeGenBase.ocean.biomeID
+ && var12 != BiomeGenBase.ocean.biomeID && var13 != BiomeGenBase.ocean.biomeID) {
+ var6[var8 + var7 * par3] = var9;
+ } else {
+ var6[var8 + var7 * par3] = BiomeGenBase.mushroomIslandShore.biomeID;
+ }
+ } else if (var9 != BiomeGenBase.ocean.biomeID && var9 != BiomeGenBase.river.biomeID
+ && var9 != BiomeGenBase.swampland.biomeID && var9 != BiomeGenBase.extremeHills.biomeID) {
+ var10 = var5[var8 + 1 + (var7 + 1 - 1) * (par3 + 2)];
+ var11 = var5[var8 + 1 + 1 + (var7 + 1) * (par3 + 2)];
+ var12 = var5[var8 + 1 - 1 + (var7 + 1) * (par3 + 2)];
+ var13 = var5[var8 + 1 + (var7 + 1 + 1) * (par3 + 2)];
+
+ if (var10 != BiomeGenBase.ocean.biomeID && var11 != BiomeGenBase.ocean.biomeID
+ && var12 != BiomeGenBase.ocean.biomeID && var13 != BiomeGenBase.ocean.biomeID) {
+ var6[var8 + var7 * par3] = var9;
+ } else {
+ var6[var8 + var7 * par3] = BiomeGenBase.beach.biomeID;
+ }
+ } else if (var9 == BiomeGenBase.extremeHills.biomeID) {
+ var10 = var5[var8 + 1 + (var7 + 1 - 1) * (par3 + 2)];
+ var11 = var5[var8 + 1 + 1 + (var7 + 1) * (par3 + 2)];
+ var12 = var5[var8 + 1 - 1 + (var7 + 1) * (par3 + 2)];
+ var13 = var5[var8 + 1 + (var7 + 1 + 1) * (par3 + 2)];
+
+ if (var10 == BiomeGenBase.extremeHills.biomeID && var11 == BiomeGenBase.extremeHills.biomeID
+ && var12 == BiomeGenBase.extremeHills.biomeID
+ && var13 == BiomeGenBase.extremeHills.biomeID) {
+ var6[var8 + var7 * par3] = var9;
+ } else {
+ var6[var8 + var7 * par3] = BiomeGenBase.extremeHillsEdge.biomeID;
+ }
+ } else {
+ var6[var8 + var7 * par3] = var9;
+ }
+ }
+ }
+
+ return var6;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/GenLayerSmooth.java b/sp-server/src/main/java/net/minecraft/src/GenLayerSmooth.java
new file mode 100644
index 0000000..9008d28
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/GenLayerSmooth.java
@@ -0,0 +1,54 @@
+package net.minecraft.src;
+
+public class GenLayerSmooth extends GenLayer {
+ public GenLayerSmooth(long par1, GenLayer par3GenLayer) {
+ super(par1);
+ super.parent = par3GenLayer;
+ }
+
+ /**
+ * Returns a list of integer values generated by this layer. These may be
+ * interpreted as temperatures, rainfall amounts, or biomeList[] indices based
+ * on the particular GenLayer subclass.
+ */
+ public int[] getInts(int par1, int par2, int par3, int par4) {
+ int var5 = par1 - 1;
+ int var6 = par2 - 1;
+ int var7 = par3 + 2;
+ int var8 = par4 + 2;
+ int[] var9 = this.parent.getInts(var5, var6, var7, var8);
+ int[] var10 = IntCache.getIntCache(par3 * par4);
+
+ for (int var11 = 0; var11 < par4; ++var11) {
+ for (int var12 = 0; var12 < par3; ++var12) {
+ int var13 = var9[var12 + 0 + (var11 + 1) * var7];
+ int var14 = var9[var12 + 2 + (var11 + 1) * var7];
+ int var15 = var9[var12 + 1 + (var11 + 0) * var7];
+ int var16 = var9[var12 + 1 + (var11 + 2) * var7];
+ int var17 = var9[var12 + 1 + (var11 + 1) * var7];
+
+ if (var13 == var14 && var15 == var16) {
+ this.initChunkSeed((long) (var12 + par1), (long) (var11 + par2));
+
+ if (this.nextInt(2) == 0) {
+ var17 = var13;
+ } else {
+ var17 = var15;
+ }
+ } else {
+ if (var13 == var14) {
+ var17 = var13;
+ }
+
+ if (var15 == var16) {
+ var17 = var15;
+ }
+ }
+
+ var10[var12 + var11 * par3] = var17;
+ }
+ }
+
+ return var10;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/GenLayerSwampRivers.java b/sp-server/src/main/java/net/minecraft/src/GenLayerSwampRivers.java
new file mode 100644
index 0000000..eef78c6
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/GenLayerSwampRivers.java
@@ -0,0 +1,35 @@
+package net.minecraft.src;
+
+public class GenLayerSwampRivers extends GenLayer {
+ public GenLayerSwampRivers(long par1, GenLayer par3GenLayer) {
+ super(par1);
+ this.parent = par3GenLayer;
+ }
+
+ /**
+ * Returns a list of integer values generated by this layer. These may be
+ * interpreted as temperatures, rainfall amounts, or biomeList[] indices based
+ * on the particular GenLayer subclass.
+ */
+ public int[] getInts(int par1, int par2, int par3, int par4) {
+ int[] var5 = this.parent.getInts(par1 - 1, par2 - 1, par3 + 2, par4 + 2);
+ int[] var6 = IntCache.getIntCache(par3 * par4);
+
+ for (int var7 = 0; var7 < par4; ++var7) {
+ for (int var8 = 0; var8 < par3; ++var8) {
+ this.initChunkSeed((long) (var8 + par1), (long) (var7 + par2));
+ int var9 = var5[var8 + 1 + (var7 + 1) * (par3 + 2)];
+
+ if ((var9 != BiomeGenBase.swampland.biomeID || this.nextInt(6) != 0)
+ && (var9 != BiomeGenBase.jungle.biomeID && var9 != BiomeGenBase.jungleHills.biomeID
+ || this.nextInt(8) != 0)) {
+ var6[var8 + var7 * par3] = var9;
+ } else {
+ var6[var8 + var7 * par3] = BiomeGenBase.river.biomeID;
+ }
+ }
+ }
+
+ return var6;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/GenLayerVoronoiZoom.java b/sp-server/src/main/java/net/minecraft/src/GenLayerVoronoiZoom.java
new file mode 100644
index 0000000..4fd5fe6
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/GenLayerVoronoiZoom.java
@@ -0,0 +1,89 @@
+package net.minecraft.src;
+
+public class GenLayerVoronoiZoom extends GenLayer {
+ public GenLayerVoronoiZoom(long par1, GenLayer par3GenLayer) {
+ super(par1);
+ super.parent = par3GenLayer;
+ }
+
+ /**
+ * Returns a list of integer values generated by this layer. These may be
+ * interpreted as temperatures, rainfall amounts, or biomeList[] indices based
+ * on the particular GenLayer subclass.
+ */
+ public int[] getInts(int par1, int par2, int par3, int par4) {
+ par1 -= 2;
+ par2 -= 2;
+ byte var5 = 2;
+ int var6 = 1 << var5;
+ int var7 = par1 >> var5;
+ int var8 = par2 >> var5;
+ int var9 = (par3 >> var5) + 3;
+ int var10 = (par4 >> var5) + 3;
+ int[] var11 = this.parent.getInts(var7, var8, var9, var10);
+ int var12 = var9 << var5;
+ int var13 = var10 << var5;
+ int[] var14 = IntCache.getIntCache(var12 * var13);
+ int var16;
+
+ for (int var15 = 0; var15 < var10 - 1; ++var15) {
+ var16 = var11[0 + (var15 + 0) * var9];
+ int var17 = var11[0 + (var15 + 1) * var9];
+
+ for (int var18 = 0; var18 < var9 - 1; ++var18) {
+ double var19 = (double) var6 * 0.9D;
+ this.initChunkSeed((long) (var18 + var7 << var5), (long) (var15 + var8 << var5));
+ double var21 = ((double) this.nextInt(1024) / 1024.0D - 0.5D) * var19;
+ double var23 = ((double) this.nextInt(1024) / 1024.0D - 0.5D) * var19;
+ this.initChunkSeed((long) (var18 + var7 + 1 << var5), (long) (var15 + var8 << var5));
+ double var25 = ((double) this.nextInt(1024) / 1024.0D - 0.5D) * var19 + (double) var6;
+ double var27 = ((double) this.nextInt(1024) / 1024.0D - 0.5D) * var19;
+ this.initChunkSeed((long) (var18 + var7 << var5), (long) (var15 + var8 + 1 << var5));
+ double var29 = ((double) this.nextInt(1024) / 1024.0D - 0.5D) * var19;
+ double var31 = ((double) this.nextInt(1024) / 1024.0D - 0.5D) * var19 + (double) var6;
+ this.initChunkSeed((long) (var18 + var7 + 1 << var5), (long) (var15 + var8 + 1 << var5));
+ double var33 = ((double) this.nextInt(1024) / 1024.0D - 0.5D) * var19 + (double) var6;
+ double var35 = ((double) this.nextInt(1024) / 1024.0D - 0.5D) * var19 + (double) var6;
+ int var37 = var11[var18 + 1 + (var15 + 0) * var9];
+ int var38 = var11[var18 + 1 + (var15 + 1) * var9];
+
+ for (int var39 = 0; var39 < var6; ++var39) {
+ int var40 = ((var15 << var5) + var39) * var12 + (var18 << var5);
+
+ for (int var41 = 0; var41 < var6; ++var41) {
+ double var42 = ((double) var39 - var23) * ((double) var39 - var23)
+ + ((double) var41 - var21) * ((double) var41 - var21);
+ double var44 = ((double) var39 - var27) * ((double) var39 - var27)
+ + ((double) var41 - var25) * ((double) var41 - var25);
+ double var46 = ((double) var39 - var31) * ((double) var39 - var31)
+ + ((double) var41 - var29) * ((double) var41 - var29);
+ double var48 = ((double) var39 - var35) * ((double) var39 - var35)
+ + ((double) var41 - var33) * ((double) var41 - var33);
+
+ if (var42 < var44 && var42 < var46 && var42 < var48) {
+ var14[var40++] = var16;
+ } else if (var44 < var42 && var44 < var46 && var44 < var48) {
+ var14[var40++] = var37;
+ } else if (var46 < var42 && var46 < var44 && var46 < var48) {
+ var14[var40++] = var17;
+ } else {
+ var14[var40++] = var38;
+ }
+ }
+ }
+
+ var16 = var37;
+ var17 = var38;
+ }
+ }
+
+ int[] var50 = IntCache.getIntCache(par3 * par4);
+
+ for (var16 = 0; var16 < par4; ++var16) {
+ System.arraycopy(var14, (var16 + (par2 & var6 - 1)) * (var9 << var5) + (par1 & var6 - 1), var50,
+ var16 * par3, par3);
+ }
+
+ return var50;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/GenLayerZoom.java b/sp-server/src/main/java/net/minecraft/src/GenLayerZoom.java
new file mode 100644
index 0000000..bac728e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/GenLayerZoom.java
@@ -0,0 +1,114 @@
+package net.minecraft.src;
+
+public class GenLayerZoom extends GenLayer {
+ public GenLayerZoom(long par1, GenLayer par3GenLayer) {
+ super(par1);
+ super.parent = par3GenLayer;
+ }
+
+ /**
+ * Returns a list of integer values generated by this layer. These may be
+ * interpreted as temperatures, rainfall amounts, or biomeList[] indices based
+ * on the particular GenLayer subclass.
+ */
+ public int[] getInts(int par1, int par2, int par3, int par4) {
+ int var5 = par1 >> 1;
+ int var6 = par2 >> 1;
+ int var7 = (par3 >> 1) + 3;
+ int var8 = (par4 >> 1) + 3;
+ int[] var9 = this.parent.getInts(var5, var6, var7, var8);
+ int[] var10 = IntCache.getIntCache(var7 * 2 * var8 * 2);
+ int var11 = var7 << 1;
+ int var13;
+
+ for (int var12 = 0; var12 < var8 - 1; ++var12) {
+ var13 = var12 << 1;
+ int var14 = var13 * var11;
+ int var15 = var9[0 + (var12 + 0) * var7];
+ int var16 = var9[0 + (var12 + 1) * var7];
+
+ for (int var17 = 0; var17 < var7 - 1; ++var17) {
+ this.initChunkSeed((long) (var17 + var5 << 1), (long) (var12 + var6 << 1));
+ int var18 = var9[var17 + 1 + (var12 + 0) * var7];
+ int var19 = var9[var17 + 1 + (var12 + 1) * var7];
+ var10[var14] = var15;
+ var10[var14++ + var11] = this.choose(var15, var16);
+ var10[var14] = this.choose(var15, var18);
+ var10[var14++ + var11] = this.modeOrRandom(var15, var18, var16, var19);
+ var15 = var18;
+ var16 = var19;
+ }
+ }
+
+ int[] var20 = IntCache.getIntCache(par3 * par4);
+
+ for (var13 = 0; var13 < par4; ++var13) {
+ System.arraycopy(var10, (var13 + (par2 & 1)) * (var7 << 1) + (par1 & 1), var20, var13 * par3, par3);
+ }
+
+ return var20;
+ }
+
+ /**
+ * Chooses one of the two inputs randomly.
+ */
+ protected int choose(int par1, int par2) {
+ return this.nextInt(2) == 0 ? par1 : par2;
+ }
+
+ /**
+ * returns the mode (most frequently occuring number) or a random number from
+ * the 4 integers provided
+ */
+ protected int modeOrRandom(int par1, int par2, int par3, int par4) {
+ if (par2 == par3 && par3 == par4) {
+ return par2;
+ } else if (par1 == par2 && par1 == par3) {
+ return par1;
+ } else if (par1 == par2 && par1 == par4) {
+ return par1;
+ } else if (par1 == par3 && par1 == par4) {
+ return par1;
+ } else if (par1 == par2 && par3 != par4) {
+ return par1;
+ } else if (par1 == par3 && par2 != par4) {
+ return par1;
+ } else if (par1 == par4 && par2 != par3) {
+ return par1;
+ } else if (par2 == par1 && par3 != par4) {
+ return par2;
+ } else if (par2 == par3 && par1 != par4) {
+ return par2;
+ } else if (par2 == par4 && par1 != par3) {
+ return par2;
+ } else if (par3 == par1 && par2 != par4) {
+ return par3;
+ } else if (par3 == par2 && par1 != par4) {
+ return par3;
+ } else if (par3 == par4 && par1 != par2) {
+ return par3;
+ } else if (par4 == par1 && par2 != par3) {
+ return par3;
+ } else if (par4 == par2 && par1 != par3) {
+ return par3;
+ } else if (par4 == par3 && par1 != par2) {
+ return par3;
+ } else {
+ int var5 = this.nextInt(4);
+ return var5 == 0 ? par1 : (var5 == 1 ? par2 : (var5 == 2 ? par3 : par4));
+ }
+ }
+
+ /**
+ * Magnify a layer. Parms are seed adjustment, layer, number of times to magnify
+ */
+ public static GenLayer magnify(long par0, GenLayer par2GenLayer, int par3) {
+ Object var4 = par2GenLayer;
+
+ for (int var5 = 0; var5 < par3; ++var5) {
+ var4 = new GenLayerZoom(par0 + (long) var5, (GenLayer) var4);
+ }
+
+ return (GenLayer) var4;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Hopper.java b/sp-server/src/main/java/net/minecraft/src/Hopper.java
new file mode 100644
index 0000000..c4ac379
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Hopper.java
@@ -0,0 +1,23 @@
+package net.minecraft.src;
+
+public interface Hopper extends IInventory {
+ /**
+ * Returns the worldObj for this tileEntity.
+ */
+ World getWorldObj();
+
+ /**
+ * Gets the world X position for this hopper entity.
+ */
+ double getXPos();
+
+ /**
+ * Gets the world Y position for this hopper entity.
+ */
+ double getYPos();
+
+ /**
+ * Gets the world Z position for this hopper entity.
+ */
+ double getZPos();
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/IAdminCommand.java b/sp-server/src/main/java/net/minecraft/src/IAdminCommand.java
new file mode 100644
index 0000000..94465e5
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/IAdminCommand.java
@@ -0,0 +1,10 @@
+package net.minecraft.src;
+
+public interface IAdminCommand {
+ /**
+ * Sends a message to the admins of the server from a given CommandSender with
+ * the given resource string and given extra srings. If the int par2 is even or
+ * zero, the original sender is also notified.
+ */
+ void notifyAdmins(ICommandSender var1, int var2, String var3, Object... var4);
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/IAnimals.java b/sp-server/src/main/java/net/minecraft/src/IAnimals.java
new file mode 100644
index 0000000..61de5b0
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/IAnimals.java
@@ -0,0 +1,4 @@
+package net.minecraft.src;
+
+public interface IAnimals {
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/IBehaviorDispenseItem.java b/sp-server/src/main/java/net/minecraft/src/IBehaviorDispenseItem.java
new file mode 100644
index 0000000..fe66e91
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/IBehaviorDispenseItem.java
@@ -0,0 +1,10 @@
+package net.minecraft.src;
+
+public interface IBehaviorDispenseItem {
+ IBehaviorDispenseItem itemDispenseBehaviorProvider = new BehaviorDispenseItemProvider();
+
+ /**
+ * Dispenses the specified ItemStack from a dispenser.
+ */
+ ItemStack dispense(IBlockSource var1, ItemStack var2);
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/IBlockAccess.java b/sp-server/src/main/java/net/minecraft/src/IBlockAccess.java
new file mode 100644
index 0000000..72a764b
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/IBlockAccess.java
@@ -0,0 +1,40 @@
+package net.minecraft.src;
+
+public interface IBlockAccess {
+ /**
+ * Returns the block ID at coords x,y,z
+ */
+ int getBlockId(int var1, int var2, int var3);
+
+ /**
+ * Returns the TileEntity associated with a given block in X,Y,Z coordinates, or
+ * null if no TileEntity exists
+ */
+ TileEntity getBlockTileEntity(int var1, int var2, int var3);
+
+ /**
+ * Returns the block metadata at coords x,y,z
+ */
+ int getBlockMetadata(int var1, int var2, int var3);
+
+ /**
+ * Returns the block's material.
+ */
+ Material getBlockMaterial(int var1, int var2, int var3);
+
+ /**
+ * Returns true if the block at the specified coordinates is an opaque cube.
+ * Args: x, y, z
+ */
+ boolean isBlockNormalCube(int var1, int var2, int var3);
+
+ /**
+ * Return the Vec3Pool object for this world.
+ */
+ Vec3Pool getWorldVec3Pool();
+
+ /**
+ * Is this block powering in the specified direction Args: x, y, z, direction
+ */
+ int isBlockProvidingPowerTo(int var1, int var2, int var3, int var4);
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/IBlockSource.java b/sp-server/src/main/java/net/minecraft/src/IBlockSource.java
new file mode 100644
index 0000000..40e788d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/IBlockSource.java
@@ -0,0 +1,19 @@
+package net.minecraft.src;
+
+public interface IBlockSource extends ILocatableSource {
+ double getX();
+
+ double getY();
+
+ double getZ();
+
+ int getXInt();
+
+ int getYInt();
+
+ int getZInt();
+
+ int getBlockMetadata();
+
+ TileEntity getBlockTileEntity();
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/IChunkLoader.java b/sp-server/src/main/java/net/minecraft/src/IChunkLoader.java
new file mode 100644
index 0000000..b788f32
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/IChunkLoader.java
@@ -0,0 +1,29 @@
+package net.minecraft.src;
+
+import java.io.IOException;
+
+public interface IChunkLoader {
+ /**
+ * Loads the specified(XZ) chunk into the specified world.
+ */
+ Chunk loadChunk(World var1, int var2, int var3) throws IOException;
+
+ void saveChunk(World var1, Chunk var2) throws MinecraftException, IOException;
+
+ /**
+ * Save extra data associated with this Chunk not normally saved during
+ * autosave, only during chunk unload. Currently unused.
+ */
+ void saveExtraChunkData(World var1, Chunk var2);
+
+ /**
+ * Called every World.tick()
+ */
+ void chunkTick();
+
+ /**
+ * Save extra data not associated with any Chunk. Not saved during autosave,
+ * only during world unload. Currently unused.
+ */
+ void saveExtraData();
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/IChunkProvider.java b/sp-server/src/main/java/net/minecraft/src/IChunkProvider.java
new file mode 100644
index 0000000..2c8746a
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/IChunkProvider.java
@@ -0,0 +1,67 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+public interface IChunkProvider {
+ /**
+ * Checks to see if a chunk exists at x, y
+ */
+ boolean chunkExists(int var1, int var2);
+
+ /**
+ * Will return back a chunk, if it doesn't exist and its not a MP client it will
+ * generates all the blocks for the specified chunk from the map seed and chunk
+ * seed
+ */
+ Chunk provideChunk(int var1, int var2);
+
+ /**
+ * loads or generates the chunk at the chunk location specified
+ */
+ Chunk loadChunk(int var1, int var2);
+
+ /**
+ * Populates chunk with ores etc etc
+ */
+ void populate(IChunkProvider var1, int var2, int var3);
+
+ /**
+ * Two modes of operation: if passed true, save all Chunks in one go. If passed
+ * false, save up to two chunks. Return true if all chunks have been saved.
+ */
+ boolean saveChunks(boolean var1, IProgressUpdate var2);
+
+ /**
+ * Unloads chunks that are marked to be unloaded. This is not guaranteed to
+ * unload every such chunk.
+ */
+ boolean unloadQueuedChunks();
+
+ /**
+ * Returns if the IChunkProvider supports saving.
+ */
+ boolean canSave();
+
+ /**
+ * Converts the instance data to a readable string.
+ */
+ String makeString();
+
+ /**
+ * Returns a list of creatures of the specified type that can spawn at the given
+ * location.
+ */
+ List getPossibleCreatures(EnumCreatureType var1, int var2, int var3, int var4);
+
+ /**
+ * Returns the location of the closest structure of the specified type. If not
+ * found returns null.
+ */
+ ChunkPosition findClosestStructure(World var1, String var2, int var3, int var4, int var5);
+
+ int getLoadedChunkCount();
+
+ void recreateStructures(int var1, int var2);
+
+ void func_104112_b();
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ICommand.java b/sp-server/src/main/java/net/minecraft/src/ICommand.java
new file mode 100644
index 0000000..c990bb2
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ICommand.java
@@ -0,0 +1,29 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+public interface ICommand extends Comparable {
+ String getCommandName();
+
+ String getCommandUsage(ICommandSender var1);
+
+ List getCommandAliases();
+
+ void processCommand(ICommandSender var1, String[] var2);
+
+ /**
+ * Returns true if the given command sender is allowed to use this command.
+ */
+ boolean canCommandSenderUseCommand(ICommandSender var1);
+
+ /**
+ * Adds the strings available in this command to the given list of tab
+ * completion options.
+ */
+ List addTabCompletionOptions(ICommandSender var1, String[] var2);
+
+ /**
+ * Return whether the specified command parameter index is a username parameter.
+ */
+ boolean isUsernameIndex(String[] var1, int var2);
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ICommandManager.java b/sp-server/src/main/java/net/minecraft/src/ICommandManager.java
new file mode 100644
index 0000000..1b3bf92
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ICommandManager.java
@@ -0,0 +1,25 @@
+package net.minecraft.src;
+
+import java.util.List;
+import java.util.Map;
+
+public interface ICommandManager {
+ int executeCommand(ICommandSender var1, String var2);
+
+ /**
+ * Performs a "begins with" string match on each token in par2. Only returns
+ * commands that par1 can use.
+ */
+ List getPossibleCommands(ICommandSender var1, String var2);
+
+ /**
+ * returns all commands that the commandSender can use
+ */
+ List getPossibleCommands(ICommandSender var1);
+
+ /**
+ * returns a map of string to commads. All commands are returned, not just ones
+ * which someone has permission to use.
+ */
+ Map getCommands();
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ICommandSender.java b/sp-server/src/main/java/net/minecraft/src/ICommandSender.java
new file mode 100644
index 0000000..b5c3162
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ICommandSender.java
@@ -0,0 +1,25 @@
+package net.minecraft.src;
+
+public interface ICommandSender {
+ /**
+ * Gets the name of this command sender (usually username, but possibly "Rcon")
+ */
+ String getCommandSenderName();
+
+ void sendChatToPlayer(String var1);
+
+ /**
+ * Returns true if the command sender is allowed to use the given command.
+ */
+ boolean canCommandSenderUseCommand(int var1, String var2);
+
+ /**
+ * Translates and formats the given string key with the given arguments.
+ */
+ String translateString(String var1, Object... var2);
+
+ /**
+ * Return the position for this command sender.
+ */
+ ChunkCoordinates getCommandSenderPosition();
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ICrafting.java b/sp-server/src/main/java/net/minecraft/src/ICrafting.java
new file mode 100644
index 0000000..3b8e760
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ICrafting.java
@@ -0,0 +1,25 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+public interface ICrafting {
+ /**
+ * update the crafting window inventory with the items in the list
+ */
+ void updateCraftingInventory(Container var1, List var2);
+
+ /**
+ * Sends the contents of an inventory slot to the client-side Container. This
+ * doesn't have to match the actual contents of that slot. Args: Container, slot
+ * number, slot contents
+ */
+ void sendSlotContents(Container var1, int var2, ItemStack var3);
+
+ /**
+ * Sends two ints to the client-side Container. Used for furnace burning time,
+ * smelting progress, brewing progress, and enchanting level. Normally the first
+ * int identifies which variable to update, and the second contains the new
+ * value. Both are truncated to shorts in non-local SMP.
+ */
+ void sendProgressBarUpdate(Container var1, int var2, int var3);
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/IEnchantmentModifier.java b/sp-server/src/main/java/net/minecraft/src/IEnchantmentModifier.java
new file mode 100644
index 0000000..7c55e8e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/IEnchantmentModifier.java
@@ -0,0 +1,9 @@
+package net.minecraft.src;
+
+interface IEnchantmentModifier {
+ /**
+ * Generic method use to calculate modifiers of offensive or defensive
+ * enchantment values.
+ */
+ void calculateModifier(Enchantment var1, int var2);
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/IEntityMultiPart.java b/sp-server/src/main/java/net/minecraft/src/IEntityMultiPart.java
new file mode 100644
index 0000000..236f19f
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/IEntityMultiPart.java
@@ -0,0 +1,7 @@
+package net.minecraft.src;
+
+public interface IEntityMultiPart {
+ World func_82194_d();
+
+ boolean attackEntityFromPart(EntityDragonPart var1, DamageSource var2, int var3);
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/IEntitySelector.java b/sp-server/src/main/java/net/minecraft/src/IEntitySelector.java
new file mode 100644
index 0000000..1811cc6
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/IEntitySelector.java
@@ -0,0 +1,11 @@
+package net.minecraft.src;
+
+public interface IEntitySelector {
+ IEntitySelector selectAnything = new EntitySelectorAlive();
+ IEntitySelector selectInventories = new EntitySelectorInventory();
+
+ /**
+ * Return whether the specified entity is applicable to this filter.
+ */
+ boolean isEntityApplicable(Entity var1);
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/IInvBasic.java b/sp-server/src/main/java/net/minecraft/src/IInvBasic.java
new file mode 100644
index 0000000..7453ddd
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/IInvBasic.java
@@ -0,0 +1,9 @@
+package net.minecraft.src;
+
+public interface IInvBasic {
+ /**
+ * Called by InventoryBasic.onInventoryChanged() on a array that is never
+ * filled.
+ */
+ void onInventoryChanged(InventoryBasic var1);
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/IInventory.java b/sp-server/src/main/java/net/minecraft/src/IInventory.java
new file mode 100644
index 0000000..a044af9
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/IInventory.java
@@ -0,0 +1,70 @@
+package net.minecraft.src;
+
+public interface IInventory {
+ /**
+ * Returns the number of slots in the inventory.
+ */
+ int getSizeInventory();
+
+ /**
+ * Returns the stack in slot i
+ */
+ ItemStack getStackInSlot(int var1);
+
+ /**
+ * Removes from an inventory slot (first arg) up to a specified number (second
+ * arg) of items and returns them in a new stack.
+ */
+ ItemStack decrStackSize(int var1, int var2);
+
+ /**
+ * When some containers are closed they call this on each slot, then drop
+ * whatever it returns as an EntityItem - like when you close a workbench GUI.
+ */
+ ItemStack getStackInSlotOnClosing(int var1);
+
+ /**
+ * Sets the given item stack to the specified slot in the inventory (can be
+ * crafting or armor sections).
+ */
+ void setInventorySlotContents(int var1, ItemStack var2);
+
+ /**
+ * Returns the name of the inventory.
+ */
+ String getInvName();
+
+ /**
+ * If this returns false, the inventory name will be used as an unlocalized
+ * name, and translated into the player's language. Otherwise it will be used
+ * directly.
+ */
+ boolean isInvNameLocalized();
+
+ /**
+ * Returns the maximum stack size for a inventory slot. Seems to always be 64,
+ * possibly will be extended. *Isn't this more of a set than a get?*
+ */
+ int getInventoryStackLimit();
+
+ /**
+ * Called when an the contents of an Inventory change, usually
+ */
+ void onInventoryChanged();
+
+ /**
+ * Do not make give this method the name canInteractWith because it clashes with
+ * Container
+ */
+ boolean isUseableByPlayer(EntityPlayer var1);
+
+ void openChest();
+
+ void closeChest();
+
+ /**
+ * Returns true if automation is allowed to insert the given stack (ignoring
+ * stack size) into the given slot.
+ */
+ boolean isStackValidForSlot(int var1, ItemStack var2);
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ILocatableSource.java b/sp-server/src/main/java/net/minecraft/src/ILocatableSource.java
new file mode 100644
index 0000000..2f081b1
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ILocatableSource.java
@@ -0,0 +1,4 @@
+package net.minecraft.src;
+
+public interface ILocatableSource extends ILocation {
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ILocation.java b/sp-server/src/main/java/net/minecraft/src/ILocation.java
new file mode 100644
index 0000000..fba832c
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ILocation.java
@@ -0,0 +1,5 @@
+package net.minecraft.src;
+
+public interface ILocation extends IPosition {
+ World getWorld();
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ILogAgent.java b/sp-server/src/main/java/net/minecraft/src/ILogAgent.java
new file mode 100644
index 0000000..00dc39f
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ILogAgent.java
@@ -0,0 +1,19 @@
+package net.minecraft.src;
+
+import java.util.logging.Logger;
+
+public interface ILogAgent {
+ Logger getServerLogger();
+
+ void func_98233_a(String var1);
+
+ void func_98236_b(String var1);
+
+ void logWarningFormatted(String var1, Object... var2);
+
+ void logWarningException(String var1, Throwable var2);
+
+ void logSevere(String var1);
+
+ void logSevereException(String var1, Throwable var2);
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/IMerchant.java b/sp-server/src/main/java/net/minecraft/src/IMerchant.java
new file mode 100644
index 0000000..efa4512
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/IMerchant.java
@@ -0,0 +1,11 @@
+package net.minecraft.src;
+
+public interface IMerchant {
+ void setCustomer(EntityPlayer var1);
+
+ EntityPlayer getCustomer();
+
+ MerchantRecipeList getRecipes(EntityPlayer var1);
+
+ void useRecipe(MerchantRecipe var1);
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/IMob.java b/sp-server/src/main/java/net/minecraft/src/IMob.java
new file mode 100644
index 0000000..db2bc52
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/IMob.java
@@ -0,0 +1,6 @@
+package net.minecraft.src;
+
+public interface IMob extends IAnimals {
+ /** Entity selector for IMob types. */
+ IEntitySelector mobSelector = new FilterIMob();
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/INetworkManager.java b/sp-server/src/main/java/net/minecraft/src/INetworkManager.java
new file mode 100644
index 0000000..948ba18
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/INetworkManager.java
@@ -0,0 +1,40 @@
+package net.minecraft.src;
+
+public interface INetworkManager {
+ /**
+ * Sets the NetHandler for this NetworkManager. Server-only.
+ */
+ void setNetHandler(NetHandler var1);
+
+ /**
+ * Adds the packet to the correct send queue (chunk data packets go to a
+ * separate queue).
+ */
+ void addToSendQueue(Packet var1);
+
+ /**
+ * Wakes reader and writer threads
+ */
+ void wakeThreads();
+
+ /**
+ * Checks timeouts and processes all pending read packets.
+ */
+ void processReadPackets();
+
+ /**
+ * Shuts down the server. (Only actually used on the server)
+ */
+ void serverShutdown();
+
+ /**
+ * Returns the number of chunk data packets waiting to be sent.
+ */
+ int getNumChunkDataPackets();
+
+ /**
+ * Shuts down the network with the specified reason. Closes all streams and
+ * sockets, spawns NetworkMasterThread to stop reading and writing threads.
+ */
+ void networkShutdown(String var1, Object... var2);
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/INpc.java b/sp-server/src/main/java/net/minecraft/src/INpc.java
new file mode 100644
index 0000000..224d1c1
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/INpc.java
@@ -0,0 +1,4 @@
+package net.minecraft.src;
+
+public interface INpc extends IAnimals {
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/IPlayerFileData.java b/sp-server/src/main/java/net/minecraft/src/IPlayerFileData.java
new file mode 100644
index 0000000..251e310
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/IPlayerFileData.java
@@ -0,0 +1,18 @@
+package net.minecraft.src;
+
+public interface IPlayerFileData {
+ /**
+ * Writes the player data to disk from the specified PlayerEntityMP.
+ */
+ void writePlayerData(EntityPlayer var1);
+
+ /**
+ * Reads the player data from disk into the specified PlayerEntityMP.
+ */
+ NBTTagCompound readPlayerData(EntityPlayer var1);
+
+ /**
+ * Returns an array of usernames for which player.dat exists for.
+ */
+ String[] getAvailablePlayerDat();
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/IPosition.java b/sp-server/src/main/java/net/minecraft/src/IPosition.java
new file mode 100644
index 0000000..3da626c
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/IPosition.java
@@ -0,0 +1,9 @@
+package net.minecraft.src;
+
+public interface IPosition {
+ double getX();
+
+ double getY();
+
+ double getZ();
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/IProgressUpdate.java b/sp-server/src/main/java/net/minecraft/src/IProgressUpdate.java
new file mode 100644
index 0000000..9965a24
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/IProgressUpdate.java
@@ -0,0 +1,20 @@
+package net.minecraft.src;
+
+public interface IProgressUpdate {
+ /**
+ * Shows the 'Saving level' string.
+ */
+ void displaySavingString(String var1);
+
+ /**
+ * Displays a string on the loading screen supposed to indicate what is being
+ * done currently.
+ */
+ void displayLoadingString(String var1);
+
+ /**
+ * Updates the progress bar on the loading screen to the specified amount. Args:
+ * loadProgress
+ */
+ void setLoadingProgress(int var1);
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/IProjectile.java b/sp-server/src/main/java/net/minecraft/src/IProjectile.java
new file mode 100644
index 0000000..9084d7b
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/IProjectile.java
@@ -0,0 +1,9 @@
+package net.minecraft.src;
+
+public interface IProjectile {
+ /**
+ * Similar to setArrowHeading, it's point the throwable entity to a x, y, z
+ * direction.
+ */
+ void setThrowableHeading(double var1, double var3, double var5, float var7, float var8);
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/IRangedAttackMob.java b/sp-server/src/main/java/net/minecraft/src/IRangedAttackMob.java
new file mode 100644
index 0000000..728aa14
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/IRangedAttackMob.java
@@ -0,0 +1,8 @@
+package net.minecraft.src;
+
+public interface IRangedAttackMob {
+ /**
+ * Attack the specified entity using a ranged attack.
+ */
+ void attackEntityWithRangedAttack(EntityLiving var1, float var2);
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/IRecipe.java b/sp-server/src/main/java/net/minecraft/src/IRecipe.java
new file mode 100644
index 0000000..8f13dc9
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/IRecipe.java
@@ -0,0 +1,20 @@
+package net.minecraft.src;
+
+public interface IRecipe {
+ /**
+ * Used to check if a recipe matches current crafting inventory
+ */
+ boolean matches(InventoryCrafting var1, World var2);
+
+ /**
+ * Returns an Item that is the result of this recipe
+ */
+ ItemStack getCraftingResult(InventoryCrafting var1);
+
+ /**
+ * Returns the size of the recipe area
+ */
+ int getRecipeSize();
+
+ ItemStack getRecipeOutput();
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/IRegistry.java b/sp-server/src/main/java/net/minecraft/src/IRegistry.java
new file mode 100644
index 0000000..da89eb8
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/IRegistry.java
@@ -0,0 +1,10 @@
+package net.minecraft.src;
+
+public interface IRegistry {
+ Object func_82594_a(Object var1);
+
+ /**
+ * Register an object on this registry.
+ */
+ void putObject(Object var1, Object var2);
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ISaveFormat.java b/sp-server/src/main/java/net/minecraft/src/ISaveFormat.java
new file mode 100644
index 0000000..daba497
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ISaveFormat.java
@@ -0,0 +1,27 @@
+package net.minecraft.src;
+
+public interface ISaveFormat {
+ /**
+ * Returns back a loader for the specified save directory
+ */
+ ISaveHandler getSaveLoader(String var1, boolean var2);
+
+ void flushCache();
+
+ /**
+ * @args: Takes one argument - the name of the directory of the world to
+ * delete. @desc: Delete the world by deleting the associated directory
+ * recursively.
+ */
+ boolean deleteWorldDirectory(String var1);
+
+ /**
+ * gets if the map is old chunk saving (true) or McRegion (false)
+ */
+ boolean isOldMapFormat(String var1);
+
+ /**
+ * converts the map to mcRegion
+ */
+ boolean convertMapFormat(String var1, IProgressUpdate var2);
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ISaveHandler.java b/sp-server/src/main/java/net/minecraft/src/ISaveHandler.java
new file mode 100644
index 0000000..958b927
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ISaveHandler.java
@@ -0,0 +1,47 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.VFile;
+
+public interface ISaveHandler {
+ /**
+ * Loads and returns the world info
+ */
+ WorldInfo loadWorldInfo();
+
+ /**
+ * Checks the session lock to prevent save collisions
+ */
+ void checkSessionLock() throws MinecraftException;
+
+ /**
+ * initializes and returns the chunk loader for the specified world provider
+ */
+ IChunkLoader getChunkLoader(WorldProvider var1);
+
+ /**
+ * Saves the given World Info with the given NBTTagCompound as the Player.
+ */
+ void saveWorldInfoWithPlayer(WorldInfo var1, NBTTagCompound var2);
+
+ /**
+ * used to update level.dat from old format to MCRegion format
+ */
+ void saveWorldInfo(WorldInfo var1);
+
+ IPlayerFileData getPlayerNBTManager();
+
+ /**
+ * Called to flush all changes to disk, waiting for them to complete.
+ */
+ void flush();
+
+ /**
+ * Gets the file location of the given map
+ */
+ VFile getMapFileFromName(String var1);
+
+ /**
+ * Returns the name of the directory where world information is saved.
+ */
+ String getWorldDirectoryName();
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/IServer.java b/sp-server/src/main/java/net/minecraft/src/IServer.java
new file mode 100644
index 0000000..6b9ffef
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/IServer.java
@@ -0,0 +1,102 @@
+package net.minecraft.src;
+
+public interface IServer {
+ /**
+ * Gets an integer property. If it does not exist, set it to the specified
+ * value.
+ */
+ int getIntProperty(String var1, int var2);
+
+ /**
+ * Gets a string property. If it does not exist, set it to the specified value.
+ */
+ String getStringProperty(String var1, String var2);
+
+ /**
+ * Saves an Object with the given property name.
+ */
+ void setProperty(String var1, Object var2);
+
+ /**
+ * Saves all of the server properties to the properties file.
+ */
+ void saveProperties();
+
+ /**
+ * Returns the filename where server properties are stored
+ */
+ String getSettingsFilename();
+
+ /**
+ * Returns the server's hostname.
+ */
+ String getHostname();
+
+ /**
+ * Never used, but "getServerPort" is already taken.
+ */
+ int getPort();
+
+ /**
+ * Returns the server message of the day
+ */
+ String getMotd();
+
+ /**
+ * Returns the server's Minecraft version as string.
+ */
+ String getMinecraftVersion();
+
+ /**
+ * Returns the number of players currently on the server.
+ */
+ int getCurrentPlayerCount();
+
+ /**
+ * Returns the maximum number of players allowed on the server.
+ */
+ int getMaxPlayers();
+
+ /**
+ * Returns an array of the usernames of all the connected players.
+ */
+ String[] getAllUsernames();
+
+ String getFolderName();
+
+ /**
+ * Used by RCon's Query in the form of "MajorServerMod 1.2.3: MyPlugin 1.3;
+ * AnotherPlugin 2.1; AndSoForth 1.0".
+ */
+ String getPlugins();
+
+ /**
+ * Handle a command received by an RCon instance
+ */
+ String handleRConCommand(String var1);
+
+ /**
+ * Returns true if debugging is enabled, false otherwise.
+ */
+ boolean isDebuggingEnabled();
+
+ /**
+ * Logs the message with a level of INFO.
+ */
+ void logInfo(String var1);
+
+ /**
+ * Logs the message with a level of WARN.
+ */
+ void logWarning(String var1);
+
+ /**
+ * Logs the error message with a level of SEVERE.
+ */
+ void logSevere(String var1);
+
+ /**
+ * If isDebuggingEnabled(), logs the message with a level of INFO.
+ */
+ void logDebug(String var1);
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ISidedInventory.java b/sp-server/src/main/java/net/minecraft/src/ISidedInventory.java
new file mode 100644
index 0000000..9cee748
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ISidedInventory.java
@@ -0,0 +1,20 @@
+package net.minecraft.src;
+
+public interface ISidedInventory extends IInventory {
+ /**
+ * param side
+ */
+ int[] getSlotsForFace(int var1);
+
+ /**
+ * Returns true if automation can insert the given item in the given slot from
+ * the given side. Args: Slot, item, side
+ */
+ boolean canInsertItem(int var1, ItemStack var2, int var3);
+
+ /**
+ * Returns true if automation can extract the given item in the given slot from
+ * the given side. Args: Slot, item, side
+ */
+ boolean canExtractItem(int var1, ItemStack var2, int var3);
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/IStatType.java b/sp-server/src/main/java/net/minecraft/src/IStatType.java
new file mode 100644
index 0000000..c2c292f
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/IStatType.java
@@ -0,0 +1,4 @@
+package net.minecraft.src;
+
+public interface IStatType {
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/IThreadedFileIO.java b/sp-server/src/main/java/net/minecraft/src/IThreadedFileIO.java
new file mode 100644
index 0000000..c9583cb
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/IThreadedFileIO.java
@@ -0,0 +1,8 @@
+package net.minecraft.src;
+
+public interface IThreadedFileIO {
+ /**
+ * Returns a boolean stating if the write was unsuccessful.
+ */
+ boolean writeNextIO();
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ITileEntityProvider.java b/sp-server/src/main/java/net/minecraft/src/ITileEntityProvider.java
new file mode 100644
index 0000000..7d3aba7
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ITileEntityProvider.java
@@ -0,0 +1,9 @@
+package net.minecraft.src;
+
+public interface ITileEntityProvider {
+ /**
+ * Returns a new instance of a block's tile entity class. Called on placing the
+ * block.
+ */
+ TileEntity createNewTileEntity(World var1);
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/IUpdatePlayerListBox.java b/sp-server/src/main/java/net/minecraft/src/IUpdatePlayerListBox.java
new file mode 100644
index 0000000..5075676
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/IUpdatePlayerListBox.java
@@ -0,0 +1,8 @@
+package net.minecraft.src;
+
+public interface IUpdatePlayerListBox {
+ /**
+ * Updates the JList with a new model.
+ */
+ void update();
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/IWorldAccess.java b/sp-server/src/main/java/net/minecraft/src/IWorldAccess.java
new file mode 100644
index 0000000..76c5a91
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/IWorldAccess.java
@@ -0,0 +1,71 @@
+package net.minecraft.src;
+
+public interface IWorldAccess {
+ /**
+ * On the client, re-renders the block. On the server, sends the block to the
+ * client (which will re-render it), including the tile entity description
+ * packet if applicable. Args: x, y, z
+ */
+ void markBlockForUpdate(int var1, int var2, int var3);
+
+ /**
+ * On the client, re-renders this block. On the server, does nothing. Used for
+ * lighting updates.
+ */
+ void markBlockForRenderUpdate(int var1, int var2, int var3);
+
+ /**
+ * On the client, re-renders all blocks in this range, inclusive. On the server,
+ * does nothing. Args: min x, min y, min z, max x, max y, max z
+ */
+ void markBlockRangeForRenderUpdate(int var1, int var2, int var3, int var4, int var5, int var6);
+
+ /**
+ * Plays the specified sound. Arg: soundName, x, y, z, volume, pitch
+ */
+ void playSound(String var1, double var2, double var4, double var6, float var8, float var9);
+
+ /**
+ * Plays sound to all near players except the player reference given
+ */
+ void playSoundToNearExcept(EntityPlayer var1, String var2, double var3, double var5, double var7, float var9,
+ float var10);
+
+ /**
+ * Spawns a particle. Arg: particleType, x, y, z, velX, velY, velZ
+ */
+ void spawnParticle(String var1, double var2, double var4, double var6, double var8, double var10, double var12);
+
+ /**
+ * Called on all IWorldAccesses when an entity is created or loaded. On client
+ * worlds, starts downloading any necessary textures. On server worlds, adds the
+ * entity to the entity tracker.
+ */
+ void onEntityCreate(Entity var1);
+
+ /**
+ * Called on all IWorldAccesses when an entity is unloaded or destroyed. On
+ * client worlds, releases any downloaded textures. On server worlds, removes
+ * the entity from the entity tracker.
+ */
+ void onEntityDestroy(Entity var1);
+
+ /**
+ * Plays the specified record. Arg: recordName, x, y, z
+ */
+ void playRecord(String var1, int var2, int var3, int var4);
+
+ void broadcastSound(int var1, int var2, int var3, int var4, int var5);
+
+ /**
+ * Plays a pre-canned sound effect along with potentially auxiliary data-driven
+ * one-shot behaviour (particles, etc).
+ */
+ void playAuxSFX(EntityPlayer var1, int var2, int var3, int var4, int var5, int var6);
+
+ /**
+ * Starts (or continues) destroying a block with given ID at the given
+ * coordinates for the given partially destroyed value
+ */
+ void destroyBlockPartially(int var1, int var2, int var3, int var4, int var5);
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Icon.java b/sp-server/src/main/java/net/minecraft/src/Icon.java
new file mode 100644
index 0000000..df811e5
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Icon.java
@@ -0,0 +1,4 @@
+package net.minecraft.src;
+
+public interface Icon {
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/IntCache.java b/sp-server/src/main/java/net/minecraft/src/IntCache.java
new file mode 100644
index 0000000..7cde578d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/IntCache.java
@@ -0,0 +1,89 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class IntCache {
+ private static int intCacheSize = 256;
+
+ /**
+ * A list of pre-allocated int[256] arrays that are currently unused and can be
+ * returned by getIntCache()
+ */
+ private static List freeSmallArrays = new ArrayList();
+
+ /**
+ * A list of pre-allocated int[256] arrays that were previously returned by
+ * getIntCache() and which will not be re- used again until resetIntCache() is
+ * called.
+ */
+ private static List inUseSmallArrays = new ArrayList();
+
+ /**
+ * A list of pre-allocated int[cacheSize] arrays that are currently unused and
+ * can be returned by getIntCache()
+ */
+ private static List freeLargeArrays = new ArrayList();
+
+ /**
+ * A list of pre-allocated int[cacheSize] arrays that were previously returned
+ * by getIntCache() and which will not be re-used again until resetIntCache() is
+ * called.
+ */
+ private static List inUseLargeArrays = new ArrayList();
+
+ public static synchronized int[] getIntCache(int par0) {
+ int[] var1;
+
+ if (par0 <= 256) {
+ if (freeSmallArrays.isEmpty()) {
+ var1 = new int[256];
+ inUseSmallArrays.add(var1);
+ return var1;
+ } else {
+ var1 = (int[]) freeSmallArrays.remove(freeSmallArrays.size() - 1);
+ inUseSmallArrays.add(var1);
+ return var1;
+ }
+ } else if (par0 > intCacheSize) {
+ intCacheSize = par0;
+ freeLargeArrays.clear();
+ inUseLargeArrays.clear();
+ var1 = new int[intCacheSize];
+ inUseLargeArrays.add(var1);
+ return var1;
+ } else if (freeLargeArrays.isEmpty()) {
+ var1 = new int[intCacheSize];
+ inUseLargeArrays.add(var1);
+ return var1;
+ } else {
+ var1 = (int[]) freeLargeArrays.remove(freeLargeArrays.size() - 1);
+ inUseLargeArrays.add(var1);
+ return var1;
+ }
+ }
+
+ /**
+ * Mark all pre-allocated arrays as available for re-use by moving them to the
+ * appropriate free lists.
+ */
+ public static synchronized void resetIntCache() {
+ if (!freeLargeArrays.isEmpty()) {
+ freeLargeArrays.remove(freeLargeArrays.size() - 1);
+ }
+
+ if (!freeSmallArrays.isEmpty()) {
+ freeSmallArrays.remove(freeSmallArrays.size() - 1);
+ }
+
+ freeLargeArrays.addAll(inUseLargeArrays);
+ freeSmallArrays.addAll(inUseSmallArrays);
+ inUseLargeArrays.clear();
+ inUseSmallArrays.clear();
+ }
+
+ public static synchronized String func_85144_b() {
+ return "cache: " + freeLargeArrays.size() + ", tcache: " + freeSmallArrays.size() + ", allocated: "
+ + inUseLargeArrays.size() + ", tallocated: " + inUseSmallArrays.size();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/IntHashMap.java b/sp-server/src/main/java/net/minecraft/src/IntHashMap.java
new file mode 100644
index 0000000..29bc21c
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/IntHashMap.java
@@ -0,0 +1,213 @@
+package net.minecraft.src;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class IntHashMap {
+ /** An array of HashEntries representing the heads of hash slot lists */
+ private transient IntHashMapEntry[] slots = new IntHashMapEntry[16];
+
+ /** The number of items stored in this map */
+ private transient int count;
+
+ /** The grow threshold */
+ private int threshold = 12;
+
+ /** The scale factor used to determine when to grow the table */
+ private final float growFactor = 0.75F;
+
+ /** A serial stamp used to mark changes */
+ private transient volatile int versionStamp;
+
+ /** The set of all the keys stored in this MCHash object */
+ private Set keySet = new HashSet();
+
+ /**
+ * Makes the passed in integer suitable for hashing by a number of shifts
+ */
+ private static int computeHash(int par0) {
+ par0 ^= par0 >>> 20 ^ par0 >>> 12;
+ return par0 ^ par0 >>> 7 ^ par0 >>> 4;
+ }
+
+ /**
+ * Computes the index of the slot for the hash and slot count passed in.
+ */
+ private static int getSlotIndex(int par0, int par1) {
+ return par0 & par1 - 1;
+ }
+
+ /**
+ * Returns the object associated to a key
+ */
+ public Object lookup(int par1) {
+ int var2 = computeHash(par1);
+
+ for (IntHashMapEntry var3 = this.slots[getSlotIndex(var2,
+ this.slots.length)]; var3 != null; var3 = var3.nextEntry) {
+ if (var3.hashEntry == par1) {
+ return var3.valueEntry;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns true if this hash table contains the specified item.
+ */
+ public boolean containsItem(int par1) {
+ return this.lookupEntry(par1) != null;
+ }
+
+ /**
+ * Returns the internal entry for a key
+ */
+ final IntHashMapEntry lookupEntry(int par1) {
+ int var2 = computeHash(par1);
+
+ for (IntHashMapEntry var3 = this.slots[getSlotIndex(var2,
+ this.slots.length)]; var3 != null; var3 = var3.nextEntry) {
+ if (var3.hashEntry == par1) {
+ return var3;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Adds a key and associated value to this map
+ */
+ public void addKey(int par1, Object par2Obj) {
+ this.keySet.add(Integer.valueOf(par1));
+ int var3 = computeHash(par1);
+ int var4 = getSlotIndex(var3, this.slots.length);
+
+ for (IntHashMapEntry var5 = this.slots[var4]; var5 != null; var5 = var5.nextEntry) {
+ if (var5.hashEntry == par1) {
+ var5.valueEntry = par2Obj;
+ return;
+ }
+ }
+
+ ++this.versionStamp;
+ this.insert(var3, par1, par2Obj, var4);
+ }
+
+ /**
+ * Increases the number of hash slots
+ */
+ private void grow(int par1) {
+ IntHashMapEntry[] var2 = this.slots;
+ int var3 = var2.length;
+
+ if (var3 == 1073741824) {
+ this.threshold = Integer.MAX_VALUE;
+ } else {
+ IntHashMapEntry[] var4 = new IntHashMapEntry[par1];
+ this.copyTo(var4);
+ this.slots = var4;
+ this.threshold = (int) ((float) par1 * this.growFactor);
+ }
+ }
+
+ /**
+ * Copies the hash slots to a new array
+ */
+ private void copyTo(IntHashMapEntry[] par1ArrayOfIntHashMapEntry) {
+ IntHashMapEntry[] var2 = this.slots;
+ int var3 = par1ArrayOfIntHashMapEntry.length;
+
+ for (int var4 = 0; var4 < var2.length; ++var4) {
+ IntHashMapEntry var5 = var2[var4];
+
+ if (var5 != null) {
+ var2[var4] = null;
+ IntHashMapEntry var6;
+
+ do {
+ var6 = var5.nextEntry;
+ int var7 = getSlotIndex(var5.slotHash, var3);
+ var5.nextEntry = par1ArrayOfIntHashMapEntry[var7];
+ par1ArrayOfIntHashMapEntry[var7] = var5;
+ var5 = var6;
+ } while (var6 != null);
+ }
+ }
+ }
+
+ /**
+ * Removes the specified object from the map and returns it
+ */
+ public Object removeObject(int par1) {
+ this.keySet.remove(Integer.valueOf(par1));
+ IntHashMapEntry var2 = this.removeEntry(par1);
+ return var2 == null ? null : var2.valueEntry;
+ }
+
+ /**
+ * Removes the specified entry from the map and returns it
+ */
+ final IntHashMapEntry removeEntry(int par1) {
+ int var2 = computeHash(par1);
+ int var3 = getSlotIndex(var2, this.slots.length);
+ IntHashMapEntry var4 = this.slots[var3];
+ IntHashMapEntry var5;
+ IntHashMapEntry var6;
+
+ for (var5 = var4; var5 != null; var5 = var6) {
+ var6 = var5.nextEntry;
+
+ if (var5.hashEntry == par1) {
+ ++this.versionStamp;
+ --this.count;
+
+ if (var4 == var5) {
+ this.slots[var3] = var6;
+ } else {
+ var4.nextEntry = var6;
+ }
+
+ return var5;
+ }
+
+ var4 = var5;
+ }
+
+ return var5;
+ }
+
+ /**
+ * Removes all entries from the map
+ */
+ public void clearMap() {
+ ++this.versionStamp;
+ IntHashMapEntry[] var1 = this.slots;
+
+ for (int var2 = 0; var2 < var1.length; ++var2) {
+ var1[var2] = null;
+ }
+
+ this.count = 0;
+ }
+
+ /**
+ * Adds an object to a slot
+ */
+ private void insert(int par1, int par2, Object par3Obj, int par4) {
+ IntHashMapEntry var5 = this.slots[par4];
+ this.slots[par4] = new IntHashMapEntry(par1, par2, par3Obj, var5);
+
+ if (this.count++ >= this.threshold) {
+ this.grow(2 * this.slots.length);
+ }
+ }
+
+ /**
+ * Returns the hash code for a key
+ */
+ static int getHash(int par0) {
+ return computeHash(par0);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/IntHashMapEntry.java b/sp-server/src/main/java/net/minecraft/src/IntHashMapEntry.java
new file mode 100644
index 0000000..d9129e4
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/IntHashMapEntry.java
@@ -0,0 +1,65 @@
+package net.minecraft.src;
+
+class IntHashMapEntry {
+ /** The hash code of this entry */
+ final int hashEntry;
+
+ /** The object stored in this entry */
+ Object valueEntry;
+
+ /** The next entry in this slot */
+ IntHashMapEntry nextEntry;
+
+ /** The id of the hash slot computed from the hash */
+ final int slotHash;
+
+ IntHashMapEntry(int par1, int par2, Object par3Obj, IntHashMapEntry par4IntHashMapEntry) {
+ this.valueEntry = par3Obj;
+ this.nextEntry = par4IntHashMapEntry;
+ this.hashEntry = par2;
+ this.slotHash = par1;
+ }
+
+ /**
+ * Returns the hash code for this entry
+ */
+ public final int getHash() {
+ return this.hashEntry;
+ }
+
+ /**
+ * Returns the object stored in this entry
+ */
+ public final Object getValue() {
+ return this.valueEntry;
+ }
+
+ public final boolean equals(Object par1Obj) {
+ if (!(par1Obj instanceof IntHashMapEntry)) {
+ return false;
+ } else {
+ IntHashMapEntry var2 = (IntHashMapEntry) par1Obj;
+ Integer var3 = Integer.valueOf(this.getHash());
+ Integer var4 = Integer.valueOf(var2.getHash());
+
+ if (var3 == var4 || var3 != null && var3.equals(var4)) {
+ Object var5 = this.getValue();
+ Object var6 = var2.getValue();
+
+ if (var5 == var6 || var5 != null && var5.equals(var6)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+ }
+
+ public final int hashCode() {
+ return IntHashMap.getHash(this.hashEntry);
+ }
+
+ public final String toString() {
+ return this.getHash() + "=" + this.getValue();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/InventoryBasic.java b/sp-server/src/main/java/net/minecraft/src/InventoryBasic.java
new file mode 100644
index 0000000..a5cc5e3
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/InventoryBasic.java
@@ -0,0 +1,145 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+public class InventoryBasic implements IInventory {
+ private String inventoryTitle;
+ private int slotsCount;
+ private ItemStack[] inventoryContents;
+ private List field_70480_d;
+ private boolean field_94051_e;
+
+ public InventoryBasic(String par1Str, boolean par2, int par3) {
+ this.inventoryTitle = par1Str;
+ this.field_94051_e = par2;
+ this.slotsCount = par3;
+ this.inventoryContents = new ItemStack[par3];
+ }
+
+ /**
+ * Returns the stack in slot i
+ */
+ public ItemStack getStackInSlot(int par1) {
+ return this.inventoryContents[par1];
+ }
+
+ /**
+ * Removes from an inventory slot (first arg) up to a specified number (second
+ * arg) of items and returns them in a new stack.
+ */
+ public ItemStack decrStackSize(int par1, int par2) {
+ if (this.inventoryContents[par1] != null) {
+ ItemStack var3;
+
+ if (this.inventoryContents[par1].stackSize <= par2) {
+ var3 = this.inventoryContents[par1];
+ this.inventoryContents[par1] = null;
+ this.onInventoryChanged();
+ return var3;
+ } else {
+ var3 = this.inventoryContents[par1].splitStack(par2);
+
+ if (this.inventoryContents[par1].stackSize == 0) {
+ this.inventoryContents[par1] = null;
+ }
+
+ this.onInventoryChanged();
+ return var3;
+ }
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * When some containers are closed they call this on each slot, then drop
+ * whatever it returns as an EntityItem - like when you close a workbench GUI.
+ */
+ public ItemStack getStackInSlotOnClosing(int par1) {
+ if (this.inventoryContents[par1] != null) {
+ ItemStack var2 = this.inventoryContents[par1];
+ this.inventoryContents[par1] = null;
+ return var2;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Sets the given item stack to the specified slot in the inventory (can be
+ * crafting or armor sections).
+ */
+ public void setInventorySlotContents(int par1, ItemStack par2ItemStack) {
+ this.inventoryContents[par1] = par2ItemStack;
+
+ if (par2ItemStack != null && par2ItemStack.stackSize > this.getInventoryStackLimit()) {
+ par2ItemStack.stackSize = this.getInventoryStackLimit();
+ }
+
+ this.onInventoryChanged();
+ }
+
+ /**
+ * Returns the number of slots in the inventory.
+ */
+ public int getSizeInventory() {
+ return this.slotsCount;
+ }
+
+ /**
+ * Returns the name of the inventory.
+ */
+ public String getInvName() {
+ return this.inventoryTitle;
+ }
+
+ /**
+ * If this returns false, the inventory name will be used as an unlocalized
+ * name, and translated into the player's language. Otherwise it will be used
+ * directly.
+ */
+ public boolean isInvNameLocalized() {
+ return this.field_94051_e;
+ }
+
+ /**
+ * Returns the maximum stack size for a inventory slot. Seems to always be 64,
+ * possibly will be extended. *Isn't this more of a set than a get?*
+ */
+ public int getInventoryStackLimit() {
+ return 64;
+ }
+
+ /**
+ * Called when an the contents of an Inventory change, usually
+ */
+ public void onInventoryChanged() {
+ if (this.field_70480_d != null) {
+ for (int var1 = 0; var1 < this.field_70480_d.size(); ++var1) {
+ ((IInvBasic) this.field_70480_d.get(var1)).onInventoryChanged(this);
+ }
+ }
+ }
+
+ /**
+ * Do not make give this method the name canInteractWith because it clashes with
+ * Container
+ */
+ public boolean isUseableByPlayer(EntityPlayer par1EntityPlayer) {
+ return true;
+ }
+
+ public void openChest() {
+ }
+
+ public void closeChest() {
+ }
+
+ /**
+ * Returns true if automation is allowed to insert the given stack (ignoring
+ * stack size) into the given slot.
+ */
+ public boolean isStackValidForSlot(int par1, ItemStack par2ItemStack) {
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/InventoryCraftResult.java b/sp-server/src/main/java/net/minecraft/src/InventoryCraftResult.java
new file mode 100644
index 0000000..1943a4d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/InventoryCraftResult.java
@@ -0,0 +1,108 @@
+package net.minecraft.src;
+
+public class InventoryCraftResult implements IInventory {
+ /** A list of one item containing the result of the crafting formula */
+ private ItemStack[] stackResult = new ItemStack[1];
+
+ /**
+ * Returns the number of slots in the inventory.
+ */
+ public int getSizeInventory() {
+ return 1;
+ }
+
+ /**
+ * Returns the stack in slot i
+ */
+ public ItemStack getStackInSlot(int par1) {
+ return this.stackResult[0];
+ }
+
+ /**
+ * Returns the name of the inventory.
+ */
+ public String getInvName() {
+ return "Result";
+ }
+
+ /**
+ * If this returns false, the inventory name will be used as an unlocalized
+ * name, and translated into the player's language. Otherwise it will be used
+ * directly.
+ */
+ public boolean isInvNameLocalized() {
+ return false;
+ }
+
+ /**
+ * Removes from an inventory slot (first arg) up to a specified number (second
+ * arg) of items and returns them in a new stack.
+ */
+ public ItemStack decrStackSize(int par1, int par2) {
+ if (this.stackResult[0] != null) {
+ ItemStack var3 = this.stackResult[0];
+ this.stackResult[0] = null;
+ return var3;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * When some containers are closed they call this on each slot, then drop
+ * whatever it returns as an EntityItem - like when you close a workbench GUI.
+ */
+ public ItemStack getStackInSlotOnClosing(int par1) {
+ if (this.stackResult[0] != null) {
+ ItemStack var2 = this.stackResult[0];
+ this.stackResult[0] = null;
+ return var2;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Sets the given item stack to the specified slot in the inventory (can be
+ * crafting or armor sections).
+ */
+ public void setInventorySlotContents(int par1, ItemStack par2ItemStack) {
+ this.stackResult[0] = par2ItemStack;
+ }
+
+ /**
+ * Returns the maximum stack size for a inventory slot. Seems to always be 64,
+ * possibly will be extended. *Isn't this more of a set than a get?*
+ */
+ public int getInventoryStackLimit() {
+ return 64;
+ }
+
+ /**
+ * Called when an the contents of an Inventory change, usually
+ */
+ public void onInventoryChanged() {
+ }
+
+ /**
+ * Do not make give this method the name canInteractWith because it clashes with
+ * Container
+ */
+ public boolean isUseableByPlayer(EntityPlayer par1EntityPlayer) {
+ return true;
+ }
+
+ public void openChest() {
+ }
+
+ public void closeChest() {
+ }
+
+ /**
+ * Returns true if automation is allowed to insert the given stack (ignoring
+ * stack size) into the given slot.
+ */
+ public boolean isStackValidForSlot(int par1, ItemStack par2ItemStack) {
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/InventoryCrafting.java b/sp-server/src/main/java/net/minecraft/src/InventoryCrafting.java
new file mode 100644
index 0000000..bf788ea
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/InventoryCrafting.java
@@ -0,0 +1,152 @@
+package net.minecraft.src;
+
+public class InventoryCrafting implements IInventory {
+ /** List of the stacks in the crafting matrix. */
+ private ItemStack[] stackList;
+
+ /** the width of the crafting inventory */
+ private int inventoryWidth;
+
+ /**
+ * Class containing the callbacks for the events on_GUIClosed and
+ * on_CraftMaxtrixChanged.
+ */
+ private Container eventHandler;
+
+ public InventoryCrafting(Container par1Container, int par2, int par3) {
+ int var4 = par2 * par3;
+ this.stackList = new ItemStack[var4];
+ this.eventHandler = par1Container;
+ this.inventoryWidth = par2;
+ }
+
+ /**
+ * Returns the number of slots in the inventory.
+ */
+ public int getSizeInventory() {
+ return this.stackList.length;
+ }
+
+ /**
+ * Returns the stack in slot i
+ */
+ public ItemStack getStackInSlot(int par1) {
+ return par1 >= this.getSizeInventory() ? null : this.stackList[par1];
+ }
+
+ /**
+ * Returns the itemstack in the slot specified (Top left is 0, 0). Args: row,
+ * column
+ */
+ public ItemStack getStackInRowAndColumn(int par1, int par2) {
+ if (par1 >= 0 && par1 < this.inventoryWidth) {
+ int var3 = par1 + par2 * this.inventoryWidth;
+ return this.getStackInSlot(var3);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Returns the name of the inventory.
+ */
+ public String getInvName() {
+ return "container.crafting";
+ }
+
+ /**
+ * If this returns false, the inventory name will be used as an unlocalized
+ * name, and translated into the player's language. Otherwise it will be used
+ * directly.
+ */
+ public boolean isInvNameLocalized() {
+ return false;
+ }
+
+ /**
+ * When some containers are closed they call this on each slot, then drop
+ * whatever it returns as an EntityItem - like when you close a workbench GUI.
+ */
+ public ItemStack getStackInSlotOnClosing(int par1) {
+ if (this.stackList[par1] != null) {
+ ItemStack var2 = this.stackList[par1];
+ this.stackList[par1] = null;
+ return var2;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Removes from an inventory slot (first arg) up to a specified number (second
+ * arg) of items and returns them in a new stack.
+ */
+ public ItemStack decrStackSize(int par1, int par2) {
+ if (this.stackList[par1] != null) {
+ ItemStack var3;
+
+ if (this.stackList[par1].stackSize <= par2) {
+ var3 = this.stackList[par1];
+ this.stackList[par1] = null;
+ this.eventHandler.onCraftMatrixChanged(this);
+ return var3;
+ } else {
+ var3 = this.stackList[par1].splitStack(par2);
+
+ if (this.stackList[par1].stackSize == 0) {
+ this.stackList[par1] = null;
+ }
+
+ this.eventHandler.onCraftMatrixChanged(this);
+ return var3;
+ }
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Sets the given item stack to the specified slot in the inventory (can be
+ * crafting or armor sections).
+ */
+ public void setInventorySlotContents(int par1, ItemStack par2ItemStack) {
+ this.stackList[par1] = par2ItemStack;
+ this.eventHandler.onCraftMatrixChanged(this);
+ }
+
+ /**
+ * Returns the maximum stack size for a inventory slot. Seems to always be 64,
+ * possibly will be extended. *Isn't this more of a set than a get?*
+ */
+ public int getInventoryStackLimit() {
+ return 64;
+ }
+
+ /**
+ * Called when an the contents of an Inventory change, usually
+ */
+ public void onInventoryChanged() {
+ }
+
+ /**
+ * Do not make give this method the name canInteractWith because it clashes with
+ * Container
+ */
+ public boolean isUseableByPlayer(EntityPlayer par1EntityPlayer) {
+ return true;
+ }
+
+ public void openChest() {
+ }
+
+ public void closeChest() {
+ }
+
+ /**
+ * Returns true if automation is allowed to insert the given stack (ignoring
+ * stack size) into the given slot.
+ */
+ public boolean isStackValidForSlot(int par1, ItemStack par2ItemStack) {
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/InventoryEnderChest.java b/sp-server/src/main/java/net/minecraft/src/InventoryEnderChest.java
new file mode 100644
index 0000000..c3d293d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/InventoryEnderChest.java
@@ -0,0 +1,81 @@
+package net.minecraft.src;
+
+public class InventoryEnderChest extends InventoryBasic {
+ private TileEntityEnderChest associatedChest;
+
+ public InventoryEnderChest() {
+ super("container.enderchest", false, 27);
+ }
+
+ public void setAssociatedChest(TileEntityEnderChest par1TileEntityEnderChest) {
+ this.associatedChest = par1TileEntityEnderChest;
+ }
+
+ public void loadInventoryFromNBT(NBTTagList par1NBTTagList) {
+ int var2;
+
+ for (var2 = 0; var2 < this.getSizeInventory(); ++var2) {
+ this.setInventorySlotContents(var2, (ItemStack) null);
+ }
+
+ for (var2 = 0; var2 < par1NBTTagList.tagCount(); ++var2) {
+ NBTTagCompound var3 = (NBTTagCompound) par1NBTTagList.tagAt(var2);
+ int var4 = var3.getByte("Slot") & 255;
+
+ if (var4 >= 0 && var4 < this.getSizeInventory()) {
+ this.setInventorySlotContents(var4, ItemStack.loadItemStackFromNBT(var3));
+ }
+ }
+ }
+
+ public NBTTagList saveInventoryToNBT() {
+ NBTTagList var1 = new NBTTagList("EnderItems");
+
+ for (int var2 = 0; var2 < this.getSizeInventory(); ++var2) {
+ ItemStack var3 = this.getStackInSlot(var2);
+
+ if (var3 != null) {
+ NBTTagCompound var4 = new NBTTagCompound();
+ var4.setByte("Slot", (byte) var2);
+ var3.writeToNBT(var4);
+ var1.appendTag(var4);
+ }
+ }
+
+ return var1;
+ }
+
+ /**
+ * Do not make give this method the name canInteractWith because it clashes with
+ * Container
+ */
+ public boolean isUseableByPlayer(EntityPlayer par1EntityPlayer) {
+ return this.associatedChest != null && !this.associatedChest.isUseableByPlayer(par1EntityPlayer) ? false
+ : super.isUseableByPlayer(par1EntityPlayer);
+ }
+
+ public void openChest() {
+ if (this.associatedChest != null) {
+ this.associatedChest.openChest();
+ }
+
+ super.openChest();
+ }
+
+ public void closeChest() {
+ if (this.associatedChest != null) {
+ this.associatedChest.closeChest();
+ }
+
+ super.closeChest();
+ this.associatedChest = null;
+ }
+
+ /**
+ * Returns true if automation is allowed to insert the given stack (ignoring
+ * stack size) into the given slot.
+ */
+ public boolean isStackValidForSlot(int par1, ItemStack par2ItemStack) {
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/InventoryLargeChest.java b/sp-server/src/main/java/net/minecraft/src/InventoryLargeChest.java
new file mode 100644
index 0000000..1e5353c
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/InventoryLargeChest.java
@@ -0,0 +1,142 @@
+package net.minecraft.src;
+
+public class InventoryLargeChest implements IInventory {
+ /** Name of the chest. */
+ private String name;
+
+ /** Inventory object corresponding to double chest upper part */
+ private IInventory upperChest;
+
+ /** Inventory object corresponding to double chest lower part */
+ private IInventory lowerChest;
+
+ public InventoryLargeChest(String par1Str, IInventory par2IInventory, IInventory par3IInventory) {
+ this.name = par1Str;
+
+ if (par2IInventory == null) {
+ par2IInventory = par3IInventory;
+ }
+
+ if (par3IInventory == null) {
+ par3IInventory = par2IInventory;
+ }
+
+ this.upperChest = par2IInventory;
+ this.lowerChest = par3IInventory;
+ }
+
+ /**
+ * Returns the number of slots in the inventory.
+ */
+ public int getSizeInventory() {
+ return this.upperChest.getSizeInventory() + this.lowerChest.getSizeInventory();
+ }
+
+ /**
+ * Return whether the given inventory is part of this large chest.
+ */
+ public boolean isPartOfLargeChest(IInventory par1IInventory) {
+ return this.upperChest == par1IInventory || this.lowerChest == par1IInventory;
+ }
+
+ /**
+ * Returns the name of the inventory.
+ */
+ public String getInvName() {
+ return this.upperChest.isInvNameLocalized() ? this.upperChest.getInvName()
+ : (this.lowerChest.isInvNameLocalized() ? this.lowerChest.getInvName() : this.name);
+ }
+
+ /**
+ * If this returns false, the inventory name will be used as an unlocalized
+ * name, and translated into the player's language. Otherwise it will be used
+ * directly.
+ */
+ public boolean isInvNameLocalized() {
+ return this.upperChest.isInvNameLocalized() || this.lowerChest.isInvNameLocalized();
+ }
+
+ /**
+ * Returns the stack in slot i
+ */
+ public ItemStack getStackInSlot(int par1) {
+ return par1 >= this.upperChest.getSizeInventory()
+ ? this.lowerChest.getStackInSlot(par1 - this.upperChest.getSizeInventory())
+ : this.upperChest.getStackInSlot(par1);
+ }
+
+ /**
+ * Removes from an inventory slot (first arg) up to a specified number (second
+ * arg) of items and returns them in a new stack.
+ */
+ public ItemStack decrStackSize(int par1, int par2) {
+ return par1 >= this.upperChest.getSizeInventory()
+ ? this.lowerChest.decrStackSize(par1 - this.upperChest.getSizeInventory(), par2)
+ : this.upperChest.decrStackSize(par1, par2);
+ }
+
+ /**
+ * When some containers are closed they call this on each slot, then drop
+ * whatever it returns as an EntityItem - like when you close a workbench GUI.
+ */
+ public ItemStack getStackInSlotOnClosing(int par1) {
+ return par1 >= this.upperChest.getSizeInventory()
+ ? this.lowerChest.getStackInSlotOnClosing(par1 - this.upperChest.getSizeInventory())
+ : this.upperChest.getStackInSlotOnClosing(par1);
+ }
+
+ /**
+ * Sets the given item stack to the specified slot in the inventory (can be
+ * crafting or armor sections).
+ */
+ public void setInventorySlotContents(int par1, ItemStack par2ItemStack) {
+ if (par1 >= this.upperChest.getSizeInventory()) {
+ this.lowerChest.setInventorySlotContents(par1 - this.upperChest.getSizeInventory(), par2ItemStack);
+ } else {
+ this.upperChest.setInventorySlotContents(par1, par2ItemStack);
+ }
+ }
+
+ /**
+ * Returns the maximum stack size for a inventory slot. Seems to always be 64,
+ * possibly will be extended. *Isn't this more of a set than a get?*
+ */
+ public int getInventoryStackLimit() {
+ return this.upperChest.getInventoryStackLimit();
+ }
+
+ /**
+ * Called when an the contents of an Inventory change, usually
+ */
+ public void onInventoryChanged() {
+ this.upperChest.onInventoryChanged();
+ this.lowerChest.onInventoryChanged();
+ }
+
+ /**
+ * Do not make give this method the name canInteractWith because it clashes with
+ * Container
+ */
+ public boolean isUseableByPlayer(EntityPlayer par1EntityPlayer) {
+ return this.upperChest.isUseableByPlayer(par1EntityPlayer)
+ && this.lowerChest.isUseableByPlayer(par1EntityPlayer);
+ }
+
+ public void openChest() {
+ this.upperChest.openChest();
+ this.lowerChest.openChest();
+ }
+
+ public void closeChest() {
+ this.upperChest.closeChest();
+ this.lowerChest.closeChest();
+ }
+
+ /**
+ * Returns true if automation is allowed to insert the given stack (ignoring
+ * stack size) into the given slot.
+ */
+ public boolean isStackValidForSlot(int par1, ItemStack par2ItemStack) {
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/InventoryMerchant.java b/sp-server/src/main/java/net/minecraft/src/InventoryMerchant.java
new file mode 100644
index 0000000..107054d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/InventoryMerchant.java
@@ -0,0 +1,203 @@
+package net.minecraft.src;
+
+public class InventoryMerchant implements IInventory {
+ private final IMerchant theMerchant;
+ private ItemStack[] theInventory = new ItemStack[3];
+ private final EntityPlayer thePlayer;
+ private MerchantRecipe currentRecipe;
+ private int currentRecipeIndex;
+
+ public InventoryMerchant(EntityPlayer par1EntityPlayer, IMerchant par2IMerchant) {
+ this.thePlayer = par1EntityPlayer;
+ this.theMerchant = par2IMerchant;
+ }
+
+ /**
+ * Returns the number of slots in the inventory.
+ */
+ public int getSizeInventory() {
+ return this.theInventory.length;
+ }
+
+ /**
+ * Returns the stack in slot i
+ */
+ public ItemStack getStackInSlot(int par1) {
+ return this.theInventory[par1];
+ }
+
+ /**
+ * Removes from an inventory slot (first arg) up to a specified number (second
+ * arg) of items and returns them in a new stack.
+ */
+ public ItemStack decrStackSize(int par1, int par2) {
+ if (this.theInventory[par1] != null) {
+ ItemStack var3;
+
+ if (par1 == 2) {
+ var3 = this.theInventory[par1];
+ this.theInventory[par1] = null;
+ return var3;
+ } else if (this.theInventory[par1].stackSize <= par2) {
+ var3 = this.theInventory[par1];
+ this.theInventory[par1] = null;
+
+ if (this.inventoryResetNeededOnSlotChange(par1)) {
+ this.resetRecipeAndSlots();
+ }
+
+ return var3;
+ } else {
+ var3 = this.theInventory[par1].splitStack(par2);
+
+ if (this.theInventory[par1].stackSize == 0) {
+ this.theInventory[par1] = null;
+ }
+
+ if (this.inventoryResetNeededOnSlotChange(par1)) {
+ this.resetRecipeAndSlots();
+ }
+
+ return var3;
+ }
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * if par1 slot has changed, does resetRecipeAndSlots need to be called?
+ */
+ private boolean inventoryResetNeededOnSlotChange(int par1) {
+ return par1 == 0 || par1 == 1;
+ }
+
+ /**
+ * When some containers are closed they call this on each slot, then drop
+ * whatever it returns as an EntityItem - like when you close a workbench GUI.
+ */
+ public ItemStack getStackInSlotOnClosing(int par1) {
+ if (this.theInventory[par1] != null) {
+ ItemStack var2 = this.theInventory[par1];
+ this.theInventory[par1] = null;
+ return var2;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Sets the given item stack to the specified slot in the inventory (can be
+ * crafting or armor sections).
+ */
+ public void setInventorySlotContents(int par1, ItemStack par2ItemStack) {
+ this.theInventory[par1] = par2ItemStack;
+
+ if (par2ItemStack != null && par2ItemStack.stackSize > this.getInventoryStackLimit()) {
+ par2ItemStack.stackSize = this.getInventoryStackLimit();
+ }
+
+ if (this.inventoryResetNeededOnSlotChange(par1)) {
+ this.resetRecipeAndSlots();
+ }
+ }
+
+ /**
+ * Returns the name of the inventory.
+ */
+ public String getInvName() {
+ return "mob.villager";
+ }
+
+ /**
+ * If this returns false, the inventory name will be used as an unlocalized
+ * name, and translated into the player's language. Otherwise it will be used
+ * directly.
+ */
+ public boolean isInvNameLocalized() {
+ return false;
+ }
+
+ /**
+ * Returns the maximum stack size for a inventory slot. Seems to always be 64,
+ * possibly will be extended. *Isn't this more of a set than a get?*
+ */
+ public int getInventoryStackLimit() {
+ return 64;
+ }
+
+ /**
+ * Do not make give this method the name canInteractWith because it clashes with
+ * Container
+ */
+ public boolean isUseableByPlayer(EntityPlayer par1EntityPlayer) {
+ return this.theMerchant.getCustomer() == par1EntityPlayer;
+ }
+
+ public void openChest() {
+ }
+
+ public void closeChest() {
+ }
+
+ /**
+ * Returns true if automation is allowed to insert the given stack (ignoring
+ * stack size) into the given slot.
+ */
+ public boolean isStackValidForSlot(int par1, ItemStack par2ItemStack) {
+ return true;
+ }
+
+ /**
+ * Called when an the contents of an Inventory change, usually
+ */
+ public void onInventoryChanged() {
+ this.resetRecipeAndSlots();
+ }
+
+ public void resetRecipeAndSlots() {
+ this.currentRecipe = null;
+ ItemStack var1 = this.theInventory[0];
+ ItemStack var2 = this.theInventory[1];
+
+ if (var1 == null) {
+ var1 = var2;
+ var2 = null;
+ }
+
+ if (var1 == null) {
+ this.setInventorySlotContents(2, (ItemStack) null);
+ } else {
+ MerchantRecipeList var3 = this.theMerchant.getRecipes(this.thePlayer);
+
+ if (var3 != null) {
+ MerchantRecipe var4 = var3.canRecipeBeUsed(var1, var2, this.currentRecipeIndex);
+
+ if (var4 != null && !var4.func_82784_g()) {
+ this.currentRecipe = var4;
+ this.setInventorySlotContents(2, var4.getItemToSell().copy());
+ } else if (var2 != null) {
+ var4 = var3.canRecipeBeUsed(var2, var1, this.currentRecipeIndex);
+
+ if (var4 != null && !var4.func_82784_g()) {
+ this.currentRecipe = var4;
+ this.setInventorySlotContents(2, var4.getItemToSell().copy());
+ } else {
+ this.setInventorySlotContents(2, (ItemStack) null);
+ }
+ } else {
+ this.setInventorySlotContents(2, (ItemStack) null);
+ }
+ }
+ }
+ }
+
+ public MerchantRecipe getCurrentRecipe() {
+ return this.currentRecipe;
+ }
+
+ public void setCurrentRecipeIndex(int par1) {
+ this.currentRecipeIndex = par1;
+ this.resetRecipeAndSlots();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/InventoryPlayer.java b/sp-server/src/main/java/net/minecraft/src/InventoryPlayer.java
new file mode 100644
index 0000000..8b9b7b7
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/InventoryPlayer.java
@@ -0,0 +1,602 @@
+package net.minecraft.src;
+
+public class InventoryPlayer implements IInventory {
+ /**
+ * An array of 36 item stacks indicating the main player inventory (including
+ * the visible bar).
+ */
+ public ItemStack[] mainInventory = new ItemStack[36];
+
+ /** An array of 4 item stacks containing the currently worn armor pieces. */
+ public ItemStack[] armorInventory = new ItemStack[4];
+
+ /** The index of the currently held item (0-8). */
+ public int currentItem = 0;
+
+ /** The player whose inventory this is. */
+ public EntityPlayer player;
+ private ItemStack itemStack;
+
+ /**
+ * Set true whenever the inventory changes. Nothing sets it false so you will
+ * have to write your own code to check it and reset the value.
+ */
+ public boolean inventoryChanged = false;
+
+ public InventoryPlayer(EntityPlayer par1EntityPlayer) {
+ this.player = par1EntityPlayer;
+ }
+
+ /**
+ * Returns the item stack currently held by the player.
+ */
+ public ItemStack getCurrentItem() {
+ return this.currentItem < 9 && this.currentItem >= 0 ? this.mainInventory[this.currentItem] : null;
+ }
+
+ /**
+ * Get the size of the player hotbar inventory
+ */
+ public static int getHotbarSize() {
+ return 9;
+ }
+
+ /**
+ * Returns a slot index in main inventory containing a specific itemID
+ */
+ private int getInventorySlotContainItem(int par1) {
+ for (int var2 = 0; var2 < this.mainInventory.length; ++var2) {
+ if (this.mainInventory[var2] != null && this.mainInventory[var2].itemID == par1) {
+ return var2;
+ }
+ }
+
+ return -1;
+ }
+
+ /**
+ * stores an itemstack in the users inventory
+ */
+ private int storeItemStack(ItemStack par1ItemStack) {
+ for (int var2 = 0; var2 < this.mainInventory.length; ++var2) {
+ if (this.mainInventory[var2] != null && this.mainInventory[var2].itemID == par1ItemStack.itemID
+ && this.mainInventory[var2].isStackable()
+ && this.mainInventory[var2].stackSize < this.mainInventory[var2].getMaxStackSize()
+ && this.mainInventory[var2].stackSize < this.getInventoryStackLimit()
+ && (!this.mainInventory[var2].getHasSubtypes()
+ || this.mainInventory[var2].getItemDamage() == par1ItemStack.getItemDamage())
+ && ItemStack.areItemStackTagsEqual(this.mainInventory[var2], par1ItemStack)) {
+ return var2;
+ }
+ }
+
+ return -1;
+ }
+
+ /**
+ * Returns the first item stack that is empty.
+ */
+ public int getFirstEmptyStack() {
+ for (int var1 = 0; var1 < this.mainInventory.length; ++var1) {
+ if (this.mainInventory[var1] == null) {
+ return var1;
+ }
+ }
+
+ return -1;
+ }
+
+ /**
+ * Clear this player's inventory, using the specified ID and metadata as filters
+ * or -1 for no filter.
+ */
+ public int clearInventory(int par1, int par2) {
+ int var3 = 0;
+ int var4;
+ ItemStack var5;
+
+ for (var4 = 0; var4 < this.mainInventory.length; ++var4) {
+ var5 = this.mainInventory[var4];
+
+ if (var5 != null && (par1 <= -1 || var5.itemID == par1) && (par2 <= -1 || var5.getItemDamage() == par2)) {
+ var3 += var5.stackSize;
+ this.mainInventory[var4] = null;
+ }
+ }
+
+ for (var4 = 0; var4 < this.armorInventory.length; ++var4) {
+ var5 = this.armorInventory[var4];
+
+ if (var5 != null && (par1 <= -1 || var5.itemID == par1) && (par2 <= -1 || var5.getItemDamage() == par2)) {
+ var3 += var5.stackSize;
+ this.armorInventory[var4] = null;
+ }
+ }
+
+ return var3;
+ }
+
+ /**
+ * This function stores as many items of an ItemStack as possible in a matching
+ * slot and returns the quantity of left over items.
+ */
+ private int storePartialItemStack(ItemStack par1ItemStack) {
+ int var2 = par1ItemStack.itemID;
+ int var3 = par1ItemStack.stackSize;
+ int var4;
+
+ if (par1ItemStack.getMaxStackSize() == 1) {
+ var4 = this.getFirstEmptyStack();
+
+ if (var4 < 0) {
+ return var3;
+ } else {
+ if (this.mainInventory[var4] == null) {
+ this.mainInventory[var4] = ItemStack.copyItemStack(par1ItemStack);
+ }
+
+ return 0;
+ }
+ } else {
+ var4 = this.storeItemStack(par1ItemStack);
+
+ if (var4 < 0) {
+ var4 = this.getFirstEmptyStack();
+ }
+
+ if (var4 < 0) {
+ return var3;
+ } else {
+ if (this.mainInventory[var4] == null) {
+ this.mainInventory[var4] = new ItemStack(var2, 0, par1ItemStack.getItemDamage());
+
+ if (par1ItemStack.hasTagCompound()) {
+ this.mainInventory[var4].setTagCompound((NBTTagCompound) par1ItemStack.getTagCompound().copy());
+ }
+ }
+
+ int var5 = var3;
+
+ if (var3 > this.mainInventory[var4].getMaxStackSize() - this.mainInventory[var4].stackSize) {
+ var5 = this.mainInventory[var4].getMaxStackSize() - this.mainInventory[var4].stackSize;
+ }
+
+ if (var5 > this.getInventoryStackLimit() - this.mainInventory[var4].stackSize) {
+ var5 = this.getInventoryStackLimit() - this.mainInventory[var4].stackSize;
+ }
+
+ if (var5 == 0) {
+ return var3;
+ } else {
+ var3 -= var5;
+ this.mainInventory[var4].stackSize += var5;
+ this.mainInventory[var4].animationsToGo = 5;
+ return var3;
+ }
+ }
+ }
+ }
+
+ /**
+ * Decrement the number of animations remaining. Only called on client side.
+ * This is used to handle the animation of receiving a block.
+ */
+ public void decrementAnimations() {
+ for (int var1 = 0; var1 < this.mainInventory.length; ++var1) {
+ if (this.mainInventory[var1] != null) {
+ this.mainInventory[var1].updateAnimation(this.player.worldObj, this.player, var1,
+ this.currentItem == var1);
+ }
+ }
+ }
+
+ /**
+ * removed one item of specified itemID from inventory (if it is in a stack, the
+ * stack size will reduce with 1)
+ */
+ public boolean consumeInventoryItem(int par1) {
+ int var2 = this.getInventorySlotContainItem(par1);
+
+ if (var2 < 0) {
+ return false;
+ } else {
+ if (--this.mainInventory[var2].stackSize <= 0) {
+ this.mainInventory[var2] = null;
+ }
+
+ return true;
+ }
+ }
+
+ /**
+ * Get if a specifiied item id is inside the inventory.
+ */
+ public boolean hasItem(int par1) {
+ int var2 = this.getInventorySlotContainItem(par1);
+ return var2 >= 0;
+ }
+
+ /**
+ * Adds the item stack to the inventory, returns false if it is impossible.
+ */
+ public boolean addItemStackToInventory(ItemStack par1ItemStack) {
+ if (par1ItemStack == null) {
+ return false;
+ } else {
+ int var2;
+
+ if (par1ItemStack.isItemDamaged()) {
+ var2 = this.getFirstEmptyStack();
+
+ if (var2 >= 0) {
+ this.mainInventory[var2] = ItemStack.copyItemStack(par1ItemStack);
+ this.mainInventory[var2].animationsToGo = 5;
+ par1ItemStack.stackSize = 0;
+ return true;
+ } else if (this.player.capabilities.isCreativeMode) {
+ par1ItemStack.stackSize = 0;
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ do {
+ var2 = par1ItemStack.stackSize;
+ par1ItemStack.stackSize = this.storePartialItemStack(par1ItemStack);
+ } while (par1ItemStack.stackSize > 0 && par1ItemStack.stackSize < var2);
+
+ if (par1ItemStack.stackSize == var2 && this.player.capabilities.isCreativeMode) {
+ par1ItemStack.stackSize = 0;
+ return true;
+ } else {
+ return par1ItemStack.stackSize < var2;
+ }
+ }
+ }
+ }
+
+ /**
+ * Removes from an inventory slot (first arg) up to a specified number (second
+ * arg) of items and returns them in a new stack.
+ */
+ public ItemStack decrStackSize(int par1, int par2) {
+ ItemStack[] var3 = this.mainInventory;
+
+ if (par1 >= this.mainInventory.length) {
+ var3 = this.armorInventory;
+ par1 -= this.mainInventory.length;
+ }
+
+ if (var3[par1] != null) {
+ ItemStack var4;
+
+ if (var3[par1].stackSize <= par2) {
+ var4 = var3[par1];
+ var3[par1] = null;
+ return var4;
+ } else {
+ var4 = var3[par1].splitStack(par2);
+
+ if (var3[par1].stackSize == 0) {
+ var3[par1] = null;
+ }
+
+ return var4;
+ }
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * When some containers are closed they call this on each slot, then drop
+ * whatever it returns as an EntityItem - like when you close a workbench GUI.
+ */
+ public ItemStack getStackInSlotOnClosing(int par1) {
+ ItemStack[] var2 = this.mainInventory;
+
+ if (par1 >= this.mainInventory.length) {
+ var2 = this.armorInventory;
+ par1 -= this.mainInventory.length;
+ }
+
+ if (var2[par1] != null) {
+ ItemStack var3 = var2[par1];
+ var2[par1] = null;
+ return var3;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Sets the given item stack to the specified slot in the inventory (can be
+ * crafting or armor sections).
+ */
+ public void setInventorySlotContents(int par1, ItemStack par2ItemStack) {
+ ItemStack[] var3 = this.mainInventory;
+
+ if (par1 >= var3.length) {
+ par1 -= var3.length;
+ var3 = this.armorInventory;
+ }
+
+ var3[par1] = par2ItemStack;
+ }
+
+ /**
+ * Gets the strength of the current item (tool) against the specified block,
+ * 1.0f if not holding anything.
+ */
+ public float getStrVsBlock(Block par1Block) {
+ float var2 = 1.0F;
+
+ if (this.mainInventory[this.currentItem] != null) {
+ var2 *= this.mainInventory[this.currentItem].getStrVsBlock(par1Block);
+ }
+
+ return var2;
+ }
+
+ /**
+ * Writes the inventory out as a list of compound tags. This is where the slot
+ * indices are used (+100 for armor, +80 for crafting).
+ */
+ public NBTTagList writeToNBT(NBTTagList par1NBTTagList) {
+ int var2;
+ NBTTagCompound var3;
+
+ for (var2 = 0; var2 < this.mainInventory.length; ++var2) {
+ if (this.mainInventory[var2] != null) {
+ var3 = new NBTTagCompound();
+ var3.setByte("Slot", (byte) var2);
+ this.mainInventory[var2].writeToNBT(var3);
+ par1NBTTagList.appendTag(var3);
+ }
+ }
+
+ for (var2 = 0; var2 < this.armorInventory.length; ++var2) {
+ if (this.armorInventory[var2] != null) {
+ var3 = new NBTTagCompound();
+ var3.setByte("Slot", (byte) (var2 + 100));
+ this.armorInventory[var2].writeToNBT(var3);
+ par1NBTTagList.appendTag(var3);
+ }
+ }
+
+ return par1NBTTagList;
+ }
+
+ /**
+ * Reads from the given tag list and fills the slots in the inventory with the
+ * correct items.
+ */
+ public void readFromNBT(NBTTagList par1NBTTagList) {
+ this.mainInventory = new ItemStack[36];
+ this.armorInventory = new ItemStack[4];
+
+ for (int var2 = 0; var2 < par1NBTTagList.tagCount(); ++var2) {
+ NBTTagCompound var3 = (NBTTagCompound) par1NBTTagList.tagAt(var2);
+ int var4 = var3.getByte("Slot") & 255;
+ ItemStack var5 = ItemStack.loadItemStackFromNBT(var3);
+
+ if (var5 != null) {
+ if (var4 >= 0 && var4 < this.mainInventory.length) {
+ this.mainInventory[var4] = var5;
+ }
+
+ if (var4 >= 100 && var4 < this.armorInventory.length + 100) {
+ this.armorInventory[var4 - 100] = var5;
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the number of slots in the inventory.
+ */
+ public int getSizeInventory() {
+ return this.mainInventory.length + 4;
+ }
+
+ /**
+ * Returns the stack in slot i
+ */
+ public ItemStack getStackInSlot(int par1) {
+ ItemStack[] var2 = this.mainInventory;
+
+ if (par1 >= var2.length) {
+ par1 -= var2.length;
+ var2 = this.armorInventory;
+ }
+
+ return var2[par1];
+ }
+
+ /**
+ * Returns the name of the inventory.
+ */
+ public String getInvName() {
+ return "container.inventory";
+ }
+
+ /**
+ * If this returns false, the inventory name will be used as an unlocalized
+ * name, and translated into the player's language. Otherwise it will be used
+ * directly.
+ */
+ public boolean isInvNameLocalized() {
+ return false;
+ }
+
+ /**
+ * Returns the maximum stack size for a inventory slot. Seems to always be 64,
+ * possibly will be extended. *Isn't this more of a set than a get?*
+ */
+ public int getInventoryStackLimit() {
+ return 64;
+ }
+
+ /**
+ * Return damage vs an entity done by the current held weapon, or 1 if nothing
+ * is held
+ */
+ public int getDamageVsEntity(Entity par1Entity) {
+ ItemStack var2 = this.getStackInSlot(this.currentItem);
+ return var2 != null ? var2.getDamageVsEntity(par1Entity) : 1;
+ }
+
+ /**
+ * Returns whether the current item (tool) can harvest from the specified block
+ * (actually get a result).
+ */
+ public boolean canHarvestBlock(Block par1Block) {
+ if (par1Block.blockMaterial.isToolNotRequired()) {
+ return true;
+ } else {
+ ItemStack var2 = this.getStackInSlot(this.currentItem);
+ return var2 != null ? var2.canHarvestBlock(par1Block) : false;
+ }
+ }
+
+ /**
+ * returns a player armor item (as itemstack) contained in specified armor slot.
+ */
+ public ItemStack armorItemInSlot(int par1) {
+ return this.armorInventory[par1];
+ }
+
+ /**
+ * Based on the damage values and maximum damage values of each armor item,
+ * returns the current armor value.
+ */
+ public int getTotalArmorValue() {
+ int var1 = 0;
+
+ for (int var2 = 0; var2 < this.armorInventory.length; ++var2) {
+ if (this.armorInventory[var2] != null && this.armorInventory[var2].getItem() instanceof ItemArmor) {
+ int var3 = ((ItemArmor) this.armorInventory[var2].getItem()).damageReduceAmount;
+ var1 += var3;
+ }
+ }
+
+ return var1;
+ }
+
+ /**
+ * Damages armor in each slot by the specified amount.
+ */
+ public void damageArmor(int par1) {
+ par1 /= 4;
+
+ if (par1 < 1) {
+ par1 = 1;
+ }
+
+ for (int var2 = 0; var2 < this.armorInventory.length; ++var2) {
+ if (this.armorInventory[var2] != null && this.armorInventory[var2].getItem() instanceof ItemArmor) {
+ this.armorInventory[var2].damageItem(par1, this.player);
+
+ if (this.armorInventory[var2].stackSize == 0) {
+ this.armorInventory[var2] = null;
+ }
+ }
+ }
+ }
+
+ /**
+ * Drop all armor and main inventory items.
+ */
+ public void dropAllItems() {
+ int var1;
+
+ for (var1 = 0; var1 < this.mainInventory.length; ++var1) {
+ if (this.mainInventory[var1] != null) {
+ this.player.dropPlayerItemWithRandomChoice(this.mainInventory[var1], true);
+ this.mainInventory[var1] = null;
+ }
+ }
+
+ for (var1 = 0; var1 < this.armorInventory.length; ++var1) {
+ if (this.armorInventory[var1] != null) {
+ this.player.dropPlayerItemWithRandomChoice(this.armorInventory[var1], true);
+ this.armorInventory[var1] = null;
+ }
+ }
+ }
+
+ /**
+ * Called when an the contents of an Inventory change, usually
+ */
+ public void onInventoryChanged() {
+ this.inventoryChanged = true;
+ }
+
+ public void setItemStack(ItemStack par1ItemStack) {
+ this.itemStack = par1ItemStack;
+ }
+
+ public ItemStack getItemStack() {
+ return this.itemStack;
+ }
+
+ /**
+ * Do not make give this method the name canInteractWith because it clashes with
+ * Container
+ */
+ public boolean isUseableByPlayer(EntityPlayer par1EntityPlayer) {
+ return this.player.isDead ? false : par1EntityPlayer.getDistanceSqToEntity(this.player) <= 64.0D;
+ }
+
+ /**
+ * Returns true if the specified ItemStack exists in the inventory.
+ */
+ public boolean hasItemStack(ItemStack par1ItemStack) {
+ int var2;
+
+ for (var2 = 0; var2 < this.armorInventory.length; ++var2) {
+ if (this.armorInventory[var2] != null && this.armorInventory[var2].isItemEqual(par1ItemStack)) {
+ return true;
+ }
+ }
+
+ for (var2 = 0; var2 < this.mainInventory.length; ++var2) {
+ if (this.mainInventory[var2] != null && this.mainInventory[var2].isItemEqual(par1ItemStack)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public void openChest() {
+ }
+
+ public void closeChest() {
+ }
+
+ /**
+ * Returns true if automation is allowed to insert the given stack (ignoring
+ * stack size) into the given slot.
+ */
+ public boolean isStackValidForSlot(int par1, ItemStack par2ItemStack) {
+ return true;
+ }
+
+ /**
+ * Copy the ItemStack contents from another InventoryPlayer instance
+ */
+ public void copyInventory(InventoryPlayer par1InventoryPlayer) {
+ int var2;
+
+ for (var2 = 0; var2 < this.mainInventory.length; ++var2) {
+ this.mainInventory[var2] = ItemStack.copyItemStack(par1InventoryPlayer.mainInventory[var2]);
+ }
+
+ for (var2 = 0; var2 < this.armorInventory.length; ++var2) {
+ this.armorInventory[var2] = ItemStack.copyItemStack(par1InventoryPlayer.armorInventory[var2]);
+ }
+
+ this.currentItem = par1InventoryPlayer.currentItem;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/InventoryRepair.java b/sp-server/src/main/java/net/minecraft/src/InventoryRepair.java
new file mode 100644
index 0000000..cb54cf2
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/InventoryRepair.java
@@ -0,0 +1,27 @@
+package net.minecraft.src;
+
+class InventoryRepair extends InventoryBasic {
+ /** Container of this anvil's block. */
+ final ContainerRepair theContainer;
+
+ InventoryRepair(ContainerRepair par1ContainerRepair, String par2Str, boolean par3, int par4) {
+ super(par2Str, par3, par4);
+ this.theContainer = par1ContainerRepair;
+ }
+
+ /**
+ * Called when an the contents of an Inventory change, usually
+ */
+ public void onInventoryChanged() {
+ super.onInventoryChanged();
+ this.theContainer.onCraftMatrixChanged(this);
+ }
+
+ /**
+ * Returns true if automation is allowed to insert the given stack (ignoring
+ * stack size) into the given slot.
+ */
+ public boolean isStackValidForSlot(int par1, ItemStack par2ItemStack) {
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Item.java b/sp-server/src/main/java/net/minecraft/src/Item.java
new file mode 100644
index 0000000..b34eaae
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Item.java
@@ -0,0 +1,620 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class Item {
+ private CreativeTabs tabToDisplayOn = null;
+
+ /** The RNG used by the Item subclasses. */
+ protected static EaglercraftRandom itemRand = new EaglercraftRandom();
+
+ /** A 32000 elements Item array. */
+ public static Item[] itemsList = new Item[32000];
+ public static Item shovelIron = (new ItemSpade(0, EnumToolMaterial.IRON)).setUnlocalizedName("shovelIron");
+ public static Item pickaxeIron = (new ItemPickaxe(1, EnumToolMaterial.IRON)).setUnlocalizedName("pickaxeIron");
+ public static Item axeIron = (new ItemAxe(2, EnumToolMaterial.IRON)).setUnlocalizedName("hatchetIron");
+ public static Item flintAndSteel = (new ItemFlintAndSteel(3)).setUnlocalizedName("flintAndSteel");
+ public static Item appleRed = (new ItemFood(4, 4, 0.3F, false)).setUnlocalizedName("apple");
+ public static ItemBow bow = (ItemBow) (new ItemBow(5)).setUnlocalizedName("bow");
+ public static Item arrow = (new Item(6)).setUnlocalizedName("arrow").setCreativeTab(CreativeTabs.tabCombat);
+ public static Item coal = (new ItemCoal(7)).setUnlocalizedName("coal");
+ public static Item diamond = (new Item(8)).setUnlocalizedName("diamond").setCreativeTab(CreativeTabs.tabMaterials);
+ public static Item ingotIron = (new Item(9)).setUnlocalizedName("ingotIron")
+ .setCreativeTab(CreativeTabs.tabMaterials);
+ public static Item ingotGold = (new Item(10)).setUnlocalizedName("ingotGold")
+ .setCreativeTab(CreativeTabs.tabMaterials);
+ public static Item swordIron = (new ItemSword(11, EnumToolMaterial.IRON)).setUnlocalizedName("swordIron");
+ public static Item swordWood = (new ItemSword(12, EnumToolMaterial.WOOD)).setUnlocalizedName("swordWood");
+ public static Item shovelWood = (new ItemSpade(13, EnumToolMaterial.WOOD)).setUnlocalizedName("shovelWood");
+ public static Item pickaxeWood = (new ItemPickaxe(14, EnumToolMaterial.WOOD)).setUnlocalizedName("pickaxeWood");
+ public static Item axeWood = (new ItemAxe(15, EnumToolMaterial.WOOD)).setUnlocalizedName("hatchetWood");
+ public static Item swordStone = (new ItemSword(16, EnumToolMaterial.STONE)).setUnlocalizedName("swordStone");
+ public static Item shovelStone = (new ItemSpade(17, EnumToolMaterial.STONE)).setUnlocalizedName("shovelStone");
+ public static Item pickaxeStone = (new ItemPickaxe(18, EnumToolMaterial.STONE)).setUnlocalizedName("pickaxeStone");
+ public static Item axeStone = (new ItemAxe(19, EnumToolMaterial.STONE)).setUnlocalizedName("hatchetStone");
+ public static Item swordDiamond = (new ItemSword(20, EnumToolMaterial.EMERALD)).setUnlocalizedName("swordDiamond");
+ public static Item shovelDiamond = (new ItemSpade(21, EnumToolMaterial.EMERALD))
+ .setUnlocalizedName("shovelDiamond");
+ public static Item pickaxeDiamond = (new ItemPickaxe(22, EnumToolMaterial.EMERALD))
+ .setUnlocalizedName("pickaxeDiamond");
+ public static Item axeDiamond = (new ItemAxe(23, EnumToolMaterial.EMERALD)).setUnlocalizedName("hatchetDiamond");
+ public static Item stick = (new Item(24)).setFull3D().setUnlocalizedName("stick")
+ .setCreativeTab(CreativeTabs.tabMaterials);
+ public static Item bowlEmpty = (new Item(25)).setUnlocalizedName("bowl").setCreativeTab(CreativeTabs.tabMaterials);
+ public static Item bowlSoup = (new ItemSoup(26, 6)).setUnlocalizedName("mushroomStew");
+ public static Item swordGold = (new ItemSword(27, EnumToolMaterial.GOLD)).setUnlocalizedName("swordGold");
+ public static Item shovelGold = (new ItemSpade(28, EnumToolMaterial.GOLD)).setUnlocalizedName("shovelGold");
+ public static Item pickaxeGold = (new ItemPickaxe(29, EnumToolMaterial.GOLD)).setUnlocalizedName("pickaxeGold");
+ public static Item axeGold = (new ItemAxe(30, EnumToolMaterial.GOLD)).setUnlocalizedName("hatchetGold");
+ public static Item silk = (new ItemReed(31, Block.tripWire)).setUnlocalizedName("string")
+ .setCreativeTab(CreativeTabs.tabMaterials);
+ public static Item feather = (new Item(32)).setUnlocalizedName("feather").setCreativeTab(CreativeTabs.tabMaterials);
+ public static Item gunpowder = (new Item(33)).setUnlocalizedName("sulphur")
+ .setPotionEffect(PotionHelper.gunpowderEffect).setCreativeTab(CreativeTabs.tabMaterials);
+ public static Item hoeWood = (new ItemHoe(34, EnumToolMaterial.WOOD)).setUnlocalizedName("hoeWood");
+ public static Item hoeStone = (new ItemHoe(35, EnumToolMaterial.STONE)).setUnlocalizedName("hoeStone");
+ public static Item hoeIron = (new ItemHoe(36, EnumToolMaterial.IRON)).setUnlocalizedName("hoeIron");
+ public static Item hoeDiamond = (new ItemHoe(37, EnumToolMaterial.EMERALD)).setUnlocalizedName("hoeDiamond");
+ public static Item hoeGold = (new ItemHoe(38, EnumToolMaterial.GOLD)).setUnlocalizedName("hoeGold");
+ public static Item seeds = (new ItemSeeds(39, Block.crops.blockID, Block.tilledField.blockID))
+ .setUnlocalizedName("seeds");
+ public static Item wheat = (new Item(40)).setUnlocalizedName("wheat").setCreativeTab(CreativeTabs.tabMaterials);
+ public static Item bread = (new ItemFood(41, 5, 0.6F, false)).setUnlocalizedName("bread");
+ public static ItemArmor helmetLeather = (ItemArmor) (new ItemArmor(42, EnumArmorMaterial.CLOTH, 0, 0))
+ .setUnlocalizedName("helmetCloth");
+ public static ItemArmor plateLeather = (ItemArmor) (new ItemArmor(43, EnumArmorMaterial.CLOTH, 0, 1))
+ .setUnlocalizedName("chestplateCloth");
+ public static ItemArmor legsLeather = (ItemArmor) (new ItemArmor(44, EnumArmorMaterial.CLOTH, 0, 2))
+ .setUnlocalizedName("leggingsCloth");
+ public static ItemArmor bootsLeather = (ItemArmor) (new ItemArmor(45, EnumArmorMaterial.CLOTH, 0, 3))
+ .setUnlocalizedName("bootsCloth");
+ public static ItemArmor helmetChain = (ItemArmor) (new ItemArmor(46, EnumArmorMaterial.CHAIN, 1, 0))
+ .setUnlocalizedName("helmetChain");
+ public static ItemArmor plateChain = (ItemArmor) (new ItemArmor(47, EnumArmorMaterial.CHAIN, 1, 1))
+ .setUnlocalizedName("chestplateChain");
+ public static ItemArmor legsChain = (ItemArmor) (new ItemArmor(48, EnumArmorMaterial.CHAIN, 1, 2))
+ .setUnlocalizedName("leggingsChain");
+ public static ItemArmor bootsChain = (ItemArmor) (new ItemArmor(49, EnumArmorMaterial.CHAIN, 1, 3))
+ .setUnlocalizedName("bootsChain");
+ public static ItemArmor helmetIron = (ItemArmor) (new ItemArmor(50, EnumArmorMaterial.IRON, 2, 0))
+ .setUnlocalizedName("helmetIron");
+ public static ItemArmor plateIron = (ItemArmor) (new ItemArmor(51, EnumArmorMaterial.IRON, 2, 1))
+ .setUnlocalizedName("chestplateIron");
+ public static ItemArmor legsIron = (ItemArmor) (new ItemArmor(52, EnumArmorMaterial.IRON, 2, 2))
+ .setUnlocalizedName("leggingsIron");
+ public static ItemArmor bootsIron = (ItemArmor) (new ItemArmor(53, EnumArmorMaterial.IRON, 2, 3))
+ .setUnlocalizedName("bootsIron");
+ public static ItemArmor helmetDiamond = (ItemArmor) (new ItemArmor(54, EnumArmorMaterial.DIAMOND, 3, 0))
+ .setUnlocalizedName("helmetDiamond");
+ public static ItemArmor plateDiamond = (ItemArmor) (new ItemArmor(55, EnumArmorMaterial.DIAMOND, 3, 1))
+ .setUnlocalizedName("chestplateDiamond");
+ public static ItemArmor legsDiamond = (ItemArmor) (new ItemArmor(56, EnumArmorMaterial.DIAMOND, 3, 2))
+ .setUnlocalizedName("leggingsDiamond");
+ public static ItemArmor bootsDiamond = (ItemArmor) (new ItemArmor(57, EnumArmorMaterial.DIAMOND, 3, 3))
+ .setUnlocalizedName("bootsDiamond");
+ public static ItemArmor helmetGold = (ItemArmor) (new ItemArmor(58, EnumArmorMaterial.GOLD, 4, 0))
+ .setUnlocalizedName("helmetGold");
+ public static ItemArmor plateGold = (ItemArmor) (new ItemArmor(59, EnumArmorMaterial.GOLD, 4, 1))
+ .setUnlocalizedName("chestplateGold");
+ public static ItemArmor legsGold = (ItemArmor) (new ItemArmor(60, EnumArmorMaterial.GOLD, 4, 2))
+ .setUnlocalizedName("leggingsGold");
+ public static ItemArmor bootsGold = (ItemArmor) (new ItemArmor(61, EnumArmorMaterial.GOLD, 4, 3))
+ .setUnlocalizedName("bootsGold");
+ public static Item flint = (new Item(62)).setUnlocalizedName("flint").setCreativeTab(CreativeTabs.tabMaterials);
+ public static Item porkRaw = (new ItemFood(63, 3, 0.3F, true)).setUnlocalizedName("porkchopRaw");
+ public static Item porkCooked = (new ItemFood(64, 8, 0.8F, true)).setUnlocalizedName("porkchopCooked");
+ public static Item painting = (new ItemHangingEntity(65, EntityPainting.class)).setUnlocalizedName("painting");
+ public static Item appleGold = (new ItemAppleGold(66, 4, 1.2F, false)).setAlwaysEdible()
+ .setPotionEffect(Potion.regeneration.id, 5, 0, 1.0F).setUnlocalizedName("appleGold");
+ public static Item sign = (new ItemSign(67)).setUnlocalizedName("sign");
+ public static Item doorWood = (new ItemDoor(68, Material.wood)).setUnlocalizedName("doorWood");
+ public static Item bucketEmpty = (new ItemBucket(69, 0)).setUnlocalizedName("bucket").setMaxStackSize(16);
+ public static Item bucketWater = (new ItemBucket(70, Block.waterMoving.blockID)).setUnlocalizedName("bucketWater")
+ .setContainerItem(bucketEmpty);
+ public static Item bucketLava = (new ItemBucket(71, Block.lavaMoving.blockID)).setUnlocalizedName("bucketLava")
+ .setContainerItem(bucketEmpty);
+ public static Item minecartEmpty = (new ItemMinecart(72, 0)).setUnlocalizedName("minecart");
+ public static Item saddle = (new ItemSaddle(73)).setUnlocalizedName("saddle");
+ public static Item doorIron = (new ItemDoor(74, Material.iron)).setUnlocalizedName("doorIron");
+ public static Item redstone = (new ItemRedstone(75)).setUnlocalizedName("redstone")
+ .setPotionEffect(PotionHelper.redstoneEffect);
+ public static Item snowball = (new ItemSnowball(76)).setUnlocalizedName("snowball");
+ public static Item boat = (new ItemBoat(77)).setUnlocalizedName("boat");
+ public static Item leather = (new Item(78)).setUnlocalizedName("leather").setCreativeTab(CreativeTabs.tabMaterials);
+ public static Item bucketMilk = (new ItemBucketMilk(79)).setUnlocalizedName("milk").setContainerItem(bucketEmpty);
+ public static Item brick = (new Item(80)).setUnlocalizedName("brick").setCreativeTab(CreativeTabs.tabMaterials);
+ public static Item clay = (new Item(81)).setUnlocalizedName("clay").setCreativeTab(CreativeTabs.tabMaterials);
+ public static Item reed = (new ItemReed(82, Block.reed)).setUnlocalizedName("reeds")
+ .setCreativeTab(CreativeTabs.tabMaterials);
+ public static Item paper = (new Item(83)).setUnlocalizedName("paper").setCreativeTab(CreativeTabs.tabMisc);
+ public static Item book = (new ItemBook(84)).setUnlocalizedName("book").setCreativeTab(CreativeTabs.tabMisc);
+ public static Item slimeBall = (new Item(85)).setUnlocalizedName("slimeball").setCreativeTab(CreativeTabs.tabMisc);
+ public static Item minecartCrate = (new ItemMinecart(86, 1)).setUnlocalizedName("minecartChest");
+ public static Item minecartPowered = (new ItemMinecart(87, 2)).setUnlocalizedName("minecartFurnace");
+ public static Item egg = (new ItemEgg(88)).setUnlocalizedName("egg");
+ public static Item compass = (new Item(89)).setUnlocalizedName("compass").setCreativeTab(CreativeTabs.tabTools);
+ public static ItemFishingRod fishingRod = (ItemFishingRod) (new ItemFishingRod(90))
+ .setUnlocalizedName("fishingRod");
+ public static Item pocketSundial = (new Item(91)).setUnlocalizedName("clock").setCreativeTab(CreativeTabs.tabTools);
+ public static Item lightStoneDust = (new Item(92)).setUnlocalizedName("yellowDust")
+ .setPotionEffect(PotionHelper.glowstoneEffect).setCreativeTab(CreativeTabs.tabMaterials);
+ public static Item fishRaw = (new ItemFood(93, 2, 0.3F, false)).setUnlocalizedName("fishRaw");
+ public static Item fishCooked = (new ItemFood(94, 5, 0.6F, false)).setUnlocalizedName("fishCooked");
+ public static Item dyePowder = (new ItemDye(95)).setUnlocalizedName("dyePowder");
+ public static Item bone = (new Item(96)).setUnlocalizedName("bone").setFull3D()
+ .setCreativeTab(CreativeTabs.tabMisc);
+ public static Item sugar = (new Item(97)).setUnlocalizedName("sugar").setPotionEffect(PotionHelper.sugarEffect)
+ .setCreativeTab(CreativeTabs.tabMaterials);
+ public static Item cake = (new ItemReed(98, Block.cake)).setMaxStackSize(1).setUnlocalizedName("cake")
+ .setCreativeTab(CreativeTabs.tabFood);
+ public static Item bed = (new ItemBed(99)).setMaxStackSize(1).setUnlocalizedName("bed");
+ public static Item redstoneRepeater = (new ItemReed(100, Block.redstoneRepeaterIdle)).setUnlocalizedName("diode")
+ .setCreativeTab(CreativeTabs.tabRedstone);
+ public static Item cookie = (new ItemFood(101, 2, 0.1F, false)).setUnlocalizedName("cookie");
+ public static ItemMap map = (ItemMap) (new ItemMap(102)).setUnlocalizedName("map");
+
+ /**
+ * Item introduced on 1.7 version, is a shear to cut leaves (you can keep the
+ * block) or get wool from sheeps.
+ */
+ public static ItemShears shears = (ItemShears) (new ItemShears(103)).setUnlocalizedName("shears");
+ public static Item melon = (new ItemFood(104, 2, 0.3F, false)).setUnlocalizedName("melon");
+ public static Item pumpkinSeeds = (new ItemSeeds(105, Block.pumpkinStem.blockID, Block.tilledField.blockID))
+ .setUnlocalizedName("seeds_pumpkin");
+ public static Item melonSeeds = (new ItemSeeds(106, Block.melonStem.blockID, Block.tilledField.blockID))
+ .setUnlocalizedName("seeds_melon");
+ public static Item beefRaw = (new ItemFood(107, 3, 0.3F, true)).setUnlocalizedName("beefRaw");
+ public static Item beefCooked = (new ItemFood(108, 8, 0.8F, true)).setUnlocalizedName("beefCooked");
+ public static Item chickenRaw = (new ItemFood(109, 2, 0.3F, true)).setPotionEffect(Potion.hunger.id, 30, 0, 0.3F)
+ .setUnlocalizedName("chickenRaw");
+ public static Item chickenCooked = (new ItemFood(110, 6, 0.6F, true)).setUnlocalizedName("chickenCooked");
+ public static Item rottenFlesh = (new ItemFood(111, 4, 0.1F, true)).setPotionEffect(Potion.hunger.id, 30, 0, 0.8F)
+ .setUnlocalizedName("rottenFlesh");
+ public static Item enderPearl = (new ItemEnderPearl(112)).setUnlocalizedName("enderPearl");
+ public static Item blazeRod = (new Item(113)).setUnlocalizedName("blazeRod")
+ .setCreativeTab(CreativeTabs.tabMaterials);
+ public static Item ghastTear = (new Item(114)).setUnlocalizedName("ghastTear")
+ .setPotionEffect(PotionHelper.ghastTearEffect).setCreativeTab(CreativeTabs.tabBrewing);
+ public static Item goldNugget = (new Item(115)).setUnlocalizedName("goldNugget")
+ .setCreativeTab(CreativeTabs.tabMaterials);
+ public static Item netherStalkSeeds = (new ItemSeeds(116, Block.netherStalk.blockID, Block.slowSand.blockID))
+ .setUnlocalizedName("netherStalkSeeds").setPotionEffect("+4");
+ public static ItemPotion potion = (ItemPotion) (new ItemPotion(117)).setUnlocalizedName("potion");
+ public static Item glassBottle = (new ItemGlassBottle(118)).setUnlocalizedName("glassBottle");
+ public static Item spiderEye = (new ItemFood(119, 2, 0.8F, false)).setPotionEffect(Potion.poison.id, 5, 0, 1.0F)
+ .setUnlocalizedName("spiderEye").setPotionEffect(PotionHelper.spiderEyeEffect);
+ public static Item fermentedSpiderEye = (new Item(120)).setUnlocalizedName("fermentedSpiderEye")
+ .setPotionEffect(PotionHelper.fermentedSpiderEyeEffect).setCreativeTab(CreativeTabs.tabBrewing);
+ public static Item blazePowder = (new Item(121)).setUnlocalizedName("blazePowder")
+ .setPotionEffect(PotionHelper.blazePowderEffect).setCreativeTab(CreativeTabs.tabBrewing);
+ public static Item magmaCream = (new Item(122)).setUnlocalizedName("magmaCream")
+ .setPotionEffect(PotionHelper.magmaCreamEffect).setCreativeTab(CreativeTabs.tabBrewing);
+ public static Item brewingStand = (new ItemReed(123, Block.brewingStand)).setUnlocalizedName("brewingStand")
+ .setCreativeTab(CreativeTabs.tabBrewing);
+ public static Item cauldron = (new ItemReed(124, Block.cauldron)).setUnlocalizedName("cauldron")
+ .setCreativeTab(CreativeTabs.tabBrewing);
+ public static Item eyeOfEnder = (new ItemEnderEye(125)).setUnlocalizedName("eyeOfEnder");
+ public static Item speckledMelon = (new Item(126)).setUnlocalizedName("speckledMelon")
+ .setPotionEffect(PotionHelper.speckledMelonEffect).setCreativeTab(CreativeTabs.tabBrewing);
+ public static Item monsterPlacer = (new ItemMonsterPlacer(127)).setUnlocalizedName("monsterPlacer");
+
+ /**
+ * Bottle o' Enchanting. Drops between 1 and 3 experience orbs when thrown.
+ */
+ public static Item expBottle = (new ItemExpBottle(128)).setUnlocalizedName("expBottle");
+
+ /**
+ * Fire Charge. When used in a dispenser it fires a fireball similiar to a
+ * Ghast's.
+ */
+ public static Item fireballCharge = (new ItemFireball(129)).setUnlocalizedName("fireball");
+ public static Item writableBook = (new ItemWritableBook(130)).setUnlocalizedName("writingBook")
+ .setCreativeTab(CreativeTabs.tabMisc);
+ public static Item writtenBook = (new ItemEditableBook(131)).setUnlocalizedName("writtenBook");
+ public static Item emerald = (new Item(132)).setUnlocalizedName("emerald")
+ .setCreativeTab(CreativeTabs.tabMaterials);
+ public static Item itemFrame = (new ItemHangingEntity(133, EntityItemFrame.class)).setUnlocalizedName("frame");
+ public static Item flowerPot = (new ItemReed(134, Block.flowerPot)).setUnlocalizedName("flowerPot")
+ .setCreativeTab(CreativeTabs.tabDecorations);
+ public static Item carrot = (new ItemSeedFood(135, 4, 0.6F, Block.carrot.blockID, Block.tilledField.blockID))
+ .setUnlocalizedName("carrots");
+ public static Item potato = (new ItemSeedFood(136, 1, 0.3F, Block.potato.blockID, Block.tilledField.blockID))
+ .setUnlocalizedName("potato");
+ public static Item bakedPotato = (new ItemFood(137, 6, 0.6F, false)).setUnlocalizedName("potatoBaked");
+ public static Item poisonousPotato = (new ItemFood(138, 2, 0.3F, false))
+ .setPotionEffect(Potion.poison.id, 5, 0, 0.6F).setUnlocalizedName("potatoPoisonous");
+ public static ItemEmptyMap emptyMap = (ItemEmptyMap) (new ItemEmptyMap(139)).setUnlocalizedName("emptyMap");
+ public static Item goldenCarrot = (new ItemFood(140, 6, 1.2F, false)).setUnlocalizedName("carrotGolden")
+ .setPotionEffect(PotionHelper.goldenCarrotEffect);
+ public static Item skull = (new ItemSkull(141)).setUnlocalizedName("skull");
+ public static Item carrotOnAStick = (new ItemCarrotOnAStick(142)).setUnlocalizedName("carrotOnAStick");
+ public static Item netherStar = (new ItemSimpleFoiled(143)).setUnlocalizedName("netherStar")
+ .setCreativeTab(CreativeTabs.tabMaterials);
+ public static Item pumpkinPie = (new ItemFood(144, 8, 0.3F, false)).setUnlocalizedName("pumpkinPie")
+ .setCreativeTab(CreativeTabs.tabFood);
+ public static Item firework = (new ItemFirework(145)).setUnlocalizedName("fireworks");
+ public static Item fireworkCharge = (new ItemFireworkCharge(146)).setUnlocalizedName("fireworksCharge")
+ .setCreativeTab(CreativeTabs.tabMisc);
+ public static ItemEnchantedBook enchantedBook = (ItemEnchantedBook) (new ItemEnchantedBook(147)).setMaxStackSize(1)
+ .setUnlocalizedName("enchantedBook");
+ public static Item comparator = (new ItemReed(148, Block.redstoneComparatorIdle)).setUnlocalizedName("comparator")
+ .setCreativeTab(CreativeTabs.tabRedstone);
+ public static Item netherrackBrick = (new Item(149)).setUnlocalizedName("netherbrick")
+ .setCreativeTab(CreativeTabs.tabMaterials);
+ public static Item netherQuartz = (new Item(150)).setUnlocalizedName("netherquartz")
+ .setCreativeTab(CreativeTabs.tabMaterials);
+ public static Item tntMinecart = (new ItemMinecart(151, 3)).setUnlocalizedName("minecartTnt");
+ public static Item hopperMinecart = (new ItemMinecart(152, 5)).setUnlocalizedName("minecartHopper");
+ public static Item record13 = (new ItemRecord(2000, "13")).setUnlocalizedName("record");
+ public static Item recordCat = (new ItemRecord(2001, "cat")).setUnlocalizedName("record");
+ public static Item recordBlocks = (new ItemRecord(2002, "blocks")).setUnlocalizedName("record");
+ public static Item recordChirp = (new ItemRecord(2003, "chirp")).setUnlocalizedName("record");
+ public static Item recordFar = (new ItemRecord(2004, "far")).setUnlocalizedName("record");
+ public static Item recordMall = (new ItemRecord(2005, "mall")).setUnlocalizedName("record");
+ public static Item recordMellohi = (new ItemRecord(2006, "mellohi")).setUnlocalizedName("record");
+ public static Item recordStal = (new ItemRecord(2007, "stal")).setUnlocalizedName("record");
+ public static Item recordStrad = (new ItemRecord(2008, "strad")).setUnlocalizedName("record");
+ public static Item recordWard = (new ItemRecord(2009, "ward")).setUnlocalizedName("record");
+ public static Item record11 = (new ItemRecord(2010, "11")).setUnlocalizedName("record");
+ public static Item recordWait = (new ItemRecord(2011, "wait")).setUnlocalizedName("record");
+
+ /** The ID of this item. */
+ public final int itemID;
+
+ /** Maximum size of the stack. */
+ protected int maxStackSize = 64;
+
+ /** Maximum damage an item can handle. */
+ private int maxDamage = 0;
+
+ /** If true, render the object in full 3D, like weapons and tools. */
+ protected boolean bFull3D = false;
+
+ /**
+ * Some items (like dyes) have multiple subtypes on same item, this is field
+ * define this behavior
+ */
+ protected boolean hasSubtypes = false;
+ private Item containerItem = null;
+
+ /**
+ * The string representing this item's effect on a potion when used as an
+ * ingredient.
+ */
+ private String potionEffect = null;
+
+ /** The unlocalized name of this item. */
+ private String unlocalizedName;
+
+ protected Item(int par1) {
+ this.itemID = 256 + par1;
+
+ if (itemsList[256 + par1] != null) {
+ System.out.println("CONFLICT @ " + par1);
+ }
+
+ itemsList[256 + par1] = this;
+ }
+
+ public Item setMaxStackSize(int par1) {
+ this.maxStackSize = par1;
+ return this;
+ }
+
+ /**
+ * Callback for item usage. If the item does something special on right
+ * clicking, he will have one of those. Return True if something happen and
+ * false if it don't. This is for ITEMS, not BLOCKS
+ */
+ public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World par3World, int par4,
+ int par5, int par6, int par7, float par8, float par9, float par10) {
+ return false;
+ }
+
+ /**
+ * Returns the strength of the stack against a given block. 1.0F base,
+ * (Quality+1)*2 if correct blocktype, 1.5F if sword
+ */
+ public float getStrVsBlock(ItemStack par1ItemStack, Block par2Block) {
+ return 1.0F;
+ }
+
+ /**
+ * Called whenever this item is equipped and the right mouse button is pressed.
+ * Args: itemStack, world, entityPlayer
+ */
+ public ItemStack onItemRightClick(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer) {
+ return par1ItemStack;
+ }
+
+ public ItemStack onEaten(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer) {
+ return par1ItemStack;
+ }
+
+ /**
+ * Returns the maximum size of the stack for a specific item. *Isn't this more a
+ * Set than a Get?*
+ */
+ public int getItemStackLimit() {
+ return this.maxStackSize;
+ }
+
+ /**
+ * Returns the metadata of the block which this Item (ItemBlock) can place
+ */
+ public int getMetadata(int par1) {
+ return 0;
+ }
+
+ public boolean getHasSubtypes() {
+ return this.hasSubtypes;
+ }
+
+ protected Item setHasSubtypes(boolean par1) {
+ this.hasSubtypes = par1;
+ return this;
+ }
+
+ /**
+ * Returns the maximum damage an item can take.
+ */
+ public int getMaxDamage() {
+ return this.maxDamage;
+ }
+
+ /**
+ * set max damage of an Item
+ */
+ protected Item setMaxDamage(int par1) {
+ this.maxDamage = par1;
+ return this;
+ }
+
+ public boolean isDamageable() {
+ return this.maxDamage > 0 && !this.hasSubtypes;
+ }
+
+ /**
+ * Current implementations of this method in child classes do not use the entry
+ * argument beside ev. They just raise the damage on the stack.
+ */
+ public boolean hitEntity(ItemStack par1ItemStack, EntityLiving par2EntityLiving, EntityLiving par3EntityLiving) {
+ return false;
+ }
+
+ public boolean onBlockDestroyed(ItemStack par1ItemStack, World par2World, int par3, int par4, int par5, int par6,
+ EntityLiving par7EntityLiving) {
+ return false;
+ }
+
+ /**
+ * Returns the damage against a given entity.
+ */
+ public int getDamageVsEntity(Entity par1Entity) {
+ return 1;
+ }
+
+ /**
+ * Returns if the item (tool) can harvest results from the block type.
+ */
+ public boolean canHarvestBlock(Block par1Block) {
+ return false;
+ }
+
+ /**
+ * Called when a player right clicks an entity with an item.
+ */
+ public boolean useItemOnEntity(ItemStack par1ItemStack, EntityLiving par2EntityLiving) {
+ return false;
+ }
+
+ /**
+ * Sets bFull3D to True and return the object.
+ */
+ public Item setFull3D() {
+ this.bFull3D = true;
+ return this;
+ }
+
+ /**
+ * Sets the unlocalized name of this item to the string passed as the parameter,
+ * prefixed by "item."
+ */
+ public Item setUnlocalizedName(String par1Str) {
+ this.unlocalizedName = par1Str;
+ return this;
+ }
+
+ /**
+ * Gets the localized name of the given item stack.
+ */
+ public String getLocalizedName(ItemStack par1ItemStack) {
+ String var2 = this.getUnlocalizedName(par1ItemStack);
+ return var2 == null ? "" : StatCollector.translateToLocal(var2);
+ }
+
+ /**
+ * Returns the unlocalized name of this item.
+ */
+ public String getUnlocalizedName() {
+ return "item." + this.unlocalizedName;
+ }
+
+ /**
+ * Returns the unlocalized name of this item. This version accepts an ItemStack
+ * so different stacks can have different names based on their damage or NBT.
+ */
+ public String getUnlocalizedName(ItemStack par1ItemStack) {
+ return "item." + this.unlocalizedName;
+ }
+
+ public Item setContainerItem(Item par1Item) {
+ this.containerItem = par1Item;
+ return this;
+ }
+
+ /**
+ * If this returns true, after a recipe involving this item is crafted the
+ * container item will be added to the player's inventory instead of remaining
+ * in the crafting grid.
+ */
+ public boolean doesContainerItemLeaveCraftingGrid(ItemStack par1ItemStack) {
+ return true;
+ }
+
+ /**
+ * If this function returns true (or the item is damageable), the ItemStack's
+ * NBT tag will be sent to the client.
+ */
+ public boolean getShareTag() {
+ return true;
+ }
+
+ public Item getContainerItem() {
+ return this.containerItem;
+ }
+
+ /**
+ * True if this Item has a container item (a.k.a. crafting result)
+ */
+ public boolean hasContainerItem() {
+ return this.containerItem != null;
+ }
+
+ public String getStatName() {
+ return StatCollector.translateToLocal(this.getUnlocalizedName() + ".name");
+ }
+
+ public String func_77653_i(ItemStack par1ItemStack) {
+ return StatCollector.translateToLocal(this.getUnlocalizedName(par1ItemStack) + ".name");
+ }
+
+ /**
+ * Called each tick as long the item is on a player inventory. Uses by maps to
+ * check if is on a player hand and update it's contents.
+ */
+ public void onUpdate(ItemStack par1ItemStack, World par2World, Entity par3Entity, int par4, boolean par5) {
+ }
+
+ /**
+ * Called when item is crafted/smelted. Used only by maps so far.
+ */
+ public void onCreated(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer) {
+ }
+
+ /**
+ * false for all Items except sub-classes of ItemMapBase
+ */
+ public boolean isMap() {
+ return false;
+ }
+
+ /**
+ * returns the action that specifies what animation to play when the items is
+ * being used
+ */
+ public EnumAction getItemUseAction(ItemStack par1ItemStack) {
+ return EnumAction.none;
+ }
+
+ /**
+ * How long it takes to use or consume an item
+ */
+ public int getMaxItemUseDuration(ItemStack par1ItemStack) {
+ return 0;
+ }
+
+ /**
+ * called when the player releases the use item button. Args: itemstack, world,
+ * entityplayer, itemInUseCount
+ */
+ public void onPlayerStoppedUsing(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer,
+ int par4) {
+ }
+
+ /**
+ * Sets the string representing this item's effect on a potion when used as an
+ * ingredient.
+ */
+ protected Item setPotionEffect(String par1Str) {
+ this.potionEffect = par1Str;
+ return this;
+ }
+
+ /**
+ * Returns a string representing what this item does to a potion.
+ */
+ public String getPotionEffect() {
+ return this.potionEffect;
+ }
+
+ /**
+ * Returns true if this item serves as a potion ingredient (its ingredient
+ * information is not null).
+ */
+ public boolean isPotionIngredient() {
+ return this.potionEffect != null;
+ }
+
+ public String getItemDisplayName(ItemStack par1ItemStack) {
+ return ("" + StringTranslate.getInstance().translateNamedKey(this.getLocalizedName(par1ItemStack))).trim();
+ }
+
+ /**
+ * Checks isDamagable and if it cannot be stacked
+ */
+ public boolean isItemTool(ItemStack par1ItemStack) {
+ return this.getItemStackLimit() == 1 && this.isDamageable();
+ }
+
+ protected MovingObjectPosition getMovingObjectPositionFromPlayer(World par1World, EntityPlayer par2EntityPlayer,
+ boolean par3) {
+ float var4 = 1.0F;
+ float var5 = par2EntityPlayer.prevRotationPitch
+ + (par2EntityPlayer.rotationPitch - par2EntityPlayer.prevRotationPitch) * var4;
+ float var6 = par2EntityPlayer.prevRotationYaw
+ + (par2EntityPlayer.rotationYaw - par2EntityPlayer.prevRotationYaw) * var4;
+ double var7 = par2EntityPlayer.prevPosX + (par2EntityPlayer.posX - par2EntityPlayer.prevPosX) * (double) var4;
+ double var9 = par2EntityPlayer.prevPosY + (par2EntityPlayer.posY - par2EntityPlayer.prevPosY) * (double) var4
+ + 1.62D - (double) par2EntityPlayer.yOffset;
+ double var11 = par2EntityPlayer.prevPosZ + (par2EntityPlayer.posZ - par2EntityPlayer.prevPosZ) * (double) var4;
+ Vec3 var13 = par1World.getWorldVec3Pool().getVecFromPool(var7, var9, var11);
+ float var14 = MathHelper.cos(-var6 * 0.017453292F - (float) Math.PI);
+ float var15 = MathHelper.sin(-var6 * 0.017453292F - (float) Math.PI);
+ float var16 = -MathHelper.cos(-var5 * 0.017453292F);
+ float var17 = MathHelper.sin(-var5 * 0.017453292F);
+ float var18 = var15 * var16;
+ float var20 = var14 * var16;
+ double var21 = 5.0D;
+ Vec3 var23 = var13.addVector((double) var18 * var21, (double) var17 * var21, (double) var20 * var21);
+ return par1World.rayTraceBlocks_do_do(var13, var23, par3, !par3);
+ }
+
+ /**
+ * Return the enchantability factor of the item, most of the time is based on
+ * material.
+ */
+ public int getItemEnchantability() {
+ return 0;
+ }
+
+ /**
+ * returns this;
+ */
+ public Item setCreativeTab(CreativeTabs par1CreativeTabs) {
+ this.tabToDisplayOn = par1CreativeTabs;
+ return this;
+ }
+
+ public boolean func_82788_x() {
+ return true;
+ }
+
+ /**
+ * Return whether this item is repairable in an anvil.
+ */
+ public boolean getIsRepairable(ItemStack par1ItemStack, ItemStack par2ItemStack) {
+ return false;
+ }
+
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemAnvilBlock.java b/sp-server/src/main/java/net/minecraft/src/ItemAnvilBlock.java
new file mode 100644
index 0000000..899c285
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemAnvilBlock.java
@@ -0,0 +1,14 @@
+package net.minecraft.src;
+
+public class ItemAnvilBlock extends ItemMultiTextureTile {
+ public ItemAnvilBlock(Block par1Block) {
+ super(par1Block.blockID - 256, par1Block, BlockAnvil.statuses);
+ }
+
+ /**
+ * Returns the metadata of the block which this Item (ItemBlock) can place
+ */
+ public int getMetadata(int par1) {
+ return par1 << 2;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemAppleGold.java b/sp-server/src/main/java/net/minecraft/src/ItemAppleGold.java
new file mode 100644
index 0000000..31124f9
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemAppleGold.java
@@ -0,0 +1,20 @@
+package net.minecraft.src;
+
+public class ItemAppleGold extends ItemFood {
+ public ItemAppleGold(int par1, int par2, float par3, boolean par4) {
+ super(par1, par2, par3, par4);
+ this.setHasSubtypes(true);
+ }
+
+ protected void onFoodEaten(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer) {
+ if (par1ItemStack.getItemDamage() > 0) {
+ if (!par2World.isRemote) {
+ par3EntityPlayer.addPotionEffect(new PotionEffect(Potion.regeneration.id, 600, 3));
+ par3EntityPlayer.addPotionEffect(new PotionEffect(Potion.resistance.id, 6000, 0));
+ par3EntityPlayer.addPotionEffect(new PotionEffect(Potion.fireResistance.id, 6000, 0));
+ }
+ } else {
+ super.onFoodEaten(par1ItemStack, par2World, par3EntityPlayer);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemArmor.java b/sp-server/src/main/java/net/minecraft/src/ItemArmor.java
new file mode 100644
index 0000000..2c50fa0
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemArmor.java
@@ -0,0 +1,153 @@
+package net.minecraft.src;
+
+public class ItemArmor extends Item {
+ /** Holds the 'base' maxDamage that each armorType have. */
+ private static final int[] maxDamageArray = new int[] { 11, 16, 15, 13 };
+ private static final String[] field_94606_cu = new String[] { "helmetCloth_overlay", "chestplateCloth_overlay",
+ "leggingsCloth_overlay", "bootsCloth_overlay" };
+ public static final String[] field_94603_a = new String[] { "slot_empty_helmet", "slot_empty_chestplate",
+ "slot_empty_leggings", "slot_empty_boots" };
+ private static final IBehaviorDispenseItem field_96605_cw = new BehaviorDispenseArmor();
+
+ /**
+ * Stores the armor type: 0 is helmet, 1 is plate, 2 is legs and 3 is boots
+ */
+ public final int armorType;
+
+ /** Holds the amount of damage that the armor reduces at full durability. */
+ public final int damageReduceAmount;
+
+ /**
+ * Used on RenderPlayer to select the correspondent armor to be rendered on the
+ * player: 0 is cloth, 1 is chain, 2 is iron, 3 is diamond and 4 is gold.
+ */
+ public final int renderIndex;
+
+ /** The EnumArmorMaterial used for this ItemArmor */
+ private final EnumArmorMaterial material;
+
+ public ItemArmor(int par1, EnumArmorMaterial par2EnumArmorMaterial, int par3, int par4) {
+ super(par1);
+ this.material = par2EnumArmorMaterial;
+ this.armorType = par4;
+ this.renderIndex = par3;
+ this.damageReduceAmount = par2EnumArmorMaterial.getDamageReductionAmount(par4);
+ this.setMaxDamage(par2EnumArmorMaterial.getDurability(par4));
+ this.maxStackSize = 1;
+ this.setCreativeTab(CreativeTabs.tabCombat);
+ BlockDispenser.dispenseBehaviorRegistry.putObject(this, field_96605_cw);
+ }
+
+ /**
+ * Return the enchantability factor of the item, most of the time is based on
+ * material.
+ */
+ public int getItemEnchantability() {
+ return this.material.getEnchantability();
+ }
+
+ /**
+ * Return the armor material for this armor item.
+ */
+ public EnumArmorMaterial getArmorMaterial() {
+ return this.material;
+ }
+
+ /**
+ * Return whether the specified armor ItemStack has a color.
+ */
+ public boolean hasColor(ItemStack par1ItemStack) {
+ return this.material != EnumArmorMaterial.CLOTH ? false
+ : (!par1ItemStack.hasTagCompound() ? false
+ : (!par1ItemStack.getTagCompound().hasKey("display") ? false
+ : par1ItemStack.getTagCompound().getCompoundTag("display").hasKey("color")));
+ }
+
+ /**
+ * Return the color for the specified armor ItemStack.
+ */
+ public int getColor(ItemStack par1ItemStack) {
+ if (this.material != EnumArmorMaterial.CLOTH) {
+ return -1;
+ } else {
+ NBTTagCompound var2 = par1ItemStack.getTagCompound();
+
+ if (var2 == null) {
+ return 10511680;
+ } else {
+ NBTTagCompound var3 = var2.getCompoundTag("display");
+ return var3 == null ? 10511680 : (var3.hasKey("color") ? var3.getInteger("color") : 10511680);
+ }
+ }
+ }
+
+ /**
+ * Remove the color from the specified armor ItemStack.
+ */
+ public void removeColor(ItemStack par1ItemStack) {
+ if (this.material == EnumArmorMaterial.CLOTH) {
+ NBTTagCompound var2 = par1ItemStack.getTagCompound();
+
+ if (var2 != null) {
+ NBTTagCompound var3 = var2.getCompoundTag("display");
+
+ if (var3.hasKey("color")) {
+ var3.removeTag("color");
+ }
+ }
+ }
+ }
+
+ public void func_82813_b(ItemStack par1ItemStack, int par2) {
+ if (this.material != EnumArmorMaterial.CLOTH) {
+ throw new UnsupportedOperationException("Can\'t dye non-leather!");
+ } else {
+ NBTTagCompound var3 = par1ItemStack.getTagCompound();
+
+ if (var3 == null) {
+ var3 = new NBTTagCompound();
+ par1ItemStack.setTagCompound(var3);
+ }
+
+ NBTTagCompound var4 = var3.getCompoundTag("display");
+
+ if (!var3.hasKey("display")) {
+ var3.setCompoundTag("display", var4);
+ }
+
+ var4.setInteger("color", par2);
+ }
+ }
+
+ /**
+ * Return whether this item is repairable in an anvil.
+ */
+ public boolean getIsRepairable(ItemStack par1ItemStack, ItemStack par2ItemStack) {
+ return this.material.getArmorCraftingMaterial() == par2ItemStack.itemID ? true
+ : super.getIsRepairable(par1ItemStack, par2ItemStack);
+ }
+
+ /**
+ * Called whenever this item is equipped and the right mouse button is pressed.
+ * Args: itemStack, world, entityPlayer
+ */
+ public ItemStack onItemRightClick(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer) {
+ int var4 = EntityLiving.getArmorPosition(par1ItemStack) - 1;
+ ItemStack var5 = par3EntityPlayer.getCurrentArmor(var4);
+
+ if (var5 == null) {
+ par3EntityPlayer.setCurrentItemOrArmor(var4, par1ItemStack.copy());
+ par1ItemStack.stackSize = 0;
+ }
+
+ return par1ItemStack;
+ }
+
+ /**
+ * Returns the 'max damage' factor array for the armor, each piece of armor have
+ * a durability factor (that gets multiplied by armor material factor)
+ */
+ static int[] getMaxDamageArray() {
+ return maxDamageArray;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemAxe.java b/sp-server/src/main/java/net/minecraft/src/ItemAxe.java
new file mode 100644
index 0000000..c63ff39
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemAxe.java
@@ -0,0 +1,22 @@
+package net.minecraft.src;
+
+public class ItemAxe extends ItemTool {
+ /** an array of the blocks this axe is effective against */
+ private static Block[] blocksEffectiveAgainst = new Block[] { Block.planks, Block.bookShelf, Block.wood,
+ Block.chest, Block.stoneDoubleSlab, Block.stoneSingleSlab, Block.pumpkin, Block.pumpkinLantern };
+
+ protected ItemAxe(int par1, EnumToolMaterial par2EnumToolMaterial) {
+ super(par1, 3, par2EnumToolMaterial, blocksEffectiveAgainst);
+ }
+
+ /**
+ * Returns the strength of the stack against a given block. 1.0F base,
+ * (Quality+1)*2 if correct blocktype, 1.5F if sword
+ */
+ public float getStrVsBlock(ItemStack par1ItemStack, Block par2Block) {
+ return par2Block != null && (par2Block.blockMaterial == Material.wood
+ || par2Block.blockMaterial == Material.plants || par2Block.blockMaterial == Material.vine)
+ ? this.efficiencyOnProperMaterial
+ : super.getStrVsBlock(par1ItemStack, par2Block);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemBed.java b/sp-server/src/main/java/net/minecraft/src/ItemBed.java
new file mode 100644
index 0000000..8937720
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemBed.java
@@ -0,0 +1,64 @@
+package net.minecraft.src;
+
+public class ItemBed extends Item {
+ public ItemBed(int par1) {
+ super(par1);
+ this.setCreativeTab(CreativeTabs.tabDecorations);
+ }
+
+ /**
+ * Callback for item usage. If the item does something special on right
+ * clicking, he will have one of those. Return True if something happen and
+ * false if it don't. This is for ITEMS, not BLOCKS
+ */
+ public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World par3World, int par4,
+ int par5, int par6, int par7, float par8, float par9, float par10) {
+ if (par3World.isRemote) {
+ return true;
+ } else if (par7 != 1) {
+ return false;
+ } else {
+ ++par5;
+ BlockBed var11 = (BlockBed) Block.bed;
+ int var12 = MathHelper.floor_double((double) (par2EntityPlayer.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3;
+ byte var13 = 0;
+ byte var14 = 0;
+
+ if (var12 == 0) {
+ var14 = 1;
+ }
+
+ if (var12 == 1) {
+ var13 = -1;
+ }
+
+ if (var12 == 2) {
+ var14 = -1;
+ }
+
+ if (var12 == 3) {
+ var13 = 1;
+ }
+
+ if (par2EntityPlayer.canPlayerEdit(par4, par5, par6, par7, par1ItemStack)
+ && par2EntityPlayer.canPlayerEdit(par4 + var13, par5, par6 + var14, par7, par1ItemStack)) {
+ if (par3World.isAirBlock(par4, par5, par6) && par3World.isAirBlock(par4 + var13, par5, par6 + var14)
+ && par3World.doesBlockHaveSolidTopSurface(par4, par5 - 1, par6)
+ && par3World.doesBlockHaveSolidTopSurface(par4 + var13, par5 - 1, par6 + var14)) {
+ par3World.setBlock(par4, par5, par6, var11.blockID, var12, 3);
+
+ if (par3World.getBlockId(par4, par5, par6) == var11.blockID) {
+ par3World.setBlock(par4 + var13, par5, par6 + var14, var11.blockID, var12 + 8, 3);
+ }
+
+ --par1ItemStack.stackSize;
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemBlock.java b/sp-server/src/main/java/net/minecraft/src/ItemBlock.java
new file mode 100644
index 0000000..b969af6
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemBlock.java
@@ -0,0 +1,102 @@
+package net.minecraft.src;
+
+public class ItemBlock extends Item {
+ /** The block ID of the Block associated with this ItemBlock */
+ private int blockID;
+
+ public ItemBlock(int par1) {
+ super(par1);
+ this.blockID = par1 + 256;
+ }
+
+ /**
+ * Returns the blockID for this Item
+ */
+ public int getBlockID() {
+ return this.blockID;
+ }
+
+ /**
+ * Callback for item usage. If the item does something special on right
+ * clicking, he will have one of those. Return True if something happen and
+ * false if it don't. This is for ITEMS, not BLOCKS
+ */
+ public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World par3World, int par4,
+ int par5, int par6, int par7, float par8, float par9, float par10) {
+ int var11 = par3World.getBlockId(par4, par5, par6);
+
+ if (var11 == Block.snow.blockID && (par3World.getBlockMetadata(par4, par5, par6) & 7) < 1) {
+ par7 = 1;
+ } else if (var11 != Block.vine.blockID && var11 != Block.tallGrass.blockID && var11 != Block.deadBush.blockID) {
+ if (par7 == 0) {
+ --par5;
+ }
+
+ if (par7 == 1) {
+ ++par5;
+ }
+
+ if (par7 == 2) {
+ --par6;
+ }
+
+ if (par7 == 3) {
+ ++par6;
+ }
+
+ if (par7 == 4) {
+ --par4;
+ }
+
+ if (par7 == 5) {
+ ++par4;
+ }
+ }
+
+ if (par1ItemStack.stackSize == 0) {
+ return false;
+ } else if (!par2EntityPlayer.canPlayerEdit(par4, par5, par6, par7, par1ItemStack)) {
+ return false;
+ } else if (par5 == 255 && Block.blocksList[this.blockID].blockMaterial.isSolid()) {
+ return false;
+ } else if (par3World.canPlaceEntityOnSide(this.blockID, par4, par5, par6, false, par7, par2EntityPlayer,
+ par1ItemStack)) {
+ Block var12 = Block.blocksList[this.blockID];
+ int var13 = this.getMetadata(par1ItemStack.getItemDamage());
+ int var14 = Block.blocksList[this.blockID].onBlockPlaced(par3World, par4, par5, par6, par7, par8, par9,
+ par10, var13);
+
+ if (par3World.setBlock(par4, par5, par6, this.blockID, var14, 3)) {
+ if (par3World.getBlockId(par4, par5, par6) == this.blockID) {
+ Block.blocksList[this.blockID].onBlockPlacedBy(par3World, par4, par5, par6, par2EntityPlayer,
+ par1ItemStack);
+ Block.blocksList[this.blockID].onPostBlockPlaced(par3World, par4, par5, par6, var14);
+ }
+
+ par3World.playSoundEffect((double) ((float) par4 + 0.5F), (double) ((float) par5 + 0.5F),
+ (double) ((float) par6 + 0.5F), var12.stepSound.getPlaceSound(),
+ (var12.stepSound.getVolume() + 1.0F) / 2.0F, var12.stepSound.getPitch() * 0.8F);
+ --par1ItemStack.stackSize;
+ }
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Returns the unlocalized name of this item. This version accepts an ItemStack
+ * so different stacks can have different names based on their damage or NBT.
+ */
+ public String getUnlocalizedName(ItemStack par1ItemStack) {
+ return Block.blocksList[this.blockID].getUnlocalizedName();
+ }
+
+ /**
+ * Returns the unlocalized name of this item.
+ */
+ public String getUnlocalizedName() {
+ return Block.blocksList[this.blockID].getUnlocalizedName();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemBlockWithMetadata.java b/sp-server/src/main/java/net/minecraft/src/ItemBlockWithMetadata.java
new file mode 100644
index 0000000..a826060
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemBlockWithMetadata.java
@@ -0,0 +1,19 @@
+package net.minecraft.src;
+
+public class ItemBlockWithMetadata extends ItemBlock {
+ private Block theBlock;
+
+ public ItemBlockWithMetadata(int par1, Block par2Block) {
+ super(par1);
+ this.theBlock = par2Block;
+ this.setMaxDamage(0);
+ this.setHasSubtypes(true);
+ }
+
+ /**
+ * Returns the metadata of the block which this Item (ItemBlock) can place
+ */
+ public int getMetadata(int par1) {
+ return par1;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemBoat.java b/sp-server/src/main/java/net/minecraft/src/ItemBoat.java
new file mode 100644
index 0000000..a8d6462
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemBoat.java
@@ -0,0 +1,98 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+public class ItemBoat extends Item {
+ public ItemBoat(int par1) {
+ super(par1);
+ this.maxStackSize = 1;
+ this.setCreativeTab(CreativeTabs.tabTransport);
+ }
+
+ /**
+ * Called whenever this item is equipped and the right mouse button is pressed.
+ * Args: itemStack, world, entityPlayer
+ */
+ public ItemStack onItemRightClick(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer) {
+ float var4 = 1.0F;
+ float var5 = par3EntityPlayer.prevRotationPitch
+ + (par3EntityPlayer.rotationPitch - par3EntityPlayer.prevRotationPitch) * var4;
+ float var6 = par3EntityPlayer.prevRotationYaw
+ + (par3EntityPlayer.rotationYaw - par3EntityPlayer.prevRotationYaw) * var4;
+ double var7 = par3EntityPlayer.prevPosX + (par3EntityPlayer.posX - par3EntityPlayer.prevPosX) * (double) var4;
+ double var9 = par3EntityPlayer.prevPosY + (par3EntityPlayer.posY - par3EntityPlayer.prevPosY) * (double) var4
+ + 1.62D - (double) par3EntityPlayer.yOffset;
+ double var11 = par3EntityPlayer.prevPosZ + (par3EntityPlayer.posZ - par3EntityPlayer.prevPosZ) * (double) var4;
+ Vec3 var13 = par2World.getWorldVec3Pool().getVecFromPool(var7, var9, var11);
+ float var14 = MathHelper.cos(-var6 * 0.017453292F - (float) Math.PI);
+ float var15 = MathHelper.sin(-var6 * 0.017453292F - (float) Math.PI);
+ float var16 = -MathHelper.cos(-var5 * 0.017453292F);
+ float var17 = MathHelper.sin(-var5 * 0.017453292F);
+ float var18 = var15 * var16;
+ float var20 = var14 * var16;
+ double var21 = 5.0D;
+ Vec3 var23 = var13.addVector((double) var18 * var21, (double) var17 * var21, (double) var20 * var21);
+ MovingObjectPosition var24 = par2World.rayTraceBlocks_do(var13, var23, true);
+
+ if (var24 == null) {
+ return par1ItemStack;
+ } else {
+ Vec3 var25 = par3EntityPlayer.getLook(var4);
+ boolean var26 = false;
+ float var27 = 1.0F;
+ List var28 = par2World.getEntitiesWithinAABBExcludingEntity(par3EntityPlayer,
+ par3EntityPlayer.boundingBox
+ .addCoord(var25.xCoord * var21, var25.yCoord * var21, var25.zCoord * var21)
+ .expand((double) var27, (double) var27, (double) var27));
+ int var29;
+
+ for (var29 = 0; var29 < var28.size(); ++var29) {
+ Entity var30 = (Entity) var28.get(var29);
+
+ if (var30.canBeCollidedWith()) {
+ float var31 = var30.getCollisionBorderSize();
+ AxisAlignedBB var32 = var30.boundingBox.expand((double) var31, (double) var31, (double) var31);
+
+ if (var32.isVecInside(var13)) {
+ var26 = true;
+ }
+ }
+ }
+
+ if (var26) {
+ return par1ItemStack;
+ } else {
+ if (var24.typeOfHit == EnumMovingObjectType.TILE) {
+ var29 = var24.blockX;
+ int var33 = var24.blockY;
+ int var34 = var24.blockZ;
+
+ if (par2World.getBlockId(var29, var33, var34) == Block.snow.blockID) {
+ --var33;
+ }
+
+ EntityBoat var35 = new EntityBoat(par2World, (double) ((float) var29 + 0.5F),
+ (double) ((float) var33 + 1.0F), (double) ((float) var34 + 0.5F));
+ var35.rotationYaw = (float) (((MathHelper
+ .floor_double((double) (par3EntityPlayer.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3) - 1)
+ * 90);
+
+ if (!par2World.getCollidingBoundingBoxes(var35, var35.boundingBox.expand(-0.1D, -0.1D, -0.1D))
+ .isEmpty()) {
+ return par1ItemStack;
+ }
+
+ if (!par2World.isRemote) {
+ par2World.spawnEntityInWorld(var35);
+ }
+
+ if (!par3EntityPlayer.capabilities.isCreativeMode) {
+ --par1ItemStack.stackSize;
+ }
+ }
+
+ return par1ItemStack;
+ }
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemBook.java b/sp-server/src/main/java/net/minecraft/src/ItemBook.java
new file mode 100644
index 0000000..91dbd88
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemBook.java
@@ -0,0 +1,22 @@
+package net.minecraft.src;
+
+public class ItemBook extends Item {
+ public ItemBook(int par1) {
+ super(par1);
+ }
+
+ /**
+ * Checks isDamagable and if it cannot be stacked
+ */
+ public boolean isItemTool(ItemStack par1ItemStack) {
+ return par1ItemStack.stackSize == 1;
+ }
+
+ /**
+ * Return the enchantability factor of the item, most of the time is based on
+ * material.
+ */
+ public int getItemEnchantability() {
+ return 1;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemBow.java b/sp-server/src/main/java/net/minecraft/src/ItemBow.java
new file mode 100644
index 0000000..ac870d4
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemBow.java
@@ -0,0 +1,111 @@
+package net.minecraft.src;
+
+public class ItemBow extends Item {
+ public static final String[] bowPullIconNameArray = new String[] { "bow_pull_0", "bow_pull_1", "bow_pull_2" };
+
+ public ItemBow(int par1) {
+ super(par1);
+ this.maxStackSize = 1;
+ this.setMaxDamage(384);
+ this.setCreativeTab(CreativeTabs.tabCombat);
+ }
+
+ /**
+ * called when the player releases the use item button. Args: itemstack, world,
+ * entityplayer, itemInUseCount
+ */
+ public void onPlayerStoppedUsing(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer,
+ int par4) {
+ boolean var5 = par3EntityPlayer.capabilities.isCreativeMode
+ || EnchantmentHelper.getEnchantmentLevel(Enchantment.infinity.effectId, par1ItemStack) > 0;
+
+ if (var5 || par3EntityPlayer.inventory.hasItem(Item.arrow.itemID)) {
+ int var6 = this.getMaxItemUseDuration(par1ItemStack) - par4;
+ float var7 = (float) var6 / 20.0F;
+ var7 = (var7 * var7 + var7 * 2.0F) / 3.0F;
+
+ if ((double) var7 < 0.1D) {
+ return;
+ }
+
+ if (var7 > 1.0F) {
+ var7 = 1.0F;
+ }
+
+ EntityArrow var8 = new EntityArrow(par2World, par3EntityPlayer, var7 * 2.0F);
+
+ if (var7 == 1.0F) {
+ var8.setIsCritical(true);
+ }
+
+ int var9 = EnchantmentHelper.getEnchantmentLevel(Enchantment.power.effectId, par1ItemStack);
+
+ if (var9 > 0) {
+ var8.setDamage(var8.getDamage() + (double) var9 * 0.5D + 0.5D);
+ }
+
+ int var10 = EnchantmentHelper.getEnchantmentLevel(Enchantment.punch.effectId, par1ItemStack);
+
+ if (var10 > 0) {
+ var8.setKnockbackStrength(var10);
+ }
+
+ if (EnchantmentHelper.getEnchantmentLevel(Enchantment.flame.effectId, par1ItemStack) > 0) {
+ var8.setFire(100);
+ }
+
+ par1ItemStack.damageItem(1, par3EntityPlayer);
+ par2World.playSoundAtEntity(par3EntityPlayer, "random.bow", 1.0F,
+ 1.0F / (itemRand.nextFloat() * 0.4F + 1.2F) + var7 * 0.5F);
+
+ if (var5) {
+ var8.canBePickedUp = 2;
+ } else {
+ par3EntityPlayer.inventory.consumeInventoryItem(Item.arrow.itemID);
+ }
+
+ if (!par2World.isRemote) {
+ par2World.spawnEntityInWorld(var8);
+ }
+ }
+ }
+
+ public ItemStack onEaten(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer) {
+ return par1ItemStack;
+ }
+
+ /**
+ * How long it takes to use or consume an item
+ */
+ public int getMaxItemUseDuration(ItemStack par1ItemStack) {
+ return 72000;
+ }
+
+ /**
+ * returns the action that specifies what animation to play when the items is
+ * being used
+ */
+ public EnumAction getItemUseAction(ItemStack par1ItemStack) {
+ return EnumAction.bow;
+ }
+
+ /**
+ * Called whenever this item is equipped and the right mouse button is pressed.
+ * Args: itemStack, world, entityPlayer
+ */
+ public ItemStack onItemRightClick(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer) {
+ if (par3EntityPlayer.capabilities.isCreativeMode || par3EntityPlayer.inventory.hasItem(Item.arrow.itemID)) {
+ par3EntityPlayer.setItemInUse(par1ItemStack, this.getMaxItemUseDuration(par1ItemStack));
+ }
+
+ return par1ItemStack;
+ }
+
+ /**
+ * Return the enchantability factor of the item, most of the time is based on
+ * material.
+ */
+ public int getItemEnchantability() {
+ return 1;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemBucket.java b/sp-server/src/main/java/net/minecraft/src/ItemBucket.java
new file mode 100644
index 0000000..2adee92
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemBucket.java
@@ -0,0 +1,153 @@
+package net.minecraft.src;
+
+public class ItemBucket extends Item {
+ /** field for checking if the bucket has been filled. */
+ private int isFull;
+
+ public ItemBucket(int par1, int par2) {
+ super(par1);
+ this.maxStackSize = 1;
+ this.isFull = par2;
+ this.setCreativeTab(CreativeTabs.tabMisc);
+ }
+
+ /**
+ * Called whenever this item is equipped and the right mouse button is pressed.
+ * Args: itemStack, world, entityPlayer
+ */
+ public ItemStack onItemRightClick(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer) {
+ float var4 = 1.0F;
+ double var5 = par3EntityPlayer.prevPosX + (par3EntityPlayer.posX - par3EntityPlayer.prevPosX) * (double) var4;
+ double var7 = par3EntityPlayer.prevPosY + (par3EntityPlayer.posY - par3EntityPlayer.prevPosY) * (double) var4
+ + 1.62D - (double) par3EntityPlayer.yOffset;
+ double var9 = par3EntityPlayer.prevPosZ + (par3EntityPlayer.posZ - par3EntityPlayer.prevPosZ) * (double) var4;
+ boolean var11 = this.isFull == 0;
+ MovingObjectPosition var12 = this.getMovingObjectPositionFromPlayer(par2World, par3EntityPlayer, var11);
+
+ if (var12 == null) {
+ return par1ItemStack;
+ } else {
+ if (var12.typeOfHit == EnumMovingObjectType.TILE) {
+ int var13 = var12.blockX;
+ int var14 = var12.blockY;
+ int var15 = var12.blockZ;
+
+ if (!par2World.canMineBlock(par3EntityPlayer, var13, var14, var15)) {
+ return par1ItemStack;
+ }
+
+ if (this.isFull == 0) {
+ if (!par3EntityPlayer.canPlayerEdit(var13, var14, var15, var12.sideHit, par1ItemStack)) {
+ return par1ItemStack;
+ }
+
+ if (par2World.getBlockMaterial(var13, var14, var15) == Material.water
+ && par2World.getBlockMetadata(var13, var14, var15) == 0) {
+ par2World.setBlockToAir(var13, var14, var15);
+
+ if (par3EntityPlayer.capabilities.isCreativeMode) {
+ return par1ItemStack;
+ }
+
+ if (--par1ItemStack.stackSize <= 0) {
+ return new ItemStack(Item.bucketWater);
+ }
+
+ if (!par3EntityPlayer.inventory.addItemStackToInventory(new ItemStack(Item.bucketWater))) {
+ par3EntityPlayer.dropPlayerItem(new ItemStack(Item.bucketWater.itemID, 1, 0));
+ }
+
+ return par1ItemStack;
+ }
+
+ if (par2World.getBlockMaterial(var13, var14, var15) == Material.lava
+ && par2World.getBlockMetadata(var13, var14, var15) == 0) {
+ par2World.setBlockToAir(var13, var14, var15);
+
+ if (par3EntityPlayer.capabilities.isCreativeMode) {
+ return par1ItemStack;
+ }
+
+ if (--par1ItemStack.stackSize <= 0) {
+ return new ItemStack(Item.bucketLava);
+ }
+
+ if (!par3EntityPlayer.inventory.addItemStackToInventory(new ItemStack(Item.bucketLava))) {
+ par3EntityPlayer.dropPlayerItem(new ItemStack(Item.bucketLava.itemID, 1, 0));
+ }
+
+ return par1ItemStack;
+ }
+ } else {
+ if (this.isFull < 0) {
+ return new ItemStack(Item.bucketEmpty);
+ }
+
+ if (var12.sideHit == 0) {
+ --var14;
+ }
+
+ if (var12.sideHit == 1) {
+ ++var14;
+ }
+
+ if (var12.sideHit == 2) {
+ --var15;
+ }
+
+ if (var12.sideHit == 3) {
+ ++var15;
+ }
+
+ if (var12.sideHit == 4) {
+ --var13;
+ }
+
+ if (var12.sideHit == 5) {
+ ++var13;
+ }
+
+ if (!par3EntityPlayer.canPlayerEdit(var13, var14, var15, var12.sideHit, par1ItemStack)) {
+ return par1ItemStack;
+ }
+
+ if (this.tryPlaceContainedLiquid(par2World, var5, var7, var9, var13, var14, var15)
+ && !par3EntityPlayer.capabilities.isCreativeMode) {
+ return new ItemStack(Item.bucketEmpty);
+ }
+ }
+ } else if (this.isFull == 0 && var12.entityHit instanceof EntityCow) {
+ return new ItemStack(Item.bucketMilk);
+ }
+
+ return par1ItemStack;
+ }
+ }
+
+ /**
+ * Attempts to place the liquid contained inside the bucket.
+ */
+ public boolean tryPlaceContainedLiquid(World par1World, double par2, double par4, double par6, int par8, int par9,
+ int par10) {
+ if (this.isFull <= 0) {
+ return false;
+ } else if (!par1World.isAirBlock(par8, par9, par10)
+ && par1World.getBlockMaterial(par8, par9, par10).isSolid()) {
+ return false;
+ } else {
+ if (par1World.provider.isHellWorld && this.isFull == Block.waterMoving.blockID) {
+ par1World.playSoundEffect(par2 + 0.5D, par4 + 0.5D, par6 + 0.5D, "random.fizz", 0.5F,
+ 2.6F + (par1World.rand.nextFloat() - par1World.rand.nextFloat()) * 0.8F);
+
+ for (int var11 = 0; var11 < 8; ++var11) {
+ par1World.spawnParticle("largesmoke", (double) par8 + Math.random(), (double) par9 + Math.random(),
+ (double) par10 + Math.random(), 0.0D, 0.0D, 0.0D);
+ }
+ } else {
+ par1World.setBlock(par8, par9, par10, this.isFull, 0, 3);
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemBucketMilk.java b/sp-server/src/main/java/net/minecraft/src/ItemBucketMilk.java
new file mode 100644
index 0000000..7393491
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemBucketMilk.java
@@ -0,0 +1,45 @@
+package net.minecraft.src;
+
+public class ItemBucketMilk extends Item {
+ public ItemBucketMilk(int par1) {
+ super(par1);
+ this.setMaxStackSize(1);
+ this.setCreativeTab(CreativeTabs.tabMisc);
+ }
+
+ public ItemStack onEaten(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer) {
+ if (!par3EntityPlayer.capabilities.isCreativeMode) {
+ --par1ItemStack.stackSize;
+ }
+
+ if (!par2World.isRemote) {
+ par3EntityPlayer.clearActivePotions();
+ }
+
+ return par1ItemStack.stackSize <= 0 ? new ItemStack(Item.bucketEmpty) : par1ItemStack;
+ }
+
+ /**
+ * How long it takes to use or consume an item
+ */
+ public int getMaxItemUseDuration(ItemStack par1ItemStack) {
+ return 32;
+ }
+
+ /**
+ * returns the action that specifies what animation to play when the items is
+ * being used
+ */
+ public EnumAction getItemUseAction(ItemStack par1ItemStack) {
+ return EnumAction.drink;
+ }
+
+ /**
+ * Called whenever this item is equipped and the right mouse button is pressed.
+ * Args: itemStack, world, entityPlayer
+ */
+ public ItemStack onItemRightClick(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer) {
+ par3EntityPlayer.setItemInUse(par1ItemStack, this.getMaxItemUseDuration(par1ItemStack));
+ return par1ItemStack;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemCarrotOnAStick.java b/sp-server/src/main/java/net/minecraft/src/ItemCarrotOnAStick.java
new file mode 100644
index 0000000..f8dcde2
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemCarrotOnAStick.java
@@ -0,0 +1,34 @@
+package net.minecraft.src;
+
+public class ItemCarrotOnAStick extends Item {
+ public ItemCarrotOnAStick(int par1) {
+ super(par1);
+ this.setCreativeTab(CreativeTabs.tabTransport);
+ this.setMaxStackSize(1);
+ this.setMaxDamage(25);
+ }
+
+ /**
+ * Called whenever this item is equipped and the right mouse button is pressed.
+ * Args: itemStack, world, entityPlayer
+ */
+ public ItemStack onItemRightClick(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer) {
+ if (par3EntityPlayer.isRiding() && par3EntityPlayer.ridingEntity instanceof EntityPig) {
+ EntityPig var4 = (EntityPig) par3EntityPlayer.ridingEntity;
+
+ if (var4.getAIControlledByPlayer().isControlledByPlayer()
+ && par1ItemStack.getMaxDamage() - par1ItemStack.getItemDamage() >= 7) {
+ var4.getAIControlledByPlayer().boostSpeed();
+ par1ItemStack.damageItem(7, par3EntityPlayer);
+
+ if (par1ItemStack.stackSize == 0) {
+ ItemStack var5 = new ItemStack(Item.fishingRod);
+ var5.setTagCompound(par1ItemStack.stackTagCompound);
+ return var5;
+ }
+ }
+ }
+
+ return par1ItemStack;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemCloth.java b/sp-server/src/main/java/net/minecraft/src/ItemCloth.java
new file mode 100644
index 0000000..71366bb
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemCloth.java
@@ -0,0 +1,25 @@
+package net.minecraft.src;
+
+public class ItemCloth extends ItemBlock {
+ public ItemCloth(int par1) {
+ super(par1);
+ this.setMaxDamage(0);
+ this.setHasSubtypes(true);
+ }
+
+ /**
+ * Returns the metadata of the block which this Item (ItemBlock) can place
+ */
+ public int getMetadata(int par1) {
+ return par1;
+ }
+
+ /**
+ * Returns the unlocalized name of this item. This version accepts an ItemStack
+ * so different stacks can have different names based on their damage or NBT.
+ */
+ public String getUnlocalizedName(ItemStack par1ItemStack) {
+ return super.getUnlocalizedName() + "."
+ + ItemDye.dyeColorNames[BlockCloth.getBlockFromDye(par1ItemStack.getItemDamage())];
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemCoal.java b/sp-server/src/main/java/net/minecraft/src/ItemCoal.java
new file mode 100644
index 0000000..f934f1f
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemCoal.java
@@ -0,0 +1,18 @@
+package net.minecraft.src;
+
+public class ItemCoal extends Item {
+ public ItemCoal(int par1) {
+ super(par1);
+ this.setHasSubtypes(true);
+ this.setMaxDamage(0);
+ this.setCreativeTab(CreativeTabs.tabMaterials);
+ }
+
+ /**
+ * Returns the unlocalized name of this item. This version accepts an ItemStack
+ * so different stacks can have different names based on their damage or NBT.
+ */
+ public String getUnlocalizedName(ItemStack par1ItemStack) {
+ return par1ItemStack.getItemDamage() == 1 ? "item.charcoal" : "item.coal";
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemColored.java b/sp-server/src/main/java/net/minecraft/src/ItemColored.java
new file mode 100644
index 0000000..8aed141
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemColored.java
@@ -0,0 +1,47 @@
+package net.minecraft.src;
+
+public class ItemColored extends ItemBlock {
+ private final Block blockRef;
+ private String[] blockNames;
+
+ public ItemColored(int par1, boolean par2) {
+ super(par1);
+ this.blockRef = Block.blocksList[this.getBlockID()];
+
+ if (par2) {
+ this.setMaxDamage(0);
+ this.setHasSubtypes(true);
+ }
+ }
+
+ /**
+ * Returns the metadata of the block which this Item (ItemBlock) can place
+ */
+ public int getMetadata(int par1) {
+ return par1;
+ }
+
+ /**
+ * Sets the array of strings to be used for name lookups from item damage to
+ * metadata
+ */
+ public ItemColored setBlockNames(String[] par1ArrayOfStr) {
+ this.blockNames = par1ArrayOfStr;
+ return this;
+ }
+
+ /**
+ * Returns the unlocalized name of this item. This version accepts an ItemStack
+ * so different stacks can have different names based on their damage or NBT.
+ */
+ public String getUnlocalizedName(ItemStack par1ItemStack) {
+ if (this.blockNames == null) {
+ return super.getUnlocalizedName(par1ItemStack);
+ } else {
+ int var2 = par1ItemStack.getItemDamage();
+ return var2 >= 0 && var2 < this.blockNames.length
+ ? super.getUnlocalizedName(par1ItemStack) + "." + this.blockNames[var2]
+ : super.getUnlocalizedName(par1ItemStack);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemDoor.java b/sp-server/src/main/java/net/minecraft/src/ItemDoor.java
new file mode 100644
index 0000000..b10b4f2
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemDoor.java
@@ -0,0 +1,90 @@
+package net.minecraft.src;
+
+public class ItemDoor extends Item {
+ private Material doorMaterial;
+
+ public ItemDoor(int par1, Material par2Material) {
+ super(par1);
+ this.doorMaterial = par2Material;
+ this.maxStackSize = 1;
+ this.setCreativeTab(CreativeTabs.tabRedstone);
+ }
+
+ /**
+ * Callback for item usage. If the item does something special on right
+ * clicking, he will have one of those. Return True if something happen and
+ * false if it don't. This is for ITEMS, not BLOCKS
+ */
+ public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World par3World, int par4,
+ int par5, int par6, int par7, float par8, float par9, float par10) {
+ if (par7 != 1) {
+ return false;
+ } else {
+ ++par5;
+ Block var11;
+
+ if (this.doorMaterial == Material.wood) {
+ var11 = Block.doorWood;
+ } else {
+ var11 = Block.doorIron;
+ }
+
+ if (par2EntityPlayer.canPlayerEdit(par4, par5, par6, par7, par1ItemStack)
+ && par2EntityPlayer.canPlayerEdit(par4, par5 + 1, par6, par7, par1ItemStack)) {
+ if (!var11.canPlaceBlockAt(par3World, par4, par5, par6)) {
+ return false;
+ } else {
+ int var12 = MathHelper.floor_double(
+ (double) ((par2EntityPlayer.rotationYaw + 180.0F) * 4.0F / 360.0F) - 0.5D) & 3;
+ placeDoorBlock(par3World, par4, par5, par6, var12, var11);
+ --par1ItemStack.stackSize;
+ return true;
+ }
+ } else {
+ return false;
+ }
+ }
+ }
+
+ public static void placeDoorBlock(World par0World, int par1, int par2, int par3, int par4, Block par5Block) {
+ byte var6 = 0;
+ byte var7 = 0;
+
+ if (par4 == 0) {
+ var7 = 1;
+ }
+
+ if (par4 == 1) {
+ var6 = -1;
+ }
+
+ if (par4 == 2) {
+ var7 = -1;
+ }
+
+ if (par4 == 3) {
+ var6 = 1;
+ }
+
+ int var8 = (par0World.isBlockNormalCube(par1 - var6, par2, par3 - var7) ? 1 : 0)
+ + (par0World.isBlockNormalCube(par1 - var6, par2 + 1, par3 - var7) ? 1 : 0);
+ int var9 = (par0World.isBlockNormalCube(par1 + var6, par2, par3 + var7) ? 1 : 0)
+ + (par0World.isBlockNormalCube(par1 + var6, par2 + 1, par3 + var7) ? 1 : 0);
+ boolean var10 = par0World.getBlockId(par1 - var6, par2, par3 - var7) == par5Block.blockID
+ || par0World.getBlockId(par1 - var6, par2 + 1, par3 - var7) == par5Block.blockID;
+ boolean var11 = par0World.getBlockId(par1 + var6, par2, par3 + var7) == par5Block.blockID
+ || par0World.getBlockId(par1 + var6, par2 + 1, par3 + var7) == par5Block.blockID;
+ boolean var12 = false;
+
+ if (var10 && !var11) {
+ var12 = true;
+ } else if (var9 > var8) {
+ var12 = true;
+ }
+
+ par0World.setBlock(par1, par2, par3, par5Block.blockID, par4, 2);
+ par0World.setBlock(par1, par2 + 1, par3, par5Block.blockID, 8 | (var12 ? 1 : 0), 2);
+ par0World.notifyBlocksOfNeighborChange(par1, par2, par3, par5Block.blockID);
+ par0World.notifyBlocksOfNeighborChange(par1, par2 + 1, par3, par5Block.blockID);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemDye.java b/sp-server/src/main/java/net/minecraft/src/ItemDye.java
new file mode 100644
index 0000000..2318706
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemDye.java
@@ -0,0 +1,226 @@
+package net.minecraft.src;
+
+public class ItemDye extends Item {
+ /** List of dye color names */
+ public static final String[] dyeColorNames = new String[] { "black", "red", "green", "brown", "blue", "purple",
+ "cyan", "silver", "gray", "pink", "lime", "yellow", "lightBlue", "magenta", "orange", "white" };
+ public static final String[] field_94595_b = new String[] { "dyePowder_black", "dyePowder_red", "dyePowder_green",
+ "dyePowder_brown", "dyePowder_blue", "dyePowder_purple", "dyePowder_cyan", "dyePowder_silver",
+ "dyePowder_gray", "dyePowder_pink", "dyePowder_lime", "dyePowder_yellow", "dyePowder_lightBlue",
+ "dyePowder_magenta", "dyePowder_orange", "dyePowder_white" };
+ public static final int[] dyeColors = new int[] { 1973019, 11743532, 3887386, 5320730, 2437522, 8073150, 2651799,
+ 11250603, 4408131, 14188952, 4312372, 14602026, 6719955, 12801229, 15435844, 15790320 };
+
+ public ItemDye(int par1) {
+ super(par1);
+ this.setHasSubtypes(true);
+ this.setMaxDamage(0);
+ this.setCreativeTab(CreativeTabs.tabMaterials);
+ }
+
+ /**
+ * Returns the unlocalized name of this item. This version accepts an ItemStack
+ * so different stacks can have different names based on their damage or NBT.
+ */
+ public String getUnlocalizedName(ItemStack par1ItemStack) {
+ int var2 = MathHelper.clamp_int(par1ItemStack.getItemDamage(), 0, 15);
+ return super.getUnlocalizedName() + "." + dyeColorNames[var2];
+ }
+
+ /**
+ * Callback for item usage. If the item does something special on right
+ * clicking, he will have one of those. Return True if something happen and
+ * false if it don't. This is for ITEMS, not BLOCKS
+ */
+ public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World par3World, int par4,
+ int par5, int par6, int par7, float par8, float par9, float par10) {
+ if (!par2EntityPlayer.canPlayerEdit(par4, par5, par6, par7, par1ItemStack)) {
+ return false;
+ } else {
+ if (par1ItemStack.getItemDamage() == 15) {
+ if (func_96604_a(par1ItemStack, par3World, par4, par5, par6)) {
+ if (!par3World.isRemote) {
+ par3World.playAuxSFX(2005, par4, par5, par6, 0);
+ }
+
+ return true;
+ }
+ } else if (par1ItemStack.getItemDamage() == 3) {
+ int var11 = par3World.getBlockId(par4, par5, par6);
+ int var12 = par3World.getBlockMetadata(par4, par5, par6);
+
+ if (var11 == Block.wood.blockID && BlockLog.limitToValidMetadata(var12) == 3) {
+ if (par7 == 0) {
+ return false;
+ }
+
+ if (par7 == 1) {
+ return false;
+ }
+
+ if (par7 == 2) {
+ --par6;
+ }
+
+ if (par7 == 3) {
+ ++par6;
+ }
+
+ if (par7 == 4) {
+ --par4;
+ }
+
+ if (par7 == 5) {
+ ++par4;
+ }
+
+ if (par3World.isAirBlock(par4, par5, par6)) {
+ int var13 = Block.blocksList[Block.cocoaPlant.blockID].onBlockPlaced(par3World, par4, par5,
+ par6, par7, par8, par9, par10, 0);
+ par3World.setBlock(par4, par5, par6, Block.cocoaPlant.blockID, var13, 2);
+
+ if (!par2EntityPlayer.capabilities.isCreativeMode) {
+ --par1ItemStack.stackSize;
+ }
+ }
+
+ return true;
+ }
+ }
+
+ return false;
+ }
+ }
+
+ public static boolean func_96604_a(ItemStack par0ItemStack, World par1World, int par2, int par3, int par4) {
+ int var5 = par1World.getBlockId(par2, par3, par4);
+
+ if (var5 == Block.sapling.blockID) {
+ if (!par1World.isRemote) {
+ if ((double) par1World.rand.nextFloat() < 0.45D) {
+ ((BlockSapling) Block.sapling).markOrGrowMarked(par1World, par2, par3, par4, par1World.rand);
+ }
+
+ --par0ItemStack.stackSize;
+ }
+
+ return true;
+ } else if (var5 != Block.mushroomBrown.blockID && var5 != Block.mushroomRed.blockID) {
+ if (var5 != Block.melonStem.blockID && var5 != Block.pumpkinStem.blockID) {
+ if (var5 > 0 && Block.blocksList[var5] instanceof BlockCrops) {
+ if (par1World.getBlockMetadata(par2, par3, par4) == 7) {
+ return false;
+ } else {
+ if (!par1World.isRemote) {
+ ((BlockCrops) Block.blocksList[var5]).fertilize(par1World, par2, par3, par4);
+ --par0ItemStack.stackSize;
+ }
+
+ return true;
+ }
+ } else {
+ int var6;
+ int var7;
+ int var8;
+
+ if (var5 == Block.cocoaPlant.blockID) {
+ var6 = par1World.getBlockMetadata(par2, par3, par4);
+ var7 = BlockDirectional.getDirection(var6);
+ var8 = BlockCocoa.func_72219_c(var6);
+
+ if (var8 >= 2) {
+ return false;
+ } else {
+ if (!par1World.isRemote) {
+ ++var8;
+ par1World.setBlockMetadata(par2, par3, par4, var8 << 2 | var7, 2);
+ --par0ItemStack.stackSize;
+ }
+
+ return true;
+ }
+ } else if (var5 != Block.grass.blockID) {
+ return false;
+ } else {
+ if (!par1World.isRemote) {
+ --par0ItemStack.stackSize;
+ label102:
+
+ for (var6 = 0; var6 < 128; ++var6) {
+ var7 = par2;
+ var8 = par3 + 1;
+ int var9 = par4;
+
+ for (int var10 = 0; var10 < var6 / 16; ++var10) {
+ var7 += itemRand.nextInt(3) - 1;
+ var8 += (itemRand.nextInt(3) - 1) * itemRand.nextInt(3) / 2;
+ var9 += itemRand.nextInt(3) - 1;
+
+ if (par1World.getBlockId(var7, var8 - 1, var9) != Block.grass.blockID
+ || par1World.isBlockNormalCube(var7, var8, var9)) {
+ continue label102;
+ }
+ }
+
+ if (par1World.getBlockId(var7, var8, var9) == 0) {
+ if (itemRand.nextInt(10) != 0) {
+ if (Block.tallGrass.canBlockStay(par1World, var7, var8, var9)) {
+ par1World.setBlock(var7, var8, var9, Block.tallGrass.blockID, 1, 3);
+ }
+ } else if (itemRand.nextInt(3) != 0) {
+ if (Block.plantYellow.canBlockStay(par1World, var7, var8, var9)) {
+ par1World.setBlock(var7, var8, var9, Block.plantYellow.blockID);
+ }
+ } else if (Block.plantRed.canBlockStay(par1World, var7, var8, var9)) {
+ par1World.setBlock(var7, var8, var9, Block.plantRed.blockID);
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+ }
+ } else if (par1World.getBlockMetadata(par2, par3, par4) == 7) {
+ return false;
+ } else {
+ if (!par1World.isRemote) {
+ ((BlockStem) Block.blocksList[var5]).fertilizeStem(par1World, par2, par3, par4);
+ --par0ItemStack.stackSize;
+ }
+
+ return true;
+ }
+ } else {
+ if (!par1World.isRemote) {
+ if ((double) par1World.rand.nextFloat() < 0.4D) {
+ ((BlockMushroom) Block.blocksList[var5]).fertilizeMushroom(par1World, par2, par3, par4,
+ par1World.rand);
+ }
+
+ --par0ItemStack.stackSize;
+ }
+
+ return true;
+ }
+ }
+
+ /**
+ * Called when a player right clicks an entity with an item.
+ */
+ public boolean useItemOnEntity(ItemStack par1ItemStack, EntityLiving par2EntityLiving) {
+ if (par2EntityLiving instanceof EntitySheep) {
+ EntitySheep var3 = (EntitySheep) par2EntityLiving;
+ int var4 = BlockCloth.getBlockFromDye(par1ItemStack.getItemDamage());
+
+ if (!var3.getSheared() && var3.getFleeceColor() != var4) {
+ var3.setFleeceColor(var4);
+ --par1ItemStack.stackSize;
+ }
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemEditableBook.java b/sp-server/src/main/java/net/minecraft/src/ItemEditableBook.java
new file mode 100644
index 0000000..725d352
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemEditableBook.java
@@ -0,0 +1,49 @@
+package net.minecraft.src;
+
+public class ItemEditableBook extends Item {
+ public ItemEditableBook(int par1) {
+ super(par1);
+ this.setMaxStackSize(1);
+ }
+
+ public static boolean validBookTagContents(NBTTagCompound par0NBTTagCompound) {
+ if (!ItemWritableBook.validBookTagPages(par0NBTTagCompound)) {
+ return false;
+ } else if (!par0NBTTagCompound.hasKey("title")) {
+ return false;
+ } else {
+ String var1 = par0NBTTagCompound.getString("title");
+ return var1 != null && var1.length() <= 16 ? par0NBTTagCompound.hasKey("author") : false;
+ }
+ }
+
+ public String getItemDisplayName(ItemStack par1ItemStack) {
+ if (par1ItemStack.hasTagCompound()) {
+ NBTTagCompound var2 = par1ItemStack.getTagCompound();
+ NBTTagString var3 = (NBTTagString) var2.getTag("title");
+
+ if (var3 != null) {
+ return var3.toString();
+ }
+ }
+
+ return super.getItemDisplayName(par1ItemStack);
+ }
+
+ /**
+ * Called whenever this item is equipped and the right mouse button is pressed.
+ * Args: itemStack, world, entityPlayer
+ */
+ public ItemStack onItemRightClick(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer) {
+ par3EntityPlayer.displayGUIBook(par1ItemStack);
+ return par1ItemStack;
+ }
+
+ /**
+ * If this function returns true (or the item is damageable), the ItemStack's
+ * NBT tag will be sent to the client.
+ */
+ public boolean getShareTag() {
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemEgg.java b/sp-server/src/main/java/net/minecraft/src/ItemEgg.java
new file mode 100644
index 0000000..d4e9546
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemEgg.java
@@ -0,0 +1,27 @@
+package net.minecraft.src;
+
+public class ItemEgg extends Item {
+ public ItemEgg(int par1) {
+ super(par1);
+ this.maxStackSize = 16;
+ this.setCreativeTab(CreativeTabs.tabMaterials);
+ }
+
+ /**
+ * Called whenever this item is equipped and the right mouse button is pressed.
+ * Args: itemStack, world, entityPlayer
+ */
+ public ItemStack onItemRightClick(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer) {
+ if (!par3EntityPlayer.capabilities.isCreativeMode) {
+ --par1ItemStack.stackSize;
+ }
+
+ par2World.playSoundAtEntity(par3EntityPlayer, "random.bow", 0.5F, 0.4F / (itemRand.nextFloat() * 0.4F + 0.8F));
+
+ if (!par2World.isRemote) {
+ par2World.spawnEntityInWorld(new EntityEgg(par2World, par3EntityPlayer));
+ }
+
+ return par1ItemStack;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemEmptyMap.java b/sp-server/src/main/java/net/minecraft/src/ItemEmptyMap.java
new file mode 100644
index 0000000..f79d8e8
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemEmptyMap.java
@@ -0,0 +1,36 @@
+package net.minecraft.src;
+
+public class ItemEmptyMap extends ItemMapBase {
+ protected ItemEmptyMap(int par1) {
+ super(par1);
+ this.setCreativeTab(CreativeTabs.tabMisc);
+ }
+
+ /**
+ * Called whenever this item is equipped and the right mouse button is pressed.
+ * Args: itemStack, world, entityPlayer
+ */
+ public ItemStack onItemRightClick(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer) {
+ ItemStack var4 = new ItemStack(Item.map, 1, par2World.getUniqueDataId("map"));
+ String var5 = "map_" + var4.getItemDamage();
+ MapData var6 = new MapData(var5);
+ par2World.setItemData(var5, var6);
+ var6.scale = 0;
+ int var7 = 128 * (1 << var6.scale);
+ var6.xCenter = (int) (Math.round(par3EntityPlayer.posX / (double) var7) * (long) var7);
+ var6.zCenter = (int) (Math.round(par3EntityPlayer.posZ / (double) var7) * (long) var7);
+ var6.dimension = (byte) par2World.provider.dimensionId;
+ var6.markDirty();
+ --par1ItemStack.stackSize;
+
+ if (par1ItemStack.stackSize <= 0) {
+ return var4;
+ } else {
+ if (!par3EntityPlayer.inventory.addItemStackToInventory(var4.copy())) {
+ par3EntityPlayer.dropPlayerItem(var4);
+ }
+
+ return par1ItemStack;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemEnchantedBook.java b/sp-server/src/main/java/net/minecraft/src/ItemEnchantedBook.java
new file mode 100644
index 0000000..3e1d3a6
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemEnchantedBook.java
@@ -0,0 +1,79 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class ItemEnchantedBook extends Item {
+ public ItemEnchantedBook(int par1) {
+ super(par1);
+ }
+
+ /**
+ * Checks isDamagable and if it cannot be stacked
+ */
+ public boolean isItemTool(ItemStack par1ItemStack) {
+ return false;
+ }
+
+ public NBTTagList func_92110_g(ItemStack par1ItemStack) {
+ return par1ItemStack.stackTagCompound != null && par1ItemStack.stackTagCompound.hasKey("StoredEnchantments")
+ ? (NBTTagList) par1ItemStack.stackTagCompound.getTag("StoredEnchantments")
+ : new NBTTagList();
+ }
+
+ public void func_92115_a(ItemStack par1ItemStack, EnchantmentData par2EnchantmentData) {
+ NBTTagList var3 = this.func_92110_g(par1ItemStack);
+ boolean var4 = true;
+
+ for (int var5 = 0; var5 < var3.tagCount(); ++var5) {
+ NBTTagCompound var6 = (NBTTagCompound) var3.tagAt(var5);
+
+ if (var6.getShort("id") == par2EnchantmentData.enchantmentobj.effectId) {
+ if (var6.getShort("lvl") < par2EnchantmentData.enchantmentLevel) {
+ var6.setShort("lvl", (short) par2EnchantmentData.enchantmentLevel);
+ }
+
+ var4 = false;
+ break;
+ }
+ }
+
+ if (var4) {
+ NBTTagCompound var7 = new NBTTagCompound();
+ var7.setShort("id", (short) par2EnchantmentData.enchantmentobj.effectId);
+ var7.setShort("lvl", (short) par2EnchantmentData.enchantmentLevel);
+ var3.appendTag(var7);
+ }
+
+ if (!par1ItemStack.hasTagCompound()) {
+ par1ItemStack.setTagCompound(new NBTTagCompound());
+ }
+
+ par1ItemStack.getTagCompound().setTag("StoredEnchantments", var3);
+ }
+
+ public ItemStack func_92111_a(EnchantmentData par1EnchantmentData) {
+ ItemStack var2 = new ItemStack(this);
+ this.func_92115_a(var2, par1EnchantmentData);
+ return var2;
+ }
+
+ public ItemStack func_92109_a(EaglercraftRandom par1Random) {
+ Enchantment var2 = Enchantment.field_92090_c[par1Random.nextInt(Enchantment.field_92090_c.length)];
+ ItemStack var3 = new ItemStack(this.itemID, 1, 0);
+ int var4 = MathHelper.getRandomIntegerInRange(par1Random, var2.getMinLevel(), var2.getMaxLevel());
+ this.func_92115_a(var3, new EnchantmentData(var2, var4));
+ return var3;
+ }
+
+ public WeightedRandomChestContent func_92114_b(EaglercraftRandom par1Random) {
+ return this.func_92112_a(par1Random, 1, 1, 1);
+ }
+
+ public WeightedRandomChestContent func_92112_a(EaglercraftRandom par1Random, int par2, int par3, int par4) {
+ Enchantment var5 = Enchantment.field_92090_c[par1Random.nextInt(Enchantment.field_92090_c.length)];
+ ItemStack var6 = new ItemStack(this.itemID, 1, 0);
+ int var7 = MathHelper.getRandomIntegerInRange(par1Random, var5.getMinLevel(), var5.getMaxLevel());
+ this.func_92115_a(var6, new EnchantmentData(var5, var7));
+ return new WeightedRandomChestContent(var6, par2, par3, par4);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemEnderEye.java b/sp-server/src/main/java/net/minecraft/src/ItemEnderEye.java
new file mode 100644
index 0000000..dc3b9b6
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemEnderEye.java
@@ -0,0 +1,161 @@
+package net.minecraft.src;
+
+public class ItemEnderEye extends Item {
+ public ItemEnderEye(int par1) {
+ super(par1);
+ this.setCreativeTab(CreativeTabs.tabMisc);
+ }
+
+ /**
+ * Callback for item usage. If the item does something special on right
+ * clicking, he will have one of those. Return True if something happen and
+ * false if it don't. This is for ITEMS, not BLOCKS
+ */
+ public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World par3World, int par4,
+ int par5, int par6, int par7, float par8, float par9, float par10) {
+ int var11 = par3World.getBlockId(par4, par5, par6);
+ int var12 = par3World.getBlockMetadata(par4, par5, par6);
+
+ if (par2EntityPlayer.canPlayerEdit(par4, par5, par6, par7, par1ItemStack)
+ && var11 == Block.endPortalFrame.blockID && !BlockEndPortalFrame.isEnderEyeInserted(var12)) {
+ if (par3World.isRemote) {
+ return true;
+ } else {
+ par3World.setBlockMetadata(par4, par5, par6, var12 + 4, 2);
+ --par1ItemStack.stackSize;
+ int var13;
+
+ for (var13 = 0; var13 < 16; ++var13) {
+ double var14 = (double) ((float) par4 + (5.0F + itemRand.nextFloat() * 6.0F) / 16.0F);
+ double var16 = (double) ((float) par5 + 0.8125F);
+ double var18 = (double) ((float) par6 + (5.0F + itemRand.nextFloat() * 6.0F) / 16.0F);
+ double var20 = 0.0D;
+ double var22 = 0.0D;
+ double var24 = 0.0D;
+ par3World.spawnParticle("smoke", var14, var16, var18, var20, var22, var24);
+ }
+
+ var13 = var12 & 3;
+ int var26 = 0;
+ int var15 = 0;
+ boolean var27 = false;
+ boolean var17 = true;
+ int var28 = Direction.enderEyeMetaToDirection[var13];
+ int var19;
+ int var21;
+ int var23;
+ int var29;
+ int var30;
+
+ for (var19 = -2; var19 <= 2; ++var19) {
+ var29 = par4 + Direction.offsetX[var28] * var19;
+ var21 = par6 + Direction.offsetZ[var28] * var19;
+ var30 = par3World.getBlockId(var29, par5, var21);
+
+ if (var30 == Block.endPortalFrame.blockID) {
+ var23 = par3World.getBlockMetadata(var29, par5, var21);
+
+ if (!BlockEndPortalFrame.isEnderEyeInserted(var23)) {
+ var17 = false;
+ break;
+ }
+
+ var15 = var19;
+
+ if (!var27) {
+ var26 = var19;
+ var27 = true;
+ }
+ }
+ }
+
+ if (var17 && var15 == var26 + 2) {
+ for (var19 = var26; var19 <= var15; ++var19) {
+ var29 = par4 + Direction.offsetX[var28] * var19;
+ var21 = par6 + Direction.offsetZ[var28] * var19;
+ var29 += Direction.offsetX[var13] * 4;
+ var21 += Direction.offsetZ[var13] * 4;
+ var30 = par3World.getBlockId(var29, par5, var21);
+ var23 = par3World.getBlockMetadata(var29, par5, var21);
+
+ if (var30 != Block.endPortalFrame.blockID || !BlockEndPortalFrame.isEnderEyeInserted(var23)) {
+ var17 = false;
+ break;
+ }
+ }
+
+ for (var19 = var26 - 1; var19 <= var15 + 1; var19 += 4) {
+ for (var29 = 1; var29 <= 3; ++var29) {
+ var21 = par4 + Direction.offsetX[var28] * var19;
+ var30 = par6 + Direction.offsetZ[var28] * var19;
+ var21 += Direction.offsetX[var13] * var29;
+ var30 += Direction.offsetZ[var13] * var29;
+ var23 = par3World.getBlockId(var21, par5, var30);
+ int var31 = par3World.getBlockMetadata(var21, par5, var30);
+
+ if (var23 != Block.endPortalFrame.blockID
+ || !BlockEndPortalFrame.isEnderEyeInserted(var31)) {
+ var17 = false;
+ break;
+ }
+ }
+ }
+
+ if (var17) {
+ for (var19 = var26; var19 <= var15; ++var19) {
+ for (var29 = 1; var29 <= 3; ++var29) {
+ var21 = par4 + Direction.offsetX[var28] * var19;
+ var30 = par6 + Direction.offsetZ[var28] * var19;
+ var21 += Direction.offsetX[var13] * var29;
+ var30 += Direction.offsetZ[var13] * var29;
+ par3World.setBlock(var21, par5, var30, Block.endPortal.blockID, 0, 2);
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Called whenever this item is equipped and the right mouse button is pressed.
+ * Args: itemStack, world, entityPlayer
+ */
+ public ItemStack onItemRightClick(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer) {
+ MovingObjectPosition var4 = this.getMovingObjectPositionFromPlayer(par2World, par3EntityPlayer, false);
+
+ if (var4 != null && var4.typeOfHit == EnumMovingObjectType.TILE) {
+ int var5 = par2World.getBlockId(var4.blockX, var4.blockY, var4.blockZ);
+
+ if (var5 == Block.endPortalFrame.blockID) {
+ return par1ItemStack;
+ }
+ }
+
+ if (!par2World.isRemote) {
+ ChunkPosition var7 = par2World.findClosestStructure("Stronghold", (int) par3EntityPlayer.posX,
+ (int) par3EntityPlayer.posY, (int) par3EntityPlayer.posZ);
+
+ if (var7 != null) {
+ EntityEnderEye var6 = new EntityEnderEye(par2World, par3EntityPlayer.posX,
+ par3EntityPlayer.posY + 1.62D - (double) par3EntityPlayer.yOffset, par3EntityPlayer.posZ);
+ var6.moveTowards((double) var7.x, var7.y, (double) var7.z);
+ par2World.spawnEntityInWorld(var6);
+ par2World.playSoundAtEntity(par3EntityPlayer, "random.bow", 0.5F,
+ 0.4F / (itemRand.nextFloat() * 0.4F + 0.8F));
+ par2World.playAuxSFXAtEntity((EntityPlayer) null, 1002, (int) par3EntityPlayer.posX,
+ (int) par3EntityPlayer.posY, (int) par3EntityPlayer.posZ, 0);
+
+ if (!par3EntityPlayer.capabilities.isCreativeMode) {
+ --par1ItemStack.stackSize;
+ }
+ }
+ }
+
+ return par1ItemStack;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemEnderPearl.java b/sp-server/src/main/java/net/minecraft/src/ItemEnderPearl.java
new file mode 100644
index 0000000..372a56e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemEnderPearl.java
@@ -0,0 +1,29 @@
+package net.minecraft.src;
+
+public class ItemEnderPearl extends Item {
+ public ItemEnderPearl(int par1) {
+ super(par1);
+ this.maxStackSize = 16;
+ this.setCreativeTab(CreativeTabs.tabMisc);
+ }
+
+ /**
+ * Called whenever this item is equipped and the right mouse button is pressed.
+ * Args: itemStack, world, entityPlayer
+ */
+ public ItemStack onItemRightClick(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer) {
+ if (par3EntityPlayer.ridingEntity != null) {
+ return par1ItemStack;
+ } else {
+ --par1ItemStack.stackSize;
+ par2World.playSoundAtEntity(par3EntityPlayer, "random.bow", 0.5F,
+ 0.4F / (itemRand.nextFloat() * 0.4F + 0.8F));
+
+ if (!par2World.isRemote) {
+ par2World.spawnEntityInWorld(new EntityEnderPearl(par2World, par3EntityPlayer));
+ }
+
+ return par1ItemStack;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemExpBottle.java b/sp-server/src/main/java/net/minecraft/src/ItemExpBottle.java
new file mode 100644
index 0000000..236fd45
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemExpBottle.java
@@ -0,0 +1,26 @@
+package net.minecraft.src;
+
+public class ItemExpBottle extends Item {
+ public ItemExpBottle(int par1) {
+ super(par1);
+ this.setCreativeTab(CreativeTabs.tabMisc);
+ }
+
+ /**
+ * Called whenever this item is equipped and the right mouse button is pressed.
+ * Args: itemStack, world, entityPlayer
+ */
+ public ItemStack onItemRightClick(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer) {
+ if (!par3EntityPlayer.capabilities.isCreativeMode) {
+ --par1ItemStack.stackSize;
+ }
+
+ par2World.playSoundAtEntity(par3EntityPlayer, "random.bow", 0.5F, 0.4F / (itemRand.nextFloat() * 0.4F + 0.8F));
+
+ if (!par2World.isRemote) {
+ par2World.spawnEntityInWorld(new EntityExpBottle(par2World, par3EntityPlayer));
+ }
+
+ return par1ItemStack;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemFireball.java b/sp-server/src/main/java/net/minecraft/src/ItemFireball.java
new file mode 100644
index 0000000..65e537d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemFireball.java
@@ -0,0 +1,62 @@
+package net.minecraft.src;
+
+public class ItemFireball extends Item {
+ public ItemFireball(int par1) {
+ super(par1);
+ this.setCreativeTab(CreativeTabs.tabMisc);
+ }
+
+ /**
+ * Callback for item usage. If the item does something special on right
+ * clicking, he will have one of those. Return True if something happen and
+ * false if it don't. This is for ITEMS, not BLOCKS
+ */
+ public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World par3World, int par4,
+ int par5, int par6, int par7, float par8, float par9, float par10) {
+ if (par3World.isRemote) {
+ return true;
+ } else {
+ if (par7 == 0) {
+ --par5;
+ }
+
+ if (par7 == 1) {
+ ++par5;
+ }
+
+ if (par7 == 2) {
+ --par6;
+ }
+
+ if (par7 == 3) {
+ ++par6;
+ }
+
+ if (par7 == 4) {
+ --par4;
+ }
+
+ if (par7 == 5) {
+ ++par4;
+ }
+
+ if (!par2EntityPlayer.canPlayerEdit(par4, par5, par6, par7, par1ItemStack)) {
+ return false;
+ } else {
+ int var11 = par3World.getBlockId(par4, par5, par6);
+
+ if (var11 == 0) {
+ par3World.playSoundEffect((double) par4 + 0.5D, (double) par5 + 0.5D, (double) par6 + 0.5D,
+ "fire.ignite", 1.0F, itemRand.nextFloat() * 0.4F + 0.8F);
+ par3World.setBlock(par4, par5, par6, Block.fire.blockID);
+ }
+
+ if (!par2EntityPlayer.capabilities.isCreativeMode) {
+ --par1ItemStack.stackSize;
+ }
+
+ return true;
+ }
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemFirework.java b/sp-server/src/main/java/net/minecraft/src/ItemFirework.java
new file mode 100644
index 0000000..cf1ad20
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemFirework.java
@@ -0,0 +1,29 @@
+package net.minecraft.src;
+
+public class ItemFirework extends Item {
+ public ItemFirework(int par1) {
+ super(par1);
+ }
+
+ /**
+ * Callback for item usage. If the item does something special on right
+ * clicking, he will have one of those. Return True if something happen and
+ * false if it don't. This is for ITEMS, not BLOCKS
+ */
+ public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World par3World, int par4,
+ int par5, int par6, int par7, float par8, float par9, float par10) {
+ if (!par3World.isRemote) {
+ EntityFireworkRocket var11 = new EntityFireworkRocket(par3World, (double) ((float) par4 + par8),
+ (double) ((float) par5 + par9), (double) ((float) par6 + par10), par1ItemStack);
+ par3World.spawnEntityInWorld(var11);
+
+ if (!par2EntityPlayer.capabilities.isCreativeMode) {
+ --par1ItemStack.stackSize;
+ }
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemFireworkCharge.java b/sp-server/src/main/java/net/minecraft/src/ItemFireworkCharge.java
new file mode 100644
index 0000000..0cbd393
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemFireworkCharge.java
@@ -0,0 +1,7 @@
+package net.minecraft.src;
+
+public class ItemFireworkCharge extends Item {
+ public ItemFireworkCharge(int par1) {
+ super(par1);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemFishingRod.java b/sp-server/src/main/java/net/minecraft/src/ItemFishingRod.java
new file mode 100644
index 0000000..be8070c
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemFishingRod.java
@@ -0,0 +1,33 @@
+package net.minecraft.src;
+
+public class ItemFishingRod extends Item {
+ public ItemFishingRod(int par1) {
+ super(par1);
+ this.setMaxDamage(64);
+ this.setMaxStackSize(1);
+ this.setCreativeTab(CreativeTabs.tabTools);
+ }
+
+ /**
+ * Called whenever this item is equipped and the right mouse button is pressed.
+ * Args: itemStack, world, entityPlayer
+ */
+ public ItemStack onItemRightClick(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer) {
+ if (par3EntityPlayer.fishEntity != null) {
+ int var4 = par3EntityPlayer.fishEntity.catchFish();
+ par1ItemStack.damageItem(var4, par3EntityPlayer);
+ par3EntityPlayer.swingItem();
+ } else {
+ par2World.playSoundAtEntity(par3EntityPlayer, "random.bow", 0.5F,
+ 0.4F / (itemRand.nextFloat() * 0.4F + 0.8F));
+
+ if (!par2World.isRemote) {
+ par2World.spawnEntityInWorld(new EntityFishHook(par2World, par3EntityPlayer));
+ }
+
+ par3EntityPlayer.swingItem();
+ }
+
+ return par1ItemStack;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemFlintAndSteel.java b/sp-server/src/main/java/net/minecraft/src/ItemFlintAndSteel.java
new file mode 100644
index 0000000..f5a9b8d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemFlintAndSteel.java
@@ -0,0 +1,57 @@
+package net.minecraft.src;
+
+public class ItemFlintAndSteel extends Item {
+ public ItemFlintAndSteel(int par1) {
+ super(par1);
+ this.maxStackSize = 1;
+ this.setMaxDamage(64);
+ this.setCreativeTab(CreativeTabs.tabTools);
+ }
+
+ /**
+ * Callback for item usage. If the item does something special on right
+ * clicking, he will have one of those. Return True if something happen and
+ * false if it don't. This is for ITEMS, not BLOCKS
+ */
+ public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World par3World, int par4,
+ int par5, int par6, int par7, float par8, float par9, float par10) {
+ if (par7 == 0) {
+ --par5;
+ }
+
+ if (par7 == 1) {
+ ++par5;
+ }
+
+ if (par7 == 2) {
+ --par6;
+ }
+
+ if (par7 == 3) {
+ ++par6;
+ }
+
+ if (par7 == 4) {
+ --par4;
+ }
+
+ if (par7 == 5) {
+ ++par4;
+ }
+
+ if (!par2EntityPlayer.canPlayerEdit(par4, par5, par6, par7, par1ItemStack)) {
+ return false;
+ } else {
+ int var11 = par3World.getBlockId(par4, par5, par6);
+
+ if (var11 == 0) {
+ par3World.playSoundEffect((double) par4 + 0.5D, (double) par5 + 0.5D, (double) par6 + 0.5D,
+ "fire.ignite", 1.0F, itemRand.nextFloat() * 0.4F + 0.8F);
+ par3World.setBlock(par4, par5, par6, Block.fire.blockID);
+ }
+
+ par1ItemStack.damageItem(1, par2EntityPlayer);
+ return true;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemFood.java b/sp-server/src/main/java/net/minecraft/src/ItemFood.java
new file mode 100644
index 0000000..e79c8cb
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemFood.java
@@ -0,0 +1,128 @@
+package net.minecraft.src;
+
+public class ItemFood extends Item {
+ /** Number of ticks to run while 'EnumAction'ing until result. */
+ public final int itemUseDuration;
+
+ /** The amount this food item heals the player. */
+ private final int healAmount;
+ private final float saturationModifier;
+
+ /** Whether wolves like this food (true for raw and cooked porkchop). */
+ private final boolean isWolfsFavoriteMeat;
+
+ /**
+ * If this field is true, the food can be consumed even if the player don't need
+ * to eat.
+ */
+ private boolean alwaysEdible;
+
+ /**
+ * represents the potion effect that will occurr upon eating this food. Set by
+ * setPotionEffect
+ */
+ private int potionId;
+
+ /** set by setPotionEffect */
+ private int potionDuration;
+
+ /** set by setPotionEffect */
+ private int potionAmplifier;
+
+ /** probably of the set potion effect occurring */
+ private float potionEffectProbability;
+
+ public ItemFood(int par1, int par2, float par3, boolean par4) {
+ super(par1);
+ this.itemUseDuration = 32;
+ this.healAmount = par2;
+ this.isWolfsFavoriteMeat = par4;
+ this.saturationModifier = par3;
+ this.setCreativeTab(CreativeTabs.tabFood);
+ }
+
+ public ItemFood(int par1, int par2, boolean par3) {
+ this(par1, par2, 0.6F, par3);
+ }
+
+ public ItemStack onEaten(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer) {
+ --par1ItemStack.stackSize;
+ par3EntityPlayer.getFoodStats().addStats(this);
+ par2World.playSoundAtEntity(par3EntityPlayer, "random.burp", 0.5F, par2World.rand.nextFloat() * 0.1F + 0.9F);
+ this.onFoodEaten(par1ItemStack, par2World, par3EntityPlayer);
+ return par1ItemStack;
+ }
+
+ protected void onFoodEaten(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer) {
+ if (!par2World.isRemote && this.potionId > 0 && par2World.rand.nextFloat() < this.potionEffectProbability) {
+ par3EntityPlayer
+ .addPotionEffect(new PotionEffect(this.potionId, this.potionDuration * 20, this.potionAmplifier));
+ }
+ }
+
+ /**
+ * How long it takes to use or consume an item
+ */
+ public int getMaxItemUseDuration(ItemStack par1ItemStack) {
+ return 32;
+ }
+
+ /**
+ * returns the action that specifies what animation to play when the items is
+ * being used
+ */
+ public EnumAction getItemUseAction(ItemStack par1ItemStack) {
+ return EnumAction.eat;
+ }
+
+ /**
+ * Called whenever this item is equipped and the right mouse button is pressed.
+ * Args: itemStack, world, entityPlayer
+ */
+ public ItemStack onItemRightClick(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer) {
+ if (par3EntityPlayer.canEat(this.alwaysEdible)) {
+ par3EntityPlayer.setItemInUse(par1ItemStack, this.getMaxItemUseDuration(par1ItemStack));
+ }
+
+ return par1ItemStack;
+ }
+
+ public int getHealAmount() {
+ return this.healAmount;
+ }
+
+ /**
+ * gets the saturationModifier of the ItemFood
+ */
+ public float getSaturationModifier() {
+ return this.saturationModifier;
+ }
+
+ /**
+ * Whether wolves like this food (true for raw and cooked porkchop).
+ */
+ public boolean isWolfsFavoriteMeat() {
+ return this.isWolfsFavoriteMeat;
+ }
+
+ /**
+ * sets a potion effect on the item. Args: int potionId, int duration (will be
+ * multiplied by 20), int amplifier, float probability of effect happening
+ */
+ public ItemFood setPotionEffect(int par1, int par2, int par3, float par4) {
+ this.potionId = par1;
+ this.potionDuration = par2;
+ this.potionAmplifier = par3;
+ this.potionEffectProbability = par4;
+ return this;
+ }
+
+ /**
+ * Set the field 'alwaysEdible' to true, and make the food edible even if the
+ * player don't need to eat.
+ */
+ public ItemFood setAlwaysEdible() {
+ this.alwaysEdible = true;
+ return this;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemGlassBottle.java b/sp-server/src/main/java/net/minecraft/src/ItemGlassBottle.java
new file mode 100644
index 0000000..b8e4015
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemGlassBottle.java
@@ -0,0 +1,48 @@
+package net.minecraft.src;
+
+public class ItemGlassBottle extends Item {
+ public ItemGlassBottle(int par1) {
+ super(par1);
+ this.setCreativeTab(CreativeTabs.tabBrewing);
+ }
+
+ /**
+ * Called whenever this item is equipped and the right mouse button is pressed.
+ * Args: itemStack, world, entityPlayer
+ */
+ public ItemStack onItemRightClick(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer) {
+ MovingObjectPosition var4 = this.getMovingObjectPositionFromPlayer(par2World, par3EntityPlayer, true);
+
+ if (var4 == null) {
+ return par1ItemStack;
+ } else {
+ if (var4.typeOfHit == EnumMovingObjectType.TILE) {
+ int var5 = var4.blockX;
+ int var6 = var4.blockY;
+ int var7 = var4.blockZ;
+
+ if (!par2World.canMineBlock(par3EntityPlayer, var5, var6, var7)) {
+ return par1ItemStack;
+ }
+
+ if (!par3EntityPlayer.canPlayerEdit(var5, var6, var7, var4.sideHit, par1ItemStack)) {
+ return par1ItemStack;
+ }
+
+ if (par2World.getBlockMaterial(var5, var6, var7) == Material.water) {
+ --par1ItemStack.stackSize;
+
+ if (par1ItemStack.stackSize <= 0) {
+ return new ItemStack(Item.potion);
+ }
+
+ if (!par3EntityPlayer.inventory.addItemStackToInventory(new ItemStack(Item.potion))) {
+ par3EntityPlayer.dropPlayerItem(new ItemStack(Item.potion.itemID, 1, 0));
+ }
+ }
+ }
+
+ return par1ItemStack;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemHangingEntity.java b/sp-server/src/main/java/net/minecraft/src/ItemHangingEntity.java
new file mode 100644
index 0000000..836ea5c
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemHangingEntity.java
@@ -0,0 +1,53 @@
+package net.minecraft.src;
+
+public class ItemHangingEntity extends Item {
+ private final Class hangingEntityClass;
+
+ public ItemHangingEntity(int par1, Class par2Class) {
+ super(par1);
+ this.hangingEntityClass = par2Class;
+ this.setCreativeTab(CreativeTabs.tabDecorations);
+ }
+
+ /**
+ * Callback for item usage. If the item does something special on right
+ * clicking, he will have one of those. Return True if something happen and
+ * false if it don't. This is for ITEMS, not BLOCKS
+ */
+ public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World par3World, int par4,
+ int par5, int par6, int par7, float par8, float par9, float par10) {
+ if (par7 == 0) {
+ return false;
+ } else if (par7 == 1) {
+ return false;
+ } else {
+ int var11 = Direction.facingToDirection[par7];
+ EntityHanging var12 = this.createHangingEntity(par3World, par4, par5, par6, var11);
+
+ if (!par2EntityPlayer.canPlayerEdit(par4, par5, par6, par7, par1ItemStack)) {
+ return false;
+ } else {
+ if (var12 != null && var12.onValidSurface()) {
+ if (!par3World.isRemote) {
+ par3World.spawnEntityInWorld(var12);
+ }
+
+ --par1ItemStack.stackSize;
+ }
+
+ return true;
+ }
+ }
+ }
+
+ /**
+ * Create the hanging entity associated to this item.
+ */
+ private EntityHanging createHangingEntity(World par1World, int par2, int par3, int par4, int par5) {
+ return (EntityHanging) (this.hangingEntityClass == EntityPainting.class
+ ? new EntityPainting(par1World, par2, par3, par4, par5)
+ : (this.hangingEntityClass == EntityItemFrame.class
+ ? new EntityItemFrame(par1World, par2, par3, par4, par5)
+ : null));
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemHoe.java b/sp-server/src/main/java/net/minecraft/src/ItemHoe.java
new file mode 100644
index 0000000..cb35f34
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemHoe.java
@@ -0,0 +1,53 @@
+package net.minecraft.src;
+
+public class ItemHoe extends Item {
+ protected EnumToolMaterial theToolMaterial;
+
+ public ItemHoe(int par1, EnumToolMaterial par2EnumToolMaterial) {
+ super(par1);
+ this.theToolMaterial = par2EnumToolMaterial;
+ this.maxStackSize = 1;
+ this.setMaxDamage(par2EnumToolMaterial.getMaxUses());
+ this.setCreativeTab(CreativeTabs.tabTools);
+ }
+
+ /**
+ * Callback for item usage. If the item does something special on right
+ * clicking, he will have one of those. Return True if something happen and
+ * false if it don't. This is for ITEMS, not BLOCKS
+ */
+ public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World par3World, int par4,
+ int par5, int par6, int par7, float par8, float par9, float par10) {
+ if (!par2EntityPlayer.canPlayerEdit(par4, par5, par6, par7, par1ItemStack)) {
+ return false;
+ } else {
+ int var11 = par3World.getBlockId(par4, par5, par6);
+ int var12 = par3World.getBlockId(par4, par5 + 1, par6);
+
+ if ((par7 == 0 || var12 != 0 || var11 != Block.grass.blockID) && var11 != Block.dirt.blockID) {
+ return false;
+ } else {
+ Block var13 = Block.tilledField;
+ par3World.playSoundEffect((double) ((float) par4 + 0.5F), (double) ((float) par5 + 0.5F),
+ (double) ((float) par6 + 0.5F), var13.stepSound.getStepSound(),
+ (var13.stepSound.getVolume() + 1.0F) / 2.0F, var13.stepSound.getPitch() * 0.8F);
+
+ if (par3World.isRemote) {
+ return true;
+ } else {
+ par3World.setBlock(par4, par5, par6, var13.blockID);
+ par1ItemStack.damageItem(1, par2EntityPlayer);
+ return true;
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the name of the material this tool is made from as it is declared in
+ * EnumToolMaterial (meaning diamond would return "EMERALD")
+ */
+ public String getMaterialName() {
+ return this.theToolMaterial.toString();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemInWorldManager.java b/sp-server/src/main/java/net/minecraft/src/ItemInWorldManager.java
new file mode 100644
index 0000000..3de549c
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemInWorldManager.java
@@ -0,0 +1,323 @@
+package net.minecraft.src;
+
+public class ItemInWorldManager {
+ /** The world object that this object is connected to. */
+ public World theWorld;
+
+ /** The EntityPlayerMP object that this object is connected to. */
+ public EntityPlayerMP thisPlayerMP;
+ private EnumGameType gameType;
+
+ /** True if the player is destroying a block */
+ private boolean isDestroyingBlock;
+ private int initialDamage;
+ private int curBlockX;
+ private int curBlockY;
+ private int curBlockZ;
+ private int curblockDamage;
+
+ /**
+ * Set to true when the "finished destroying block" packet is received but the
+ * block wasn't fully damaged yet. The block will not be destroyed while this is
+ * false.
+ */
+ private boolean receivedFinishDiggingPacket;
+ private int posX;
+ private int posY;
+ private int posZ;
+ private int field_73093_n;
+ private int durabilityRemainingOnBlock;
+
+ public ItemInWorldManager(World par1World) {
+ this.gameType = EnumGameType.NOT_SET;
+ this.durabilityRemainingOnBlock = -1;
+ this.theWorld = par1World;
+ }
+
+ public void setGameType(EnumGameType par1EnumGameType) {
+ this.gameType = par1EnumGameType;
+ par1EnumGameType.configurePlayerCapabilities(this.thisPlayerMP.capabilities);
+ this.thisPlayerMP.sendPlayerAbilities();
+ }
+
+ public EnumGameType getGameType() {
+ return this.gameType;
+ }
+
+ /**
+ * Get if we are in creative game mode.
+ */
+ public boolean isCreative() {
+ return this.gameType.isCreative();
+ }
+
+ /**
+ * if the gameType is currently NOT_SET then change it to par1
+ */
+ public void initializeGameType(EnumGameType par1EnumGameType) {
+ if (this.gameType == EnumGameType.NOT_SET) {
+ this.gameType = par1EnumGameType;
+ }
+
+ this.setGameType(this.gameType);
+ }
+
+ public void updateBlockRemoving() {
+ ++this.curblockDamage;
+ int var1;
+ float var4;
+ int var5;
+
+ if (this.receivedFinishDiggingPacket) {
+ var1 = this.curblockDamage - this.field_73093_n;
+ int var2 = this.theWorld.getBlockId(this.posX, this.posY, this.posZ);
+
+ if (var2 == 0) {
+ this.receivedFinishDiggingPacket = false;
+ } else {
+ Block var3 = Block.blocksList[var2];
+ var4 = var3.getPlayerRelativeBlockHardness(this.thisPlayerMP, this.thisPlayerMP.worldObj, this.posX,
+ this.posY, this.posZ) * (float) (var1 + 1);
+ var5 = (int) (var4 * 10.0F);
+
+ if (var5 != this.durabilityRemainingOnBlock) {
+ this.theWorld.destroyBlockInWorldPartially(this.thisPlayerMP.entityId, this.posX, this.posY,
+ this.posZ, var5);
+ this.durabilityRemainingOnBlock = var5;
+ }
+
+ if (var4 >= 1.0F) {
+ this.receivedFinishDiggingPacket = false;
+ this.tryHarvestBlock(this.posX, this.posY, this.posZ);
+ }
+ }
+ } else if (this.isDestroyingBlock) {
+ var1 = this.theWorld.getBlockId(this.curBlockX, this.curBlockY, this.curBlockZ);
+ Block var6 = Block.blocksList[var1];
+
+ if (var6 == null) {
+ this.theWorld.destroyBlockInWorldPartially(this.thisPlayerMP.entityId, this.curBlockX, this.curBlockY,
+ this.curBlockZ, -1);
+ this.durabilityRemainingOnBlock = -1;
+ this.isDestroyingBlock = false;
+ } else {
+ int var7 = this.curblockDamage - this.initialDamage;
+ var4 = var6.getPlayerRelativeBlockHardness(this.thisPlayerMP, this.thisPlayerMP.worldObj,
+ this.curBlockX, this.curBlockY, this.curBlockZ) * (float) (var7 + 1);
+ var5 = (int) (var4 * 10.0F);
+
+ if (var5 != this.durabilityRemainingOnBlock) {
+ this.theWorld.destroyBlockInWorldPartially(this.thisPlayerMP.entityId, this.curBlockX,
+ this.curBlockY, this.curBlockZ, var5);
+ this.durabilityRemainingOnBlock = var5;
+ }
+ }
+ }
+ }
+
+ /**
+ * if not creative, it calls destroyBlockInWorldPartially untill the block is
+ * broken first. par4 is the specific side. tryHarvestBlock can also be the
+ * result of this call
+ */
+ public void onBlockClicked(int par1, int par2, int par3, int par4) {
+ if (!this.gameType.isAdventure() || this.thisPlayerMP.canCurrentToolHarvestBlock(par1, par2, par3)) {
+ if (this.isCreative()) {
+ if (!this.theWorld.extinguishFire((EntityPlayer) null, par1, par2, par3, par4)) {
+ this.tryHarvestBlock(par1, par2, par3);
+ }
+ } else {
+ this.theWorld.extinguishFire((EntityPlayer) null, par1, par2, par3, par4);
+ this.initialDamage = this.curblockDamage;
+ float var5 = 1.0F;
+ int var6 = this.theWorld.getBlockId(par1, par2, par3);
+
+ if (var6 > 0) {
+ Block.blocksList[var6].onBlockClicked(this.theWorld, par1, par2, par3, this.thisPlayerMP);
+ var5 = Block.blocksList[var6].getPlayerRelativeBlockHardness(this.thisPlayerMP,
+ this.thisPlayerMP.worldObj, par1, par2, par3);
+ }
+
+ if (var6 > 0 && var5 >= 1.0F) {
+ this.tryHarvestBlock(par1, par2, par3);
+ } else {
+ this.isDestroyingBlock = true;
+ this.curBlockX = par1;
+ this.curBlockY = par2;
+ this.curBlockZ = par3;
+ int var7 = (int) (var5 * 10.0F);
+ this.theWorld.destroyBlockInWorldPartially(this.thisPlayerMP.entityId, par1, par2, par3, var7);
+ this.durabilityRemainingOnBlock = var7;
+ }
+ }
+ }
+ }
+
+ public void blockRemoving(int par1, int par2, int par3) {
+ if (par1 == this.curBlockX && par2 == this.curBlockY && par3 == this.curBlockZ) {
+ int var4 = this.curblockDamage - this.initialDamage;
+ int var5 = this.theWorld.getBlockId(par1, par2, par3);
+
+ if (var5 != 0) {
+ Block var6 = Block.blocksList[var5];
+ float var7 = var6.getPlayerRelativeBlockHardness(this.thisPlayerMP, this.thisPlayerMP.worldObj, par1,
+ par2, par3) * (float) (var4 + 1);
+
+ if (var7 >= 0.7F) {
+ this.isDestroyingBlock = false;
+ this.theWorld.destroyBlockInWorldPartially(this.thisPlayerMP.entityId, par1, par2, par3, -1);
+ this.tryHarvestBlock(par1, par2, par3);
+ } else if (!this.receivedFinishDiggingPacket) {
+ this.isDestroyingBlock = false;
+ this.receivedFinishDiggingPacket = true;
+ this.posX = par1;
+ this.posY = par2;
+ this.posZ = par3;
+ this.field_73093_n = this.initialDamage;
+ }
+ }
+ }
+ }
+
+ /**
+ * note: this ignores the pars passed in and continues to destroy the
+ * onClickedBlock
+ */
+ public void cancelDestroyingBlock(int par1, int par2, int par3) {
+ this.isDestroyingBlock = false;
+ this.theWorld.destroyBlockInWorldPartially(this.thisPlayerMP.entityId, this.curBlockX, this.curBlockY,
+ this.curBlockZ, -1);
+ }
+
+ /**
+ * Removes a block and triggers the appropriate events
+ */
+ private boolean removeBlock(int par1, int par2, int par3) {
+ Block var4 = Block.blocksList[this.theWorld.getBlockId(par1, par2, par3)];
+ int var5 = this.theWorld.getBlockMetadata(par1, par2, par3);
+
+ if (var4 != null) {
+ var4.onBlockHarvested(this.theWorld, par1, par2, par3, var5, this.thisPlayerMP);
+ }
+
+ boolean var6 = this.theWorld.setBlockToAir(par1, par2, par3);
+
+ if (var4 != null && var6) {
+ var4.onBlockDestroyedByPlayer(this.theWorld, par1, par2, par3, var5);
+ }
+
+ return var6;
+ }
+
+ /**
+ * Attempts to harvest a block at the given coordinate
+ */
+ public boolean tryHarvestBlock(int par1, int par2, int par3) {
+ if (this.gameType.isAdventure() && !this.thisPlayerMP.canCurrentToolHarvestBlock(par1, par2, par3)) {
+ return false;
+ } else {
+ int var4 = this.theWorld.getBlockId(par1, par2, par3);
+ int var5 = this.theWorld.getBlockMetadata(par1, par2, par3);
+ this.theWorld.playAuxSFXAtEntity(this.thisPlayerMP, 2001, par1, par2, par3,
+ var4 + (this.theWorld.getBlockMetadata(par1, par2, par3) << 12));
+ boolean var6 = this.removeBlock(par1, par2, par3);
+
+ if (this.isCreative()) {
+ this.thisPlayerMP.playerNetServerHandler
+ .sendPacket(new Packet53BlockChange(par1, par2, par3, this.theWorld));
+ } else {
+ ItemStack var7 = this.thisPlayerMP.getCurrentEquippedItem();
+ boolean var8 = this.thisPlayerMP.canHarvestBlock(Block.blocksList[var4]);
+
+ if (var7 != null) {
+ var7.onBlockDestroyed(this.theWorld, var4, par1, par2, par3, this.thisPlayerMP);
+
+ if (var7.stackSize == 0) {
+ this.thisPlayerMP.destroyCurrentEquippedItem();
+ }
+ }
+
+ if (var6 && var8) {
+ Block.blocksList[var4].harvestBlock(this.theWorld, this.thisPlayerMP, par1, par2, par3, var5);
+ }
+ }
+
+ return var6;
+ }
+ }
+
+ /**
+ * Attempts to right-click use an item by the given EntityPlayer in the given
+ * World
+ */
+ public boolean tryUseItem(EntityPlayer par1EntityPlayer, World par2World, ItemStack par3ItemStack) {
+ int var4 = par3ItemStack.stackSize;
+ int var5 = par3ItemStack.getItemDamage();
+ ItemStack var6 = par3ItemStack.useItemRightClick(par2World, par1EntityPlayer);
+
+ if (var6 == par3ItemStack && (var6 == null
+ || var6.stackSize == var4 && var6.getMaxItemUseDuration() <= 0 && var6.getItemDamage() == var5)) {
+ return false;
+ } else {
+ par1EntityPlayer.inventory.mainInventory[par1EntityPlayer.inventory.currentItem] = var6;
+
+ if (this.isCreative()) {
+ var6.stackSize = var4;
+
+ if (var6.isItemStackDamageable()) {
+ var6.setItemDamage(var5);
+ }
+ }
+
+ if (var6.stackSize == 0) {
+ par1EntityPlayer.inventory.mainInventory[par1EntityPlayer.inventory.currentItem] = null;
+ }
+
+ if (!par1EntityPlayer.isUsingItem()) {
+ ((EntityPlayerMP) par1EntityPlayer).sendContainerToPlayer(par1EntityPlayer.inventoryContainer);
+ }
+
+ return true;
+ }
+ }
+
+ /**
+ * Activate the clicked on block, otherwise use the held item. Args: player,
+ * world, itemStack, x, y, z, side, xOffset, yOffset, zOffset
+ */
+ public boolean activateBlockOrUseItem(EntityPlayer par1EntityPlayer, World par2World, ItemStack par3ItemStack,
+ int par4, int par5, int par6, int par7, float par8, float par9, float par10) {
+ int var11;
+
+ if (!par1EntityPlayer.isSneaking() || par1EntityPlayer.getHeldItem() == null) {
+ var11 = par2World.getBlockId(par4, par5, par6);
+
+ if (var11 > 0 && Block.blocksList[var11].onBlockActivated(par2World, par4, par5, par6, par1EntityPlayer,
+ par7, par8, par9, par10)) {
+ return true;
+ }
+ }
+
+ if (par3ItemStack == null) {
+ return false;
+ } else if (this.isCreative()) {
+ var11 = par3ItemStack.getItemDamage();
+ int var12 = par3ItemStack.stackSize;
+ boolean var13 = par3ItemStack.tryPlaceItemIntoWorld(par1EntityPlayer, par2World, par4, par5, par6, par7,
+ par8, par9, par10);
+ par3ItemStack.setItemDamage(var11);
+ par3ItemStack.stackSize = var12;
+ return var13;
+ } else {
+ return par3ItemStack.tryPlaceItemIntoWorld(par1EntityPlayer, par2World, par4, par5, par6, par7, par8, par9,
+ par10);
+ }
+ }
+
+ /**
+ * Sets the world instance.
+ */
+ public void setWorld(WorldServer par1WorldServer) {
+ this.theWorld = par1WorldServer;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemLeaves.java b/sp-server/src/main/java/net/minecraft/src/ItemLeaves.java
new file mode 100644
index 0000000..171a148
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemLeaves.java
@@ -0,0 +1,30 @@
+package net.minecraft.src;
+
+public class ItemLeaves extends ItemBlock {
+ public ItemLeaves(int par1) {
+ super(par1);
+ this.setMaxDamage(0);
+ this.setHasSubtypes(true);
+ }
+
+ /**
+ * Returns the metadata of the block which this Item (ItemBlock) can place
+ */
+ public int getMetadata(int par1) {
+ return par1 | 4;
+ }
+
+ /**
+ * Returns the unlocalized name of this item. This version accepts an ItemStack
+ * so different stacks can have different names based on their damage or NBT.
+ */
+ public String getUnlocalizedName(ItemStack par1ItemStack) {
+ int var2 = par1ItemStack.getItemDamage();
+
+ if (var2 < 0 || var2 >= BlockLeaves.LEAF_TYPES.length) {
+ var2 = 0;
+ }
+
+ return super.getUnlocalizedName() + "." + BlockLeaves.LEAF_TYPES[var2];
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemLilyPad.java b/sp-server/src/main/java/net/minecraft/src/ItemLilyPad.java
new file mode 100644
index 0000000..12c1d80
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemLilyPad.java
@@ -0,0 +1,45 @@
+package net.minecraft.src;
+
+public class ItemLilyPad extends ItemColored {
+ public ItemLilyPad(int par1) {
+ super(par1, false);
+ }
+
+ /**
+ * Called whenever this item is equipped and the right mouse button is pressed.
+ * Args: itemStack, world, entityPlayer
+ */
+ public ItemStack onItemRightClick(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer) {
+ MovingObjectPosition var4 = this.getMovingObjectPositionFromPlayer(par2World, par3EntityPlayer, true);
+
+ if (var4 == null) {
+ return par1ItemStack;
+ } else {
+ if (var4.typeOfHit == EnumMovingObjectType.TILE) {
+ int var5 = var4.blockX;
+ int var6 = var4.blockY;
+ int var7 = var4.blockZ;
+
+ if (!par2World.canMineBlock(par3EntityPlayer, var5, var6, var7)) {
+ return par1ItemStack;
+ }
+
+ if (!par3EntityPlayer.canPlayerEdit(var5, var6, var7, var4.sideHit, par1ItemStack)) {
+ return par1ItemStack;
+ }
+
+ if (par2World.getBlockMaterial(var5, var6, var7) == Material.water
+ && par2World.getBlockMetadata(var5, var6, var7) == 0
+ && par2World.isAirBlock(var5, var6 + 1, var7)) {
+ par2World.setBlock(var5, var6 + 1, var7, Block.waterlily.blockID);
+
+ if (!par3EntityPlayer.capabilities.isCreativeMode) {
+ --par1ItemStack.stackSize;
+ }
+ }
+ }
+
+ return par1ItemStack;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemMap.java b/sp-server/src/main/java/net/minecraft/src/ItemMap.java
new file mode 100644
index 0000000..fa251ee
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemMap.java
@@ -0,0 +1,258 @@
+package net.minecraft.src;
+
+public class ItemMap extends ItemMapBase {
+ protected ItemMap(int par1) {
+ super(par1);
+ this.setHasSubtypes(true);
+ }
+
+ public MapData getMapData(ItemStack par1ItemStack, World par2World) {
+ String var3 = "map_" + par1ItemStack.getItemDamage();
+ MapData var4 = (MapData) par2World.loadItemData((s) -> new MapData(s), var3);
+
+ if (var4 == null && !par2World.isRemote) {
+ par1ItemStack.setItemDamage(par2World.getUniqueDataId("map"));
+ var3 = "map_" + par1ItemStack.getItemDamage();
+ var4 = new MapData(var3);
+ var4.scale = 3;
+ int var5 = 128 * (1 << var4.scale);
+ var4.xCenter = Math.round((float) par2World.getWorldInfo().getSpawnX() / (float) var5) * var5;
+ var4.zCenter = Math.round((float) (par2World.getWorldInfo().getSpawnZ() / var5)) * var5;
+ var4.dimension = (byte) par2World.provider.dimensionId;
+ var4.markDirty();
+ par2World.setItemData(var3, var4);
+ }
+
+ return var4;
+ }
+
+ public void updateMapData(World par1World, Entity par2Entity, MapData par3MapData) {
+ if (par1World.provider.dimensionId == par3MapData.dimension && par2Entity instanceof EntityPlayer) {
+ short var4 = 128;
+ short var5 = 128;
+ int var6 = 1 << par3MapData.scale;
+ int var7 = par3MapData.xCenter;
+ int var8 = par3MapData.zCenter;
+ int var9 = MathHelper.floor_double(par2Entity.posX - (double) var7) / var6 + var4 / 2;
+ int var10 = MathHelper.floor_double(par2Entity.posZ - (double) var8) / var6 + var5 / 2;
+ int var11 = 128 / var6;
+
+ if (par1World.provider.hasNoSky) {
+ var11 /= 2;
+ }
+
+ MapInfo var12 = par3MapData.func_82568_a((EntityPlayer) par2Entity);
+ ++var12.field_82569_d;
+
+ for (int var13 = var9 - var11 + 1; var13 < var9 + var11; ++var13) {
+ if ((var13 & 15) == (var12.field_82569_d & 15)) {
+ int var14 = 255;
+ int var15 = 0;
+ double var16 = 0.0D;
+
+ for (int var18 = var10 - var11 - 1; var18 < var10 + var11; ++var18) {
+ if (var13 >= 0 && var18 >= -1 && var13 < var4 && var18 < var5) {
+ int var19 = var13 - var9;
+ int var20 = var18 - var10;
+ boolean var21 = var19 * var19 + var20 * var20 > (var11 - 2) * (var11 - 2);
+ int var22 = (var7 / var6 + var13 - var4 / 2) * var6;
+ int var23 = (var8 / var6 + var18 - var5 / 2) * var6;
+ int[] var24 = new int[256];
+ Chunk var25 = par1World.getChunkFromBlockCoords(var22, var23);
+
+ if (!var25.isEmpty()) {
+ int var26 = var22 & 15;
+ int var27 = var23 & 15;
+ int var28 = 0;
+ double var29 = 0.0D;
+ int var31;
+ int var32;
+ int var33;
+ int var36;
+
+ if (par1World.provider.hasNoSky) {
+ var31 = var22 + var23 * 231871;
+ var31 = var31 * var31 * 31287121 + var31 * 11;
+
+ if ((var31 >> 20 & 1) == 0) {
+ var24[Block.dirt.blockID] += 10;
+ } else {
+ var24[Block.stone.blockID] += 10;
+ }
+
+ var29 = 100.0D;
+ } else {
+ for (var31 = 0; var31 < var6; ++var31) {
+ for (var32 = 0; var32 < var6; ++var32) {
+ var33 = var25.getHeightValue(var31 + var26, var32 + var27) + 1;
+ int var34 = 0;
+
+ if (var33 > 1) {
+ boolean var35;
+
+ do {
+ var35 = true;
+ var34 = var25.getBlockID(var31 + var26, var33 - 1, var32 + var27);
+
+ if (var34 == 0) {
+ var35 = false;
+ } else if (var33 > 0 && var34 > 0
+ && Block.blocksList[var34].blockMaterial.materialMapColor == MapColor.airColor) {
+ var35 = false;
+ }
+
+ if (!var35) {
+ --var33;
+
+ if (var33 <= 0) {
+ break;
+ }
+
+ var34 = var25.getBlockID(var31 + var26, var33 - 1,
+ var32 + var27);
+ }
+ } while (var33 > 0 && !var35);
+
+ if (var33 > 0 && var34 != 0
+ && Block.blocksList[var34].blockMaterial.isLiquid()) {
+ var36 = var33 - 1;
+ boolean var37 = false;
+ int var41;
+
+ do {
+ var41 = var25.getBlockID(var31 + var26, var36--, var32 + var27);
+ ++var28;
+ } while (var36 > 0 && var41 != 0
+ && Block.blocksList[var41].blockMaterial.isLiquid());
+ }
+ }
+
+ var29 += (double) var33 / (double) (var6 * var6);
+ ++var24[var34];
+ }
+ }
+ }
+
+ var28 /= var6 * var6;
+ var31 = 0;
+ var32 = 0;
+
+ for (var33 = 0; var33 < 256; ++var33) {
+ if (var24[var33] > var31) {
+ var32 = var33;
+ var31 = var24[var33];
+ }
+ }
+
+ double var39 = (var29 - var16) * 4.0D / (double) (var6 + 4)
+ + ((double) (var13 + var18 & 1) - 0.5D) * 0.4D;
+ byte var40 = 1;
+
+ if (var39 > 0.6D) {
+ var40 = 2;
+ }
+
+ if (var39 < -0.6D) {
+ var40 = 0;
+ }
+
+ var36 = 0;
+
+ if (var32 > 0) {
+ MapColor var42 = Block.blocksList[var32].blockMaterial.materialMapColor;
+
+ if (var42 == MapColor.waterColor) {
+ var39 = (double) var28 * 0.1D + (double) (var13 + var18 & 1) * 0.2D;
+ var40 = 1;
+
+ if (var39 < 0.5D) {
+ var40 = 2;
+ }
+
+ if (var39 > 0.9D) {
+ var40 = 0;
+ }
+ }
+
+ var36 = var42.colorIndex;
+ }
+
+ var16 = var29;
+
+ if (var18 >= 0 && var19 * var19 + var20 * var20 < var11 * var11
+ && (!var21 || (var13 + var18 & 1) != 0)) {
+ byte var43 = par3MapData.colors[var13 + var18 * var4];
+ byte var38 = (byte) (var36 * 4 + var40);
+
+ if (var43 != var38) {
+ if (var14 > var18) {
+ var14 = var18;
+ }
+
+ if (var15 < var18) {
+ var15 = var18;
+ }
+
+ par3MapData.colors[var13 + var18 * var4] = var38;
+ }
+ }
+ }
+ }
+ }
+
+ if (var14 <= var15) {
+ par3MapData.setColumnDirty(var13, var14, var15);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Called each tick as long the item is on a player inventory. Uses by maps to
+ * check if is on a player hand and update it's contents.
+ */
+ public void onUpdate(ItemStack par1ItemStack, World par2World, Entity par3Entity, int par4, boolean par5) {
+ if (!par2World.isRemote) {
+ MapData var6 = this.getMapData(par1ItemStack, par2World);
+
+ if (par3Entity instanceof EntityPlayer) {
+ EntityPlayer var7 = (EntityPlayer) par3Entity;
+ var6.updateVisiblePlayers(var7, par1ItemStack);
+ }
+
+ if (par5) {
+ this.updateMapData(par2World, par3Entity, var6);
+ }
+ }
+ }
+
+ public Packet getUpdatePacket(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer) {
+ byte[] var4 = this.getMapData(par1ItemStack, par2World).getUpdatePacketData(par1ItemStack, par2World,
+ par3EntityPlayer);
+ return var4 == null ? null
+ : new Packet131MapData((short) Item.map.itemID, (short) par1ItemStack.getItemDamage(), var4);
+ }
+
+ /**
+ * Called when item is crafted/smelted. Used only by maps so far.
+ */
+ public void onCreated(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer) {
+ if (par1ItemStack.hasTagCompound() && par1ItemStack.getTagCompound().getBoolean("map_is_scaling")) {
+ MapData var4 = Item.map.getMapData(par1ItemStack, par2World);
+ par1ItemStack.setItemDamage(par2World.getUniqueDataId("map"));
+ MapData var5 = new MapData("map_" + par1ItemStack.getItemDamage());
+ var5.scale = (byte) (var4.scale + 1);
+
+ if (var5.scale > 4) {
+ var5.scale = 4;
+ }
+
+ var5.xCenter = var4.xCenter;
+ var5.zCenter = var4.zCenter;
+ var5.dimension = var4.dimension;
+ var5.markDirty();
+ par2World.setItemData("map_" + par1ItemStack.getItemDamage(), var5);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemMapBase.java b/sp-server/src/main/java/net/minecraft/src/ItemMapBase.java
new file mode 100644
index 0000000..96aa888
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemMapBase.java
@@ -0,0 +1,18 @@
+package net.minecraft.src;
+
+public class ItemMapBase extends Item {
+ protected ItemMapBase(int par1) {
+ super(par1);
+ }
+
+ /**
+ * false for all Items except sub-classes of ItemMapBase
+ */
+ public boolean isMap() {
+ return true;
+ }
+
+ public Packet getUpdatePacket(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer) {
+ return null;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemMinecart.java b/sp-server/src/main/java/net/minecraft/src/ItemMinecart.java
new file mode 100644
index 0000000..c3ae29b
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemMinecart.java
@@ -0,0 +1,42 @@
+package net.minecraft.src;
+
+public class ItemMinecart extends Item {
+ private static final IBehaviorDispenseItem dispenserMinecartBehavior = new BehaviorDispenseMinecart();
+ public int minecartType;
+
+ public ItemMinecart(int par1, int par2) {
+ super(par1);
+ this.maxStackSize = 1;
+ this.minecartType = par2;
+ this.setCreativeTab(CreativeTabs.tabTransport);
+ BlockDispenser.dispenseBehaviorRegistry.putObject(this, dispenserMinecartBehavior);
+ }
+
+ /**
+ * Callback for item usage. If the item does something special on right
+ * clicking, he will have one of those. Return True if something happen and
+ * false if it don't. This is for ITEMS, not BLOCKS
+ */
+ public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World par3World, int par4,
+ int par5, int par6, int par7, float par8, float par9, float par10) {
+ int var11 = par3World.getBlockId(par4, par5, par6);
+
+ if (BlockRailBase.isRailBlock(var11)) {
+ if (!par3World.isRemote) {
+ EntityMinecart var12 = EntityMinecart.createMinecart(par3World, (double) ((float) par4 + 0.5F),
+ (double) ((float) par5 + 0.5F), (double) ((float) par6 + 0.5F), this.minecartType);
+
+ if (par1ItemStack.hasDisplayName()) {
+ var12.func_96094_a(par1ItemStack.getDisplayName());
+ }
+
+ par3World.spawnEntityInWorld(var12);
+ }
+
+ --par1ItemStack.stackSize;
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemMonsterPlacer.java b/sp-server/src/main/java/net/minecraft/src/ItemMonsterPlacer.java
new file mode 100644
index 0000000..1103880
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemMonsterPlacer.java
@@ -0,0 +1,86 @@
+package net.minecraft.src;
+
+public class ItemMonsterPlacer extends Item {
+ public ItemMonsterPlacer(int par1) {
+ super(par1);
+ this.setHasSubtypes(true);
+ this.setCreativeTab(CreativeTabs.tabMisc);
+ }
+
+ public String getItemDisplayName(ItemStack par1ItemStack) {
+ String var2 = ("" + StatCollector.translateToLocal(this.getUnlocalizedName() + ".name")).trim();
+ String var3 = EntityList.getStringFromID(par1ItemStack.getItemDamage());
+
+ if (var3 != null) {
+ var2 = var2 + " " + StatCollector.translateToLocal("entity." + var3 + ".name");
+ }
+
+ return var2;
+ }
+
+ /**
+ * Callback for item usage. If the item does something special on right
+ * clicking, he will have one of those. Return True if something happen and
+ * false if it don't. This is for ITEMS, not BLOCKS
+ */
+ public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World par3World, int par4,
+ int par5, int par6, int par7, float par8, float par9, float par10) {
+ if (par3World.isRemote) {
+ return true;
+ } else {
+ int var11 = par3World.getBlockId(par4, par5, par6);
+ par4 += Facing.offsetsXForSide[par7];
+ par5 += Facing.offsetsYForSide[par7];
+ par6 += Facing.offsetsZForSide[par7];
+ double var12 = 0.0D;
+
+ if (par7 == 1 && Block.blocksList[var11] != null && Block.blocksList[var11].getRenderType() == 11) {
+ var12 = 0.5D;
+ }
+
+ Entity var14 = spawnCreature(par3World, par1ItemStack.getItemDamage(), (double) par4 + 0.5D,
+ (double) par5 + var12, (double) par6 + 0.5D);
+
+ if (var14 != null) {
+ if (var14 instanceof EntityLiving && par1ItemStack.hasDisplayName()) {
+ ((EntityLiving) var14).func_94058_c(par1ItemStack.getDisplayName());
+ }
+
+ if (!par2EntityPlayer.capabilities.isCreativeMode) {
+ --par1ItemStack.stackSize;
+ }
+ }
+
+ return true;
+ }
+ }
+
+ /**
+ * Spawns the creature specified by the egg's type in the location specified by
+ * the last three parameters. Parameters: world, entityID, x, y, z.
+ */
+ public static Entity spawnCreature(World par0World, int par1, double par2, double par4, double par6) {
+ if (!EntityList.entityEggs.containsKey(Integer.valueOf(par1))) {
+ return null;
+ } else {
+ Entity var8 = null;
+
+ for (int var9 = 0; var9 < 1; ++var9) {
+ var8 = EntityList.createEntityByID(par1, par0World);
+
+ if (var8 != null && var8 instanceof EntityLiving) {
+ EntityLiving var10 = (EntityLiving) var8;
+ var8.setLocationAndAngles(par2, par4, par6,
+ MathHelper.wrapAngleTo180_float(par0World.rand.nextFloat() * 360.0F), 0.0F);
+ var10.rotationYawHead = var10.rotationYaw;
+ var10.renderYawOffset = var10.rotationYaw;
+ var10.initCreature();
+ par0World.spawnEntityInWorld(var8);
+ var10.playLivingSound();
+ }
+ }
+
+ return var8;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemMultiTextureTile.java b/sp-server/src/main/java/net/minecraft/src/ItemMultiTextureTile.java
new file mode 100644
index 0000000..0f63e4c
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemMultiTextureTile.java
@@ -0,0 +1,35 @@
+package net.minecraft.src;
+
+public class ItemMultiTextureTile extends ItemBlock {
+ private final Block theBlock;
+ private final String[] field_82804_b;
+
+ public ItemMultiTextureTile(int par1, Block par2Block, String[] par3ArrayOfStr) {
+ super(par1);
+ this.theBlock = par2Block;
+ this.field_82804_b = par3ArrayOfStr;
+ this.setMaxDamage(0);
+ this.setHasSubtypes(true);
+ }
+
+ /**
+ * Returns the metadata of the block which this Item (ItemBlock) can place
+ */
+ public int getMetadata(int par1) {
+ return par1;
+ }
+
+ /**
+ * Returns the unlocalized name of this item. This version accepts an ItemStack
+ * so different stacks can have different names based on their damage or NBT.
+ */
+ public String getUnlocalizedName(ItemStack par1ItemStack) {
+ int var2 = par1ItemStack.getItemDamage();
+
+ if (var2 < 0 || var2 >= this.field_82804_b.length) {
+ var2 = 0;
+ }
+
+ return super.getUnlocalizedName() + "." + this.field_82804_b[var2];
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemPickaxe.java b/sp-server/src/main/java/net/minecraft/src/ItemPickaxe.java
new file mode 100644
index 0000000..2f6fdd3
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemPickaxe.java
@@ -0,0 +1,50 @@
+package net.minecraft.src;
+
+public class ItemPickaxe extends ItemTool {
+ /** an array of the blocks this pickaxe is effective against */
+ private static Block[] blocksEffectiveAgainst = new Block[] { Block.cobblestone, Block.stoneDoubleSlab,
+ Block.stoneSingleSlab, Block.stone, Block.sandStone, Block.cobblestoneMossy, Block.oreIron, Block.blockIron,
+ Block.oreCoal, Block.blockGold, Block.oreGold, Block.oreDiamond, Block.blockDiamond, Block.ice,
+ Block.netherrack, Block.oreLapis, Block.blockLapis, Block.oreRedstone, Block.oreRedstoneGlowing, Block.rail,
+ Block.railDetector, Block.railPowered, Block.railActivator };
+
+ protected ItemPickaxe(int par1, EnumToolMaterial par2EnumToolMaterial) {
+ super(par1, 2, par2EnumToolMaterial, blocksEffectiveAgainst);
+ }
+
+ /**
+ * Returns if the item (tool) can harvest results from the block type.
+ */
+ public boolean canHarvestBlock(Block par1Block) {
+ return par1Block == Block.obsidian ? this.toolMaterial.getHarvestLevel() == 3
+ : (par1Block != Block.blockDiamond && par1Block != Block.oreDiamond
+ ? (par1Block != Block.oreEmerald && par1Block != Block.blockEmerald
+ ? (par1Block != Block.blockGold && par1Block != Block.oreGold
+ ? (par1Block != Block.blockIron && par1Block != Block.oreIron
+ ? (par1Block != Block.blockLapis && par1Block != Block.oreLapis
+ ? (par1Block != Block.oreRedstone
+ && par1Block != Block.oreRedstoneGlowing
+ ? (par1Block.blockMaterial == Material.rock
+ ? true
+ : (par1Block.blockMaterial == Material.iron
+ ? true
+ : par1Block.blockMaterial == Material.anvil))
+ : this.toolMaterial.getHarvestLevel() >= 2)
+ : this.toolMaterial.getHarvestLevel() >= 1)
+ : this.toolMaterial.getHarvestLevel() >= 1)
+ : this.toolMaterial.getHarvestLevel() >= 2)
+ : this.toolMaterial.getHarvestLevel() >= 2)
+ : this.toolMaterial.getHarvestLevel() >= 2);
+ }
+
+ /**
+ * Returns the strength of the stack against a given block. 1.0F base,
+ * (Quality+1)*2 if correct blocktype, 1.5F if sword
+ */
+ public float getStrVsBlock(ItemStack par1ItemStack, Block par2Block) {
+ return par2Block != null && (par2Block.blockMaterial == Material.iron
+ || par2Block.blockMaterial == Material.anvil || par2Block.blockMaterial == Material.rock)
+ ? this.efficiencyOnProperMaterial
+ : super.getStrVsBlock(par1ItemStack, par2Block);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemPiston.java b/sp-server/src/main/java/net/minecraft/src/ItemPiston.java
new file mode 100644
index 0000000..90cb239
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemPiston.java
@@ -0,0 +1,14 @@
+package net.minecraft.src;
+
+public class ItemPiston extends ItemBlock {
+ public ItemPiston(int par1) {
+ super(par1);
+ }
+
+ /**
+ * Returns the metadata of the block which this Item (ItemBlock) can place
+ */
+ public int getMetadata(int par1) {
+ return 7;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemPotion.java b/sp-server/src/main/java/net/minecraft/src/ItemPotion.java
new file mode 100644
index 0000000..8b9a7a2
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemPotion.java
@@ -0,0 +1,175 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+public class ItemPotion extends Item {
+ /**
+ * Contains a map from integers to the list of potion effects that potions with
+ * that damage value confer (to prevent recalculating it).
+ */
+ private HashMap effectCache = new HashMap();
+ private static final Map field_77835_b = new LinkedHashMap();
+
+ public ItemPotion(int par1) {
+ super(par1);
+ this.setMaxStackSize(1);
+ this.setHasSubtypes(true);
+ this.setMaxDamage(0);
+ this.setCreativeTab(CreativeTabs.tabBrewing);
+ }
+
+ /**
+ * Returns a list of potion effects for the specified itemstack.
+ */
+ public List getEffects(ItemStack par1ItemStack) {
+ if (par1ItemStack.hasTagCompound() && par1ItemStack.getTagCompound().hasKey("CustomPotionEffects")) {
+ ArrayList var6 = new ArrayList();
+ NBTTagList var3 = par1ItemStack.getTagCompound().getTagList("CustomPotionEffects");
+
+ for (int var4 = 0; var4 < var3.tagCount(); ++var4) {
+ NBTTagCompound var5 = (NBTTagCompound) var3.tagAt(var4);
+ var6.add(PotionEffect.readCustomPotionEffectFromNBT(var5));
+ }
+
+ return var6;
+ } else {
+ List var2 = (List) this.effectCache.get(Integer.valueOf(par1ItemStack.getItemDamage()));
+
+ if (var2 == null) {
+ var2 = PotionHelper.getPotionEffects(par1ItemStack.getItemDamage(), false);
+ this.effectCache.put(Integer.valueOf(par1ItemStack.getItemDamage()), var2);
+ }
+
+ return var2;
+ }
+ }
+
+ /**
+ * Returns a list of effects for the specified potion damage value.
+ */
+ public List getEffects(int par1) {
+ List var2 = (List) this.effectCache.get(Integer.valueOf(par1));
+
+ if (var2 == null) {
+ var2 = PotionHelper.getPotionEffects(par1, false);
+ this.effectCache.put(Integer.valueOf(par1), var2);
+ }
+
+ return var2;
+ }
+
+ public ItemStack onEaten(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer) {
+ if (!par3EntityPlayer.capabilities.isCreativeMode) {
+ --par1ItemStack.stackSize;
+ }
+
+ if (!par2World.isRemote) {
+ List var4 = this.getEffects(par1ItemStack);
+
+ if (var4 != null) {
+ Iterator var5 = var4.iterator();
+
+ while (var5.hasNext()) {
+ PotionEffect var6 = (PotionEffect) var5.next();
+ par3EntityPlayer.addPotionEffect(new PotionEffect(var6));
+ }
+ }
+ }
+
+ if (!par3EntityPlayer.capabilities.isCreativeMode) {
+ if (par1ItemStack.stackSize <= 0) {
+ return new ItemStack(Item.glassBottle);
+ }
+
+ par3EntityPlayer.inventory.addItemStackToInventory(new ItemStack(Item.glassBottle));
+ }
+
+ return par1ItemStack;
+ }
+
+ /**
+ * How long it takes to use or consume an item
+ */
+ public int getMaxItemUseDuration(ItemStack par1ItemStack) {
+ return 32;
+ }
+
+ /**
+ * returns the action that specifies what animation to play when the items is
+ * being used
+ */
+ public EnumAction getItemUseAction(ItemStack par1ItemStack) {
+ return EnumAction.drink;
+ }
+
+ /**
+ * Called whenever this item is equipped and the right mouse button is pressed.
+ * Args: itemStack, world, entityPlayer
+ */
+ public ItemStack onItemRightClick(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer) {
+ if (isSplash(par1ItemStack.getItemDamage())) {
+ if (!par3EntityPlayer.capabilities.isCreativeMode) {
+ --par1ItemStack.stackSize;
+ }
+
+ par2World.playSoundAtEntity(par3EntityPlayer, "random.bow", 0.5F,
+ 0.4F / (itemRand.nextFloat() * 0.4F + 0.8F));
+
+ if (!par2World.isRemote) {
+ par2World.spawnEntityInWorld(new EntityPotion(par2World, par3EntityPlayer, par1ItemStack));
+ }
+
+ return par1ItemStack;
+ } else {
+ par3EntityPlayer.setItemInUse(par1ItemStack, this.getMaxItemUseDuration(par1ItemStack));
+ return par1ItemStack;
+ }
+ }
+
+ /**
+ * Callback for item usage. If the item does something special on right
+ * clicking, he will have one of those. Return True if something happen and
+ * false if it don't. This is for ITEMS, not BLOCKS
+ */
+ public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World par3World, int par4,
+ int par5, int par6, int par7, float par8, float par9, float par10) {
+ return false;
+ }
+
+ /**
+ * returns wether or not a potion is a throwable splash potion based on damage
+ * value
+ */
+ public static boolean isSplash(int par0) {
+ return (par0 & 16384) != 0;
+ }
+
+ public String getItemDisplayName(ItemStack par1ItemStack) {
+ if (par1ItemStack.getItemDamage() == 0) {
+ return StatCollector.translateToLocal("item.emptyPotion.name").trim();
+ } else {
+ String var2 = "";
+
+ if (isSplash(par1ItemStack.getItemDamage())) {
+ var2 = StatCollector.translateToLocal("potion.prefix.grenade").trim() + " ";
+ }
+
+ List var3 = Item.potion.getEffects(par1ItemStack);
+ String var4;
+
+ if (var3 != null && !var3.isEmpty()) {
+ var4 = ((PotionEffect) var3.get(0)).getEffectName();
+ var4 = var4 + ".postfix";
+ return var2 + StatCollector.translateToLocal(var4).trim();
+ } else {
+ var4 = PotionHelper.func_77905_c(par1ItemStack.getItemDamage());
+ return StatCollector.translateToLocal(var4).trim() + " " + super.getItemDisplayName(par1ItemStack);
+ }
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemRecord.java b/sp-server/src/main/java/net/minecraft/src/ItemRecord.java
new file mode 100644
index 0000000..d298b4c
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemRecord.java
@@ -0,0 +1,42 @@
+package net.minecraft.src;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class ItemRecord extends Item {
+ /** List of all record items and their names. */
+ private static final Map records = new HashMap();
+
+ /** The name of the record. */
+ public final String recordName;
+
+ protected ItemRecord(int par1, String par2Str) {
+ super(par1);
+ this.recordName = par2Str;
+ this.maxStackSize = 1;
+ this.setCreativeTab(CreativeTabs.tabMisc);
+ records.put(par2Str, this);
+ }
+
+ /**
+ * Callback for item usage. If the item does something special on right
+ * clicking, he will have one of those. Return True if something happen and
+ * false if it don't. This is for ITEMS, not BLOCKS
+ */
+ public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World par3World, int par4,
+ int par5, int par6, int par7, float par8, float par9, float par10) {
+ if (par3World.getBlockId(par4, par5, par6) == Block.jukebox.blockID
+ && par3World.getBlockMetadata(par4, par5, par6) == 0) {
+ if (par3World.isRemote) {
+ return true;
+ } else {
+ ((BlockJukeBox) Block.jukebox).insertRecord(par3World, par4, par5, par6, par1ItemStack);
+ par3World.playAuxSFXAtEntity((EntityPlayer) null, 1005, par4, par5, par6, this.itemID);
+ --par1ItemStack.stackSize;
+ return true;
+ }
+ } else {
+ return false;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemRedstone.java b/sp-server/src/main/java/net/minecraft/src/ItemRedstone.java
new file mode 100644
index 0000000..7021b00
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemRedstone.java
@@ -0,0 +1,57 @@
+package net.minecraft.src;
+
+public class ItemRedstone extends Item {
+ public ItemRedstone(int par1) {
+ super(par1);
+ this.setCreativeTab(CreativeTabs.tabRedstone);
+ }
+
+ /**
+ * Callback for item usage. If the item does something special on right
+ * clicking, he will have one of those. Return True if something happen and
+ * false if it don't. This is for ITEMS, not BLOCKS
+ */
+ public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World par3World, int par4,
+ int par5, int par6, int par7, float par8, float par9, float par10) {
+ if (par3World.getBlockId(par4, par5, par6) != Block.snow.blockID) {
+ if (par7 == 0) {
+ --par5;
+ }
+
+ if (par7 == 1) {
+ ++par5;
+ }
+
+ if (par7 == 2) {
+ --par6;
+ }
+
+ if (par7 == 3) {
+ ++par6;
+ }
+
+ if (par7 == 4) {
+ --par4;
+ }
+
+ if (par7 == 5) {
+ ++par4;
+ }
+
+ if (!par3World.isAirBlock(par4, par5, par6)) {
+ return false;
+ }
+ }
+
+ if (!par2EntityPlayer.canPlayerEdit(par4, par5, par6, par7, par1ItemStack)) {
+ return false;
+ } else {
+ if (Block.redstoneWire.canPlaceBlockAt(par3World, par4, par5, par6)) {
+ --par1ItemStack.stackSize;
+ par3World.setBlock(par4, par5, par6, Block.redstoneWire.blockID);
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemReed.java b/sp-server/src/main/java/net/minecraft/src/ItemReed.java
new file mode 100644
index 0000000..0480f67
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemReed.java
@@ -0,0 +1,76 @@
+package net.minecraft.src;
+
+public class ItemReed extends Item {
+ /** The ID of the block the reed will spawn when used from inventory bar. */
+ private int spawnID;
+
+ public ItemReed(int par1, Block par2Block) {
+ super(par1);
+ this.spawnID = par2Block.blockID;
+ }
+
+ /**
+ * Callback for item usage. If the item does something special on right
+ * clicking, he will have one of those. Return True if something happen and
+ * false if it don't. This is for ITEMS, not BLOCKS
+ */
+ public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World par3World, int par4,
+ int par5, int par6, int par7, float par8, float par9, float par10) {
+ int var11 = par3World.getBlockId(par4, par5, par6);
+
+ if (var11 == Block.snow.blockID && (par3World.getBlockMetadata(par4, par5, par6) & 7) < 1) {
+ par7 = 1;
+ } else if (var11 != Block.vine.blockID && var11 != Block.tallGrass.blockID && var11 != Block.deadBush.blockID) {
+ if (par7 == 0) {
+ --par5;
+ }
+
+ if (par7 == 1) {
+ ++par5;
+ }
+
+ if (par7 == 2) {
+ --par6;
+ }
+
+ if (par7 == 3) {
+ ++par6;
+ }
+
+ if (par7 == 4) {
+ --par4;
+ }
+
+ if (par7 == 5) {
+ ++par4;
+ }
+ }
+
+ if (!par2EntityPlayer.canPlayerEdit(par4, par5, par6, par7, par1ItemStack)) {
+ return false;
+ } else if (par1ItemStack.stackSize == 0) {
+ return false;
+ } else {
+ if (par3World.canPlaceEntityOnSide(this.spawnID, par4, par5, par6, false, par7, (Entity) null,
+ par1ItemStack)) {
+ Block var12 = Block.blocksList[this.spawnID];
+ int var13 = var12.onBlockPlaced(par3World, par4, par5, par6, par7, par8, par9, par10, 0);
+
+ if (par3World.setBlock(par4, par5, par6, this.spawnID, var13, 3)) {
+ if (par3World.getBlockId(par4, par5, par6) == this.spawnID) {
+ Block.blocksList[this.spawnID].onBlockPlacedBy(par3World, par4, par5, par6, par2EntityPlayer,
+ par1ItemStack);
+ Block.blocksList[this.spawnID].onPostBlockPlaced(par3World, par4, par5, par6, var13);
+ }
+
+ par3World.playSoundEffect((double) ((float) par4 + 0.5F), (double) ((float) par5 + 0.5F),
+ (double) ((float) par6 + 0.5F), var12.stepSound.getPlaceSound(),
+ (var12.stepSound.getVolume() + 1.0F) / 2.0F, var12.stepSound.getPitch() * 0.8F);
+ --par1ItemStack.stackSize;
+ }
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemSaddle.java b/sp-server/src/main/java/net/minecraft/src/ItemSaddle.java
new file mode 100644
index 0000000..f8d1ec9
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemSaddle.java
@@ -0,0 +1,36 @@
+package net.minecraft.src;
+
+public class ItemSaddle extends Item {
+ public ItemSaddle(int par1) {
+ super(par1);
+ this.maxStackSize = 1;
+ this.setCreativeTab(CreativeTabs.tabTransport);
+ }
+
+ /**
+ * Called when a player right clicks an entity with an item.
+ */
+ public boolean useItemOnEntity(ItemStack par1ItemStack, EntityLiving par2EntityLiving) {
+ if (par2EntityLiving instanceof EntityPig) {
+ EntityPig var3 = (EntityPig) par2EntityLiving;
+
+ if (!var3.getSaddled() && !var3.isChild()) {
+ var3.setSaddled(true);
+ --par1ItemStack.stackSize;
+ }
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Current implementations of this method in child classes do not use the entry
+ * argument beside ev. They just raise the damage on the stack.
+ */
+ public boolean hitEntity(ItemStack par1ItemStack, EntityLiving par2EntityLiving, EntityLiving par3EntityLiving) {
+ this.useItemOnEntity(par1ItemStack, par2EntityLiving);
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemSeedFood.java b/sp-server/src/main/java/net/minecraft/src/ItemSeedFood.java
new file mode 100644
index 0000000..98410e0
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemSeedFood.java
@@ -0,0 +1,40 @@
+package net.minecraft.src;
+
+public class ItemSeedFood extends ItemFood {
+ /** Block ID of the crop this seed food should place. */
+ private int cropId;
+
+ /** Block ID of the soil this seed food should be planted on. */
+ private int soilId;
+
+ public ItemSeedFood(int par1, int par2, float par3, int par4, int par5) {
+ super(par1, par2, par3, false);
+ this.cropId = par4;
+ this.soilId = par5;
+ }
+
+ /**
+ * Callback for item usage. If the item does something special on right
+ * clicking, he will have one of those. Return True if something happen and
+ * false if it don't. This is for ITEMS, not BLOCKS
+ */
+ public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World par3World, int par4,
+ int par5, int par6, int par7, float par8, float par9, float par10) {
+ if (par7 != 1) {
+ return false;
+ } else if (par2EntityPlayer.canPlayerEdit(par4, par5, par6, par7, par1ItemStack)
+ && par2EntityPlayer.canPlayerEdit(par4, par5 + 1, par6, par7, par1ItemStack)) {
+ int var11 = par3World.getBlockId(par4, par5, par6);
+
+ if (var11 == this.soilId && par3World.isAirBlock(par4, par5 + 1, par6)) {
+ par3World.setBlock(par4, par5 + 1, par6, this.cropId);
+ --par1ItemStack.stackSize;
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemSeeds.java b/sp-server/src/main/java/net/minecraft/src/ItemSeeds.java
new file mode 100644
index 0000000..3011e3c
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemSeeds.java
@@ -0,0 +1,43 @@
+package net.minecraft.src;
+
+public class ItemSeeds extends Item {
+ /**
+ * The type of block this seed turns into (wheat or pumpkin stems for instance)
+ */
+ private int blockType;
+
+ /** BlockID of the block the seeds can be planted on. */
+ private int soilBlockID;
+
+ public ItemSeeds(int par1, int par2, int par3) {
+ super(par1);
+ this.blockType = par2;
+ this.soilBlockID = par3;
+ this.setCreativeTab(CreativeTabs.tabMaterials);
+ }
+
+ /**
+ * Callback for item usage. If the item does something special on right
+ * clicking, he will have one of those. Return True if something happen and
+ * false if it don't. This is for ITEMS, not BLOCKS
+ */
+ public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World par3World, int par4,
+ int par5, int par6, int par7, float par8, float par9, float par10) {
+ if (par7 != 1) {
+ return false;
+ } else if (par2EntityPlayer.canPlayerEdit(par4, par5, par6, par7, par1ItemStack)
+ && par2EntityPlayer.canPlayerEdit(par4, par5 + 1, par6, par7, par1ItemStack)) {
+ int var11 = par3World.getBlockId(par4, par5, par6);
+
+ if (var11 == this.soilBlockID && par3World.isAirBlock(par4, par5 + 1, par6)) {
+ par3World.setBlock(par4, par5 + 1, par6, this.blockType);
+ --par1ItemStack.stackSize;
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemShears.java b/sp-server/src/main/java/net/minecraft/src/ItemShears.java
new file mode 100644
index 0000000..ef60930
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemShears.java
@@ -0,0 +1,39 @@
+package net.minecraft.src;
+
+public class ItemShears extends Item {
+ public ItemShears(int par1) {
+ super(par1);
+ this.setMaxStackSize(1);
+ this.setMaxDamage(238);
+ this.setCreativeTab(CreativeTabs.tabTools);
+ }
+
+ public boolean onBlockDestroyed(ItemStack par1ItemStack, World par2World, int par3, int par4, int par5, int par6,
+ EntityLiving par7EntityLiving) {
+ if (par3 != Block.leaves.blockID && par3 != Block.web.blockID && par3 != Block.tallGrass.blockID
+ && par3 != Block.vine.blockID && par3 != Block.tripWire.blockID) {
+ return super.onBlockDestroyed(par1ItemStack, par2World, par3, par4, par5, par6, par7EntityLiving);
+ } else {
+ par1ItemStack.damageItem(1, par7EntityLiving);
+ return true;
+ }
+ }
+
+ /**
+ * Returns if the item (tool) can harvest results from the block type.
+ */
+ public boolean canHarvestBlock(Block par1Block) {
+ return par1Block.blockID == Block.web.blockID || par1Block.blockID == Block.redstoneWire.blockID
+ || par1Block.blockID == Block.tripWire.blockID;
+ }
+
+ /**
+ * Returns the strength of the stack against a given block. 1.0F base,
+ * (Quality+1)*2 if correct blocktype, 1.5F if sword
+ */
+ public float getStrVsBlock(ItemStack par1ItemStack, Block par2Block) {
+ return par2Block.blockID != Block.web.blockID && par2Block.blockID != Block.leaves.blockID
+ ? (par2Block.blockID == Block.cloth.blockID ? 5.0F : super.getStrVsBlock(par1ItemStack, par2Block))
+ : 15.0F;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemSign.java b/sp-server/src/main/java/net/minecraft/src/ItemSign.java
new file mode 100644
index 0000000..003835c
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemSign.java
@@ -0,0 +1,66 @@
+package net.minecraft.src;
+
+public class ItemSign extends Item {
+ public ItemSign(int par1) {
+ super(par1);
+ this.maxStackSize = 16;
+ this.setCreativeTab(CreativeTabs.tabDecorations);
+ }
+
+ /**
+ * Callback for item usage. If the item does something special on right
+ * clicking, he will have one of those. Return True if something happen and
+ * false if it don't. This is for ITEMS, not BLOCKS
+ */
+ public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World par3World, int par4,
+ int par5, int par6, int par7, float par8, float par9, float par10) {
+ if (par7 == 0) {
+ return false;
+ } else if (!par3World.getBlockMaterial(par4, par5, par6).isSolid()) {
+ return false;
+ } else {
+ if (par7 == 1) {
+ ++par5;
+ }
+
+ if (par7 == 2) {
+ --par6;
+ }
+
+ if (par7 == 3) {
+ ++par6;
+ }
+
+ if (par7 == 4) {
+ --par4;
+ }
+
+ if (par7 == 5) {
+ ++par4;
+ }
+
+ if (!par2EntityPlayer.canPlayerEdit(par4, par5, par6, par7, par1ItemStack)) {
+ return false;
+ } else if (!Block.signPost.canPlaceBlockAt(par3World, par4, par5, par6)) {
+ return false;
+ } else {
+ if (par7 == 1) {
+ int var11 = MathHelper.floor_double(
+ (double) ((par2EntityPlayer.rotationYaw + 180.0F) * 16.0F / 360.0F) + 0.5D) & 15;
+ par3World.setBlock(par4, par5, par6, Block.signPost.blockID, var11, 2);
+ } else {
+ par3World.setBlock(par4, par5, par6, Block.signWall.blockID, par7, 2);
+ }
+
+ --par1ItemStack.stackSize;
+ TileEntitySign var12 = (TileEntitySign) par3World.getBlockTileEntity(par4, par5, par6);
+
+ if (var12 != null) {
+ par2EntityPlayer.displayGUIEditSign(var12);
+ }
+
+ return true;
+ }
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemSimpleFoiled.java b/sp-server/src/main/java/net/minecraft/src/ItemSimpleFoiled.java
new file mode 100644
index 0000000..7036df0
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemSimpleFoiled.java
@@ -0,0 +1,7 @@
+package net.minecraft.src;
+
+public class ItemSimpleFoiled extends Item {
+ public ItemSimpleFoiled(int par1) {
+ super(par1);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemSkull.java b/sp-server/src/main/java/net/minecraft/src/ItemSkull.java
new file mode 100644
index 0000000..6a8cc4e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemSkull.java
@@ -0,0 +1,108 @@
+package net.minecraft.src;
+
+public class ItemSkull extends Item {
+ private static final String[] skullTypes = new String[] { "skeleton", "wither", "zombie", "char", "creeper" };
+ public static final String[] field_94587_a = new String[] { "skull_skeleton", "skull_wither", "skull_zombie",
+ "skull_char", "skull_creeper" };
+
+ public ItemSkull(int par1) {
+ super(par1);
+ this.setCreativeTab(CreativeTabs.tabDecorations);
+ this.setMaxDamage(0);
+ this.setHasSubtypes(true);
+ }
+
+ /**
+ * Callback for item usage. If the item does something special on right
+ * clicking, he will have one of those. Return True if something happen and
+ * false if it don't. This is for ITEMS, not BLOCKS
+ */
+ public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World par3World, int par4,
+ int par5, int par6, int par7, float par8, float par9, float par10) {
+ if (par7 == 0) {
+ return false;
+ } else if (!par3World.getBlockMaterial(par4, par5, par6).isSolid()) {
+ return false;
+ } else {
+ if (par7 == 1) {
+ ++par5;
+ }
+
+ if (par7 == 2) {
+ --par6;
+ }
+
+ if (par7 == 3) {
+ ++par6;
+ }
+
+ if (par7 == 4) {
+ --par4;
+ }
+
+ if (par7 == 5) {
+ ++par4;
+ }
+
+ if (!par2EntityPlayer.canPlayerEdit(par4, par5, par6, par7, par1ItemStack)) {
+ return false;
+ } else if (!Block.skull.canPlaceBlockAt(par3World, par4, par5, par6)) {
+ return false;
+ } else {
+ par3World.setBlock(par4, par5, par6, Block.skull.blockID, par7, 2);
+ int var11 = 0;
+
+ if (par7 == 1) {
+ var11 = MathHelper.floor_double((double) (par2EntityPlayer.rotationYaw * 16.0F / 360.0F) + 0.5D)
+ & 15;
+ }
+
+ TileEntity var12 = par3World.getBlockTileEntity(par4, par5, par6);
+
+ if (var12 != null && var12 instanceof TileEntitySkull) {
+ String var13 = "";
+
+ if (par1ItemStack.hasTagCompound() && par1ItemStack.getTagCompound().hasKey("SkullOwner")) {
+ var13 = par1ItemStack.getTagCompound().getString("SkullOwner");
+ }
+
+ ((TileEntitySkull) var12).setSkullType(par1ItemStack.getItemDamage(), var13);
+ ((TileEntitySkull) var12).setSkullRotation(var11);
+ ((BlockSkull) Block.skull).makeWither(par3World, par4, par5, par6, (TileEntitySkull) var12);
+ }
+
+ --par1ItemStack.stackSize;
+ return true;
+ }
+ }
+ }
+
+ /**
+ * Returns the metadata of the block which this Item (ItemBlock) can place
+ */
+ public int getMetadata(int par1) {
+ return par1;
+ }
+
+ /**
+ * Returns the unlocalized name of this item. This version accepts an ItemStack
+ * so different stacks can have different names based on their damage or NBT.
+ */
+ public String getUnlocalizedName(ItemStack par1ItemStack) {
+ int var2 = par1ItemStack.getItemDamage();
+
+ if (var2 < 0 || var2 >= skullTypes.length) {
+ var2 = 0;
+ }
+
+ return super.getUnlocalizedName() + "." + skullTypes[var2];
+ }
+
+ public String getItemDisplayName(ItemStack par1ItemStack) {
+ return par1ItemStack.getItemDamage() == 3 && par1ItemStack.hasTagCompound()
+ && par1ItemStack.getTagCompound().hasKey("SkullOwner")
+ ? StatCollector.translateToLocalFormatted("item.skull.player.name",
+ new Object[] { par1ItemStack.getTagCompound().getString("SkullOwner") })
+ : super.getItemDisplayName(par1ItemStack);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemSlab.java b/sp-server/src/main/java/net/minecraft/src/ItemSlab.java
new file mode 100644
index 0000000..2897d2e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemSlab.java
@@ -0,0 +1,123 @@
+package net.minecraft.src;
+
+public class ItemSlab extends ItemBlock {
+ private final boolean isFullBlock;
+
+ /** Instance of BlockHalfSlab. */
+ private final BlockHalfSlab theHalfSlab;
+
+ /** The double-slab block corresponding to this item. */
+ private final BlockHalfSlab doubleSlab;
+
+ public ItemSlab(int par1, BlockHalfSlab par2BlockHalfSlab, BlockHalfSlab par3BlockHalfSlab, boolean par4) {
+ super(par1);
+ this.theHalfSlab = par2BlockHalfSlab;
+ this.doubleSlab = par3BlockHalfSlab;
+ this.isFullBlock = par4;
+ this.setMaxDamage(0);
+ this.setHasSubtypes(true);
+ }
+
+ /**
+ * Returns the metadata of the block which this Item (ItemBlock) can place
+ */
+ public int getMetadata(int par1) {
+ return par1;
+ }
+
+ /**
+ * Returns the unlocalized name of this item. This version accepts an ItemStack
+ * so different stacks can have different names based on their damage or NBT.
+ */
+ public String getUnlocalizedName(ItemStack par1ItemStack) {
+ return this.theHalfSlab.getFullSlabName(par1ItemStack.getItemDamage());
+ }
+
+ /**
+ * Callback for item usage. If the item does something special on right
+ * clicking, he will have one of those. Return True if something happen and
+ * false if it don't. This is for ITEMS, not BLOCKS
+ */
+ public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World par3World, int par4,
+ int par5, int par6, int par7, float par8, float par9, float par10) {
+ if (this.isFullBlock) {
+ return super.onItemUse(par1ItemStack, par2EntityPlayer, par3World, par4, par5, par6, par7, par8, par9,
+ par10);
+ } else if (par1ItemStack.stackSize == 0) {
+ return false;
+ } else if (!par2EntityPlayer.canPlayerEdit(par4, par5, par6, par7, par1ItemStack)) {
+ return false;
+ } else {
+ int var11 = par3World.getBlockId(par4, par5, par6);
+ int var12 = par3World.getBlockMetadata(par4, par5, par6);
+ int var13 = var12 & 7;
+ boolean var14 = (var12 & 8) != 0;
+
+ if ((par7 == 1 && !var14 || par7 == 0 && var14) && var11 == this.theHalfSlab.blockID
+ && var13 == par1ItemStack.getItemDamage()) {
+ if (par3World.checkNoEntityCollision(
+ this.doubleSlab.getCollisionBoundingBoxFromPool(par3World, par4, par5, par6))
+ && par3World.setBlock(par4, par5, par6, this.doubleSlab.blockID, var13, 3)) {
+ par3World.playSoundEffect((double) ((float) par4 + 0.5F), (double) ((float) par5 + 0.5F),
+ (double) ((float) par6 + 0.5F), this.doubleSlab.stepSound.getPlaceSound(),
+ (this.doubleSlab.stepSound.getVolume() + 1.0F) / 2.0F,
+ this.doubleSlab.stepSound.getPitch() * 0.8F);
+ --par1ItemStack.stackSize;
+ }
+
+ return true;
+ } else {
+ return this.func_77888_a(par1ItemStack, par2EntityPlayer, par3World, par4, par5, par6, par7) ? true
+ : super.onItemUse(par1ItemStack, par2EntityPlayer, par3World, par4, par5, par6, par7, par8,
+ par9, par10);
+ }
+ }
+ }
+
+ private boolean func_77888_a(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World par3World, int par4,
+ int par5, int par6, int par7) {
+ if (par7 == 0) {
+ --par5;
+ }
+
+ if (par7 == 1) {
+ ++par5;
+ }
+
+ if (par7 == 2) {
+ --par6;
+ }
+
+ if (par7 == 3) {
+ ++par6;
+ }
+
+ if (par7 == 4) {
+ --par4;
+ }
+
+ if (par7 == 5) {
+ ++par4;
+ }
+
+ int var8 = par3World.getBlockId(par4, par5, par6);
+ int var9 = par3World.getBlockMetadata(par4, par5, par6);
+ int var10 = var9 & 7;
+
+ if (var8 == this.theHalfSlab.blockID && var10 == par1ItemStack.getItemDamage()) {
+ if (par3World.checkNoEntityCollision(
+ this.doubleSlab.getCollisionBoundingBoxFromPool(par3World, par4, par5, par6))
+ && par3World.setBlock(par4, par5, par6, this.doubleSlab.blockID, var10, 3)) {
+ par3World.playSoundEffect((double) ((float) par4 + 0.5F), (double) ((float) par5 + 0.5F),
+ (double) ((float) par6 + 0.5F), this.doubleSlab.stepSound.getPlaceSound(),
+ (this.doubleSlab.stepSound.getVolume() + 1.0F) / 2.0F,
+ this.doubleSlab.stepSound.getPitch() * 0.8F);
+ --par1ItemStack.stackSize;
+ }
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemSnow.java b/sp-server/src/main/java/net/minecraft/src/ItemSnow.java
new file mode 100644
index 0000000..a1b5fc9
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemSnow.java
@@ -0,0 +1,43 @@
+package net.minecraft.src;
+
+public class ItemSnow extends ItemBlockWithMetadata {
+ public ItemSnow(int par1, Block par2Block) {
+ super(par1, par2Block);
+ }
+
+ /**
+ * Callback for item usage. If the item does something special on right
+ * clicking, he will have one of those. Return True if something happen and
+ * false if it don't. This is for ITEMS, not BLOCKS
+ */
+ public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World par3World, int par4,
+ int par5, int par6, int par7, float par8, float par9, float par10) {
+ if (par1ItemStack.stackSize == 0) {
+ return false;
+ } else if (!par2EntityPlayer.canPlayerEdit(par4, par5, par6, par7, par1ItemStack)) {
+ return false;
+ } else {
+ int var11 = par3World.getBlockId(par4, par5, par6);
+
+ if (var11 == Block.snow.blockID) {
+ Block var12 = Block.blocksList[this.getBlockID()];
+ int var13 = par3World.getBlockMetadata(par4, par5, par6);
+ int var14 = var13 & 7;
+
+ if (var14 <= 6
+ && par3World.checkNoEntityCollision(
+ var12.getCollisionBoundingBoxFromPool(par3World, par4, par5, par6))
+ && par3World.setBlockMetadata(par4, par5, par6, var14 + 1 | var13 & -8, 2)) {
+ par3World.playSoundEffect((double) ((float) par4 + 0.5F), (double) ((float) par5 + 0.5F),
+ (double) ((float) par6 + 0.5F), var12.stepSound.getPlaceSound(),
+ (var12.stepSound.getVolume() + 1.0F) / 2.0F, var12.stepSound.getPitch() * 0.8F);
+ --par1ItemStack.stackSize;
+ return true;
+ }
+ }
+
+ return super.onItemUse(par1ItemStack, par2EntityPlayer, par3World, par4, par5, par6, par7, par8, par9,
+ par10);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemSnowball.java b/sp-server/src/main/java/net/minecraft/src/ItemSnowball.java
new file mode 100644
index 0000000..66757b2
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemSnowball.java
@@ -0,0 +1,27 @@
+package net.minecraft.src;
+
+public class ItemSnowball extends Item {
+ public ItemSnowball(int par1) {
+ super(par1);
+ this.maxStackSize = 16;
+ this.setCreativeTab(CreativeTabs.tabMisc);
+ }
+
+ /**
+ * Called whenever this item is equipped and the right mouse button is pressed.
+ * Args: itemStack, world, entityPlayer
+ */
+ public ItemStack onItemRightClick(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer) {
+ if (!par3EntityPlayer.capabilities.isCreativeMode) {
+ --par1ItemStack.stackSize;
+ }
+
+ par2World.playSoundAtEntity(par3EntityPlayer, "random.bow", 0.5F, 0.4F / (itemRand.nextFloat() * 0.4F + 0.8F));
+
+ if (!par2World.isRemote) {
+ par2World.spawnEntityInWorld(new EntitySnowball(par2World, par3EntityPlayer));
+ }
+
+ return par1ItemStack;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemSoup.java b/sp-server/src/main/java/net/minecraft/src/ItemSoup.java
new file mode 100644
index 0000000..60dc9b4
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemSoup.java
@@ -0,0 +1,13 @@
+package net.minecraft.src;
+
+public class ItemSoup extends ItemFood {
+ public ItemSoup(int par1, int par2) {
+ super(par1, par2, false);
+ this.setMaxStackSize(1);
+ }
+
+ public ItemStack onEaten(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer) {
+ super.onEaten(par1ItemStack, par2World, par3EntityPlayer);
+ return new ItemStack(Item.bowlEmpty);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemSpade.java b/sp-server/src/main/java/net/minecraft/src/ItemSpade.java
new file mode 100644
index 0000000..2eb0067
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemSpade.java
@@ -0,0 +1,18 @@
+package net.minecraft.src;
+
+public class ItemSpade extends ItemTool {
+ /** an array of the blocks this spade is effective against */
+ private static Block[] blocksEffectiveAgainst = new Block[] { Block.grass, Block.dirt, Block.sand, Block.gravel,
+ Block.snow, Block.blockSnow, Block.blockClay, Block.tilledField, Block.slowSand, Block.mycelium };
+
+ public ItemSpade(int par1, EnumToolMaterial par2EnumToolMaterial) {
+ super(par1, 1, par2EnumToolMaterial, blocksEffectiveAgainst);
+ }
+
+ /**
+ * Returns if the item (tool) can harvest results from the block type.
+ */
+ public boolean canHarvestBlock(Block par1Block) {
+ return par1Block == Block.snow ? true : par1Block == Block.blockSnow;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemStack.java b/sp-server/src/main/java/net/minecraft/src/ItemStack.java
new file mode 100644
index 0000000..3b08804
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemStack.java
@@ -0,0 +1,574 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public final class ItemStack {
+ /** Size of the stack. */
+ public int stackSize;
+
+ /**
+ * Number of animation frames to go when receiving an item (by walking into it,
+ * for example).
+ */
+ public int animationsToGo;
+
+ /** ID of the item. */
+ public int itemID;
+
+ /**
+ * A NBTTagMap containing data about an ItemStack. Can only be used for non
+ * stackable items
+ */
+ public NBTTagCompound stackTagCompound;
+
+ /** Damage dealt to the item or number of use. Raise when using items. */
+ private int itemDamage;
+
+ /** Item frame this stack is on, or null if not on an item frame. */
+ private EntityItemFrame itemFrame;
+
+ public ItemStack(Block par1Block) {
+ this(par1Block, 1);
+ }
+
+ public ItemStack(Block par1Block, int par2) {
+ this(par1Block.blockID, par2, 0);
+ }
+
+ public ItemStack(Block par1Block, int par2, int par3) {
+ this(par1Block.blockID, par2, par3);
+ }
+
+ public ItemStack(Item par1Item) {
+ this(par1Item.itemID, 1, 0);
+ }
+
+ public ItemStack(Item par1Item, int par2) {
+ this(par1Item.itemID, par2, 0);
+ }
+
+ public ItemStack(Item par1Item, int par2, int par3) {
+ this(par1Item.itemID, par2, par3);
+ }
+
+ public ItemStack(int par1, int par2, int par3) {
+ this.stackSize = 0;
+ this.itemFrame = null;
+ this.itemID = par1;
+ this.stackSize = par2;
+ this.itemDamage = par3;
+
+ if (this.itemDamage < 0) {
+ this.itemDamage = 0;
+ }
+ }
+
+ public static ItemStack loadItemStackFromNBT(NBTTagCompound par0NBTTagCompound) {
+ ItemStack var1 = new ItemStack();
+ var1.readFromNBT(par0NBTTagCompound);
+ return var1.getItem() != null ? var1 : null;
+ }
+
+ private ItemStack() {
+ this.stackSize = 0;
+ this.itemFrame = null;
+ }
+
+ /**
+ * Remove the argument from the stack size. Return a new stack object with
+ * argument size.
+ */
+ public ItemStack splitStack(int par1) {
+ ItemStack var2 = new ItemStack(this.itemID, par1, this.itemDamage);
+
+ if (this.stackTagCompound != null) {
+ var2.stackTagCompound = (NBTTagCompound) this.stackTagCompound.copy();
+ }
+
+ this.stackSize -= par1;
+ return var2;
+ }
+
+ /**
+ * Returns the object corresponding to the stack.
+ */
+ public Item getItem() {
+ return Item.itemsList[this.itemID];
+ }
+
+ public boolean tryPlaceItemIntoWorld(EntityPlayer par1EntityPlayer, World par2World, int par3, int par4, int par5,
+ int par6, float par7, float par8, float par9) {
+ boolean var10 = this.getItem().onItemUse(this, par1EntityPlayer, par2World, par3, par4, par5, par6, par7, par8,
+ par9);
+
+ if (var10) {
+ par1EntityPlayer.addStat(StatList.objectUseStats[this.itemID], 1);
+ }
+
+ return var10;
+ }
+
+ /**
+ * Returns the strength of the stack against a given block.
+ */
+ public float getStrVsBlock(Block par1Block) {
+ return this.getItem().getStrVsBlock(this, par1Block);
+ }
+
+ /**
+ * Called whenever this item stack is equipped and right clicked. Returns the
+ * new item stack to put in the position where this item is. Args: world, player
+ */
+ public ItemStack useItemRightClick(World par1World, EntityPlayer par2EntityPlayer) {
+ return this.getItem().onItemRightClick(this, par1World, par2EntityPlayer);
+ }
+
+ public ItemStack onFoodEaten(World par1World, EntityPlayer par2EntityPlayer) {
+ return this.getItem().onEaten(this, par1World, par2EntityPlayer);
+ }
+
+ /**
+ * Write the stack fields to a NBT object. Return the new NBT object.
+ */
+ public NBTTagCompound writeToNBT(NBTTagCompound par1NBTTagCompound) {
+ par1NBTTagCompound.setShort("id", (short) this.itemID);
+ par1NBTTagCompound.setByte("Count", (byte) this.stackSize);
+ par1NBTTagCompound.setShort("Damage", (short) this.itemDamage);
+
+ if (this.stackTagCompound != null) {
+ par1NBTTagCompound.setTag("tag", this.stackTagCompound);
+ }
+
+ return par1NBTTagCompound;
+ }
+
+ /**
+ * Read the stack fields from a NBT object.
+ */
+ public void readFromNBT(NBTTagCompound par1NBTTagCompound) {
+ this.itemID = par1NBTTagCompound.getShort("id");
+ this.stackSize = par1NBTTagCompound.getByte("Count");
+ this.itemDamage = par1NBTTagCompound.getShort("Damage");
+
+ if (this.itemDamage < 0) {
+ this.itemDamage = 0;
+ }
+
+ if (par1NBTTagCompound.hasKey("tag")) {
+ this.stackTagCompound = par1NBTTagCompound.getCompoundTag("tag");
+ }
+ }
+
+ /**
+ * Returns maximum size of the stack.
+ */
+ public int getMaxStackSize() {
+ return this.getItem().getItemStackLimit();
+ }
+
+ /**
+ * Returns true if the ItemStack can hold 2 or more units of the item.
+ */
+ public boolean isStackable() {
+ return this.getMaxStackSize() > 1 && (!this.isItemStackDamageable() || !this.isItemDamaged());
+ }
+
+ /**
+ * true if this itemStack is damageable
+ */
+ public boolean isItemStackDamageable() {
+ return Item.itemsList[this.itemID].getMaxDamage() > 0;
+ }
+
+ public boolean getHasSubtypes() {
+ return Item.itemsList[this.itemID].getHasSubtypes();
+ }
+
+ /**
+ * returns true when a damageable item is damaged
+ */
+ public boolean isItemDamaged() {
+ return this.isItemStackDamageable() && this.itemDamage > 0;
+ }
+
+ /**
+ * gets the damage of an itemstack, for displaying purposes
+ */
+ public int getItemDamageForDisplay() {
+ return this.itemDamage;
+ }
+
+ /**
+ * gets the damage of an itemstack
+ */
+ public int getItemDamage() {
+ return this.itemDamage;
+ }
+
+ /**
+ * Sets the item damage of the ItemStack.
+ */
+ public void setItemDamage(int par1) {
+ this.itemDamage = par1;
+
+ if (this.itemDamage < 0) {
+ this.itemDamage = 0;
+ }
+ }
+
+ /**
+ * Returns the max damage an item in the stack can take.
+ */
+ public int getMaxDamage() {
+ return Item.itemsList[this.itemID].getMaxDamage();
+ }
+
+ public boolean func_96631_a(int par1, EaglercraftRandom par2Random) {
+ if (!this.isItemStackDamageable()) {
+ return false;
+ } else {
+ if (par1 > 0) {
+ int var3 = EnchantmentHelper.getEnchantmentLevel(Enchantment.unbreaking.effectId, this);
+ int var4 = 0;
+
+ for (int var5 = 0; var3 > 0 && var5 < par1; ++var5) {
+ if (EnchantmentDurability.func_92097_a(this, var3, par2Random)) {
+ ++var4;
+ }
+ }
+
+ par1 -= var4;
+
+ if (par1 <= 0) {
+ return false;
+ }
+ }
+
+ this.itemDamage += par1;
+ return this.itemDamage > this.getMaxDamage();
+ }
+ }
+
+ /**
+ * Damages the item in the ItemStack
+ */
+ public void damageItem(int par1, EntityLiving par2EntityLiving) {
+ if (!(par2EntityLiving instanceof EntityPlayer)
+ || !((EntityPlayer) par2EntityLiving).capabilities.isCreativeMode) {
+ if (this.isItemStackDamageable()) {
+ if (this.func_96631_a(par1, par2EntityLiving.getRNG())) {
+ par2EntityLiving.renderBrokenItemStack(this);
+
+ if (par2EntityLiving instanceof EntityPlayer) {
+ ((EntityPlayer) par2EntityLiving).addStat(StatList.objectBreakStats[this.itemID], 1);
+ }
+
+ --this.stackSize;
+
+ if (this.stackSize < 0) {
+ this.stackSize = 0;
+ }
+
+ this.itemDamage = 0;
+ }
+ }
+ }
+ }
+
+ /**
+ * Calls the corresponding fct in di
+ */
+ public void hitEntity(EntityLiving par1EntityLiving, EntityPlayer par2EntityPlayer) {
+ boolean var3 = Item.itemsList[this.itemID].hitEntity(this, par1EntityLiving, par2EntityPlayer);
+
+ if (var3) {
+ par2EntityPlayer.addStat(StatList.objectUseStats[this.itemID], 1);
+ }
+ }
+
+ public void onBlockDestroyed(World par1World, int par2, int par3, int par4, int par5,
+ EntityPlayer par6EntityPlayer) {
+ boolean var7 = Item.itemsList[this.itemID].onBlockDestroyed(this, par1World, par2, par3, par4, par5,
+ par6EntityPlayer);
+
+ if (var7) {
+ par6EntityPlayer.addStat(StatList.objectUseStats[this.itemID], 1);
+ }
+ }
+
+ /**
+ * Returns the damage against a given entity.
+ */
+ public int getDamageVsEntity(Entity par1Entity) {
+ return Item.itemsList[this.itemID].getDamageVsEntity(par1Entity);
+ }
+
+ /**
+ * Checks if the itemStack object can harvest a specified block
+ */
+ public boolean canHarvestBlock(Block par1Block) {
+ return Item.itemsList[this.itemID].canHarvestBlock(par1Block);
+ }
+
+ public boolean interactWith(EntityLiving par1EntityLiving) {
+ return Item.itemsList[this.itemID].useItemOnEntity(this, par1EntityLiving);
+ }
+
+ /**
+ * Returns a new stack with the same properties.
+ */
+ public ItemStack copy() {
+ ItemStack var1 = new ItemStack(this.itemID, this.stackSize, this.itemDamage);
+
+ if (this.stackTagCompound != null) {
+ var1.stackTagCompound = (NBTTagCompound) this.stackTagCompound.copy();
+ }
+
+ return var1;
+ }
+
+ public static boolean areItemStackTagsEqual(ItemStack par0ItemStack, ItemStack par1ItemStack) {
+ return par0ItemStack == null
+ && par1ItemStack == null
+ ? true
+ : (par0ItemStack != null && par1ItemStack != null
+ ? (par0ItemStack.stackTagCompound == null && par1ItemStack.stackTagCompound != null
+ ? false
+ : par0ItemStack.stackTagCompound == null || par0ItemStack.stackTagCompound
+ .equals(par1ItemStack.stackTagCompound))
+ : false);
+ }
+
+ /**
+ * compares ItemStack argument1 with ItemStack argument2; returns true if both
+ * ItemStacks are equal
+ */
+ public static boolean areItemStacksEqual(ItemStack par0ItemStack, ItemStack par1ItemStack) {
+ return par0ItemStack == null && par1ItemStack == null ? true
+ : (par0ItemStack != null && par1ItemStack != null ? par0ItemStack.isItemStackEqual(par1ItemStack)
+ : false);
+ }
+
+ /**
+ * compares ItemStack argument to the instance ItemStack; returns true if both
+ * ItemStacks are equal
+ */
+ private boolean isItemStackEqual(ItemStack par1ItemStack) {
+ return this.stackSize != par1ItemStack.stackSize ? false
+ : (this.itemID != par1ItemStack.itemID ? false
+ : (this.itemDamage != par1ItemStack.itemDamage ? false
+ : (this.stackTagCompound == null && par1ItemStack.stackTagCompound != null ? false
+ : this.stackTagCompound == null
+ || this.stackTagCompound.equals(par1ItemStack.stackTagCompound))));
+ }
+
+ /**
+ * compares ItemStack argument to the instance ItemStack; returns true if the
+ * Items contained in both ItemStacks are equal
+ */
+ public boolean isItemEqual(ItemStack par1ItemStack) {
+ return this.itemID == par1ItemStack.itemID && this.itemDamage == par1ItemStack.itemDamage;
+ }
+
+ public String getItemName() {
+ return Item.itemsList[this.itemID].getUnlocalizedName(this);
+ }
+
+ /**
+ * Creates a copy of a ItemStack, a null parameters will return a null.
+ */
+ public static ItemStack copyItemStack(ItemStack par0ItemStack) {
+ return par0ItemStack == null ? null : par0ItemStack.copy();
+ }
+
+ public String toString() {
+ return this.stackSize + "x" + Item.itemsList[this.itemID].getUnlocalizedName() + "@" + this.itemDamage;
+ }
+
+ /**
+ * Called each tick as long the ItemStack in on player inventory. Used to
+ * progress the pickup animation and update maps.
+ */
+ public void updateAnimation(World par1World, Entity par2Entity, int par3, boolean par4) {
+ if (this.animationsToGo > 0) {
+ --this.animationsToGo;
+ }
+
+ Item.itemsList[this.itemID].onUpdate(this, par1World, par2Entity, par3, par4);
+ }
+
+ public void onCrafting(World par1World, EntityPlayer par2EntityPlayer, int par3) {
+ par2EntityPlayer.addStat(StatList.objectCraftStats[this.itemID], par3);
+ Item.itemsList[this.itemID].onCreated(this, par1World, par2EntityPlayer);
+ }
+
+ public int getMaxItemUseDuration() {
+ return this.getItem().getMaxItemUseDuration(this);
+ }
+
+ public EnumAction getItemUseAction() {
+ return this.getItem().getItemUseAction(this);
+ }
+
+ /**
+ * Called when the player releases the use item button. Args: world,
+ * entityplayer, itemInUseCount
+ */
+ public void onPlayerStoppedUsing(World par1World, EntityPlayer par2EntityPlayer, int par3) {
+ this.getItem().onPlayerStoppedUsing(this, par1World, par2EntityPlayer, par3);
+ }
+
+ /**
+ * Returns true if the ItemStack has an NBTTagCompound. Currently used to store
+ * enchantments.
+ */
+ public boolean hasTagCompound() {
+ return this.stackTagCompound != null;
+ }
+
+ /**
+ * Returns the NBTTagCompound of the ItemStack.
+ */
+ public NBTTagCompound getTagCompound() {
+ return this.stackTagCompound;
+ }
+
+ public NBTTagList getEnchantmentTagList() {
+ return this.stackTagCompound == null ? null : (NBTTagList) this.stackTagCompound.getTag("ench");
+ }
+
+ /**
+ * Assigns a NBTTagCompound to the ItemStack, minecraft validates that only
+ * non-stackable items can have it.
+ */
+ public void setTagCompound(NBTTagCompound par1NBTTagCompound) {
+ this.stackTagCompound = par1NBTTagCompound;
+ }
+
+ /**
+ * returns the display name of the itemstack
+ */
+ public String getDisplayName() {
+ String var1 = this.getItem().getItemDisplayName(this);
+
+ if (this.stackTagCompound != null && this.stackTagCompound.hasKey("display")) {
+ NBTTagCompound var2 = this.stackTagCompound.getCompoundTag("display");
+
+ if (var2.hasKey("Name")) {
+ var1 = var2.getString("Name");
+ }
+ }
+
+ return var1;
+ }
+
+ /**
+ * Sets the item's name (used by anvil to rename the items).
+ */
+ public void setItemName(String par1Str) {
+ if (this.stackTagCompound == null) {
+ this.stackTagCompound = new NBTTagCompound("tag");
+ }
+
+ if (!this.stackTagCompound.hasKey("display")) {
+ this.stackTagCompound.setCompoundTag("display", new NBTTagCompound());
+ }
+
+ this.stackTagCompound.getCompoundTag("display").setString("Name", par1Str);
+ }
+
+ /**
+ * Returns true if the itemstack has a display name
+ */
+ public boolean hasDisplayName() {
+ return this.stackTagCompound == null ? false
+ : (!this.stackTagCompound.hasKey("display") ? false
+ : this.stackTagCompound.getCompoundTag("display").hasKey("Name"));
+ }
+
+ /**
+ * True if it is a tool and has no enchantments to begin with
+ */
+ public boolean isItemEnchantable() {
+ return !this.getItem().isItemTool(this) ? false : !this.isItemEnchanted();
+ }
+
+ /**
+ * Adds an enchantment with a desired level on the ItemStack.
+ */
+ public void addEnchantment(Enchantment par1Enchantment, int par2) {
+ if (this.stackTagCompound == null) {
+ this.setTagCompound(new NBTTagCompound());
+ }
+
+ if (!this.stackTagCompound.hasKey("ench")) {
+ this.stackTagCompound.setTag("ench", new NBTTagList("ench"));
+ }
+
+ NBTTagList var3 = (NBTTagList) this.stackTagCompound.getTag("ench");
+ NBTTagCompound var4 = new NBTTagCompound();
+ var4.setShort("id", (short) par1Enchantment.effectId);
+ var4.setShort("lvl", (short) ((byte) par2));
+ var3.appendTag(var4);
+ }
+
+ /**
+ * True if the item has enchantment data
+ */
+ public boolean isItemEnchanted() {
+ return this.stackTagCompound != null && this.stackTagCompound.hasKey("ench");
+ }
+
+ public void setTagInfo(String par1Str, NBTBase par2NBTBase) {
+ if (this.stackTagCompound == null) {
+ this.setTagCompound(new NBTTagCompound());
+ }
+
+ this.stackTagCompound.setTag(par1Str, par2NBTBase);
+ }
+
+ public boolean func_82835_x() {
+ return this.getItem().func_82788_x();
+ }
+
+ /**
+ * Return whether this stack is on an item frame.
+ */
+ public boolean isOnItemFrame() {
+ return this.itemFrame != null;
+ }
+
+ /**
+ * Set the item frame this stack is on.
+ */
+ public void setItemFrame(EntityItemFrame par1EntityItemFrame) {
+ this.itemFrame = par1EntityItemFrame;
+ }
+
+ /**
+ * Return the item frame this stack is on. Returns null if not on an item frame.
+ */
+ public EntityItemFrame getItemFrame() {
+ return this.itemFrame;
+ }
+
+ /**
+ * Get this stack's repair cost, or 0 if no repair cost is defined.
+ */
+ public int getRepairCost() {
+ return this.hasTagCompound() && this.stackTagCompound.hasKey("RepairCost")
+ ? this.stackTagCompound.getInteger("RepairCost")
+ : 0;
+ }
+
+ /**
+ * Set this stack's repair cost.
+ */
+ public void setRepairCost(int par1) {
+ if (!this.hasTagCompound()) {
+ this.stackTagCompound = new NBTTagCompound("tag");
+ }
+
+ this.stackTagCompound.setInteger("RepairCost", par1);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemSword.java b/sp-server/src/main/java/net/minecraft/src/ItemSword.java
new file mode 100644
index 0000000..af983ae
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemSword.java
@@ -0,0 +1,112 @@
+package net.minecraft.src;
+
+public class ItemSword extends Item {
+ private int weaponDamage;
+ private final EnumToolMaterial toolMaterial;
+
+ public ItemSword(int par1, EnumToolMaterial par2EnumToolMaterial) {
+ super(par1);
+ this.toolMaterial = par2EnumToolMaterial;
+ this.maxStackSize = 1;
+ this.setMaxDamage(par2EnumToolMaterial.getMaxUses());
+ this.setCreativeTab(CreativeTabs.tabCombat);
+ this.weaponDamage = 4 + par2EnumToolMaterial.getDamageVsEntity();
+ }
+
+ public int func_82803_g() {
+ return this.toolMaterial.getDamageVsEntity();
+ }
+
+ /**
+ * Returns the strength of the stack against a given block. 1.0F base,
+ * (Quality+1)*2 if correct blocktype, 1.5F if sword
+ */
+ public float getStrVsBlock(ItemStack par1ItemStack, Block par2Block) {
+ if (par2Block.blockID == Block.web.blockID) {
+ return 15.0F;
+ } else {
+ Material var3 = par2Block.blockMaterial;
+ return var3 != Material.plants && var3 != Material.vine && var3 != Material.coral && var3 != Material.leaves
+ && var3 != Material.pumpkin ? 1.0F : 1.5F;
+ }
+ }
+
+ /**
+ * Current implementations of this method in child classes do not use the entry
+ * argument beside ev. They just raise the damage on the stack.
+ */
+ public boolean hitEntity(ItemStack par1ItemStack, EntityLiving par2EntityLiving, EntityLiving par3EntityLiving) {
+ par1ItemStack.damageItem(1, par3EntityLiving);
+ return true;
+ }
+
+ public boolean onBlockDestroyed(ItemStack par1ItemStack, World par2World, int par3, int par4, int par5, int par6,
+ EntityLiving par7EntityLiving) {
+ if ((double) Block.blocksList[par3].getBlockHardness(par2World, par4, par5, par6) != 0.0D) {
+ par1ItemStack.damageItem(2, par7EntityLiving);
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns the damage against a given entity.
+ */
+ public int getDamageVsEntity(Entity par1Entity) {
+ return this.weaponDamage;
+ }
+
+ /**
+ * returns the action that specifies what animation to play when the items is
+ * being used
+ */
+ public EnumAction getItemUseAction(ItemStack par1ItemStack) {
+ return EnumAction.block;
+ }
+
+ /**
+ * How long it takes to use or consume an item
+ */
+ public int getMaxItemUseDuration(ItemStack par1ItemStack) {
+ return 72000;
+ }
+
+ /**
+ * Called whenever this item is equipped and the right mouse button is pressed.
+ * Args: itemStack, world, entityPlayer
+ */
+ public ItemStack onItemRightClick(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer) {
+ par3EntityPlayer.setItemInUse(par1ItemStack, this.getMaxItemUseDuration(par1ItemStack));
+ return par1ItemStack;
+ }
+
+ /**
+ * Returns if the item (tool) can harvest results from the block type.
+ */
+ public boolean canHarvestBlock(Block par1Block) {
+ return par1Block.blockID == Block.web.blockID;
+ }
+
+ /**
+ * Return the enchantability factor of the item, most of the time is based on
+ * material.
+ */
+ public int getItemEnchantability() {
+ return this.toolMaterial.getEnchantability();
+ }
+
+ /**
+ * Return the name for this tool's material.
+ */
+ public String getToolMaterialName() {
+ return this.toolMaterial.toString();
+ }
+
+ /**
+ * Return whether this item is repairable in an anvil.
+ */
+ public boolean getIsRepairable(ItemStack par1ItemStack, ItemStack par2ItemStack) {
+ return this.toolMaterial.getToolCraftingMaterial() == par2ItemStack.itemID ? true
+ : super.getIsRepairable(par1ItemStack, par2ItemStack);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemTool.java b/sp-server/src/main/java/net/minecraft/src/ItemTool.java
new file mode 100644
index 0000000..c9276e4
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemTool.java
@@ -0,0 +1,86 @@
+package net.minecraft.src;
+
+public class ItemTool extends Item {
+ /** Array of blocks the tool has extra effect against. */
+ private Block[] blocksEffectiveAgainst;
+ protected float efficiencyOnProperMaterial = 4.0F;
+
+ /** Damage versus entities. */
+ private int damageVsEntity;
+
+ /** The material this tool is made from. */
+ protected EnumToolMaterial toolMaterial;
+
+ protected ItemTool(int par1, int par2, EnumToolMaterial par3EnumToolMaterial, Block[] par4ArrayOfBlock) {
+ super(par1);
+ this.toolMaterial = par3EnumToolMaterial;
+ this.blocksEffectiveAgainst = par4ArrayOfBlock;
+ this.maxStackSize = 1;
+ this.setMaxDamage(par3EnumToolMaterial.getMaxUses());
+ this.efficiencyOnProperMaterial = par3EnumToolMaterial.getEfficiencyOnProperMaterial();
+ this.damageVsEntity = par2 + par3EnumToolMaterial.getDamageVsEntity();
+ this.setCreativeTab(CreativeTabs.tabTools);
+ }
+
+ /**
+ * Returns the strength of the stack against a given block. 1.0F base,
+ * (Quality+1)*2 if correct blocktype, 1.5F if sword
+ */
+ public float getStrVsBlock(ItemStack par1ItemStack, Block par2Block) {
+ for (int var3 = 0; var3 < this.blocksEffectiveAgainst.length; ++var3) {
+ if (this.blocksEffectiveAgainst[var3] == par2Block) {
+ return this.efficiencyOnProperMaterial;
+ }
+ }
+
+ return 1.0F;
+ }
+
+ /**
+ * Current implementations of this method in child classes do not use the entry
+ * argument beside ev. They just raise the damage on the stack.
+ */
+ public boolean hitEntity(ItemStack par1ItemStack, EntityLiving par2EntityLiving, EntityLiving par3EntityLiving) {
+ par1ItemStack.damageItem(2, par3EntityLiving);
+ return true;
+ }
+
+ public boolean onBlockDestroyed(ItemStack par1ItemStack, World par2World, int par3, int par4, int par5, int par6,
+ EntityLiving par7EntityLiving) {
+ if ((double) Block.blocksList[par3].getBlockHardness(par2World, par4, par5, par6) != 0.0D) {
+ par1ItemStack.damageItem(1, par7EntityLiving);
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns the damage against a given entity.
+ */
+ public int getDamageVsEntity(Entity par1Entity) {
+ return this.damageVsEntity;
+ }
+
+ /**
+ * Return the enchantability factor of the item, most of the time is based on
+ * material.
+ */
+ public int getItemEnchantability() {
+ return this.toolMaterial.getEnchantability();
+ }
+
+ /**
+ * Return the name for this tool's material.
+ */
+ public String getToolMaterialName() {
+ return this.toolMaterial.toString();
+ }
+
+ /**
+ * Return whether this item is repairable in an anvil.
+ */
+ public boolean getIsRepairable(ItemStack par1ItemStack, ItemStack par2ItemStack) {
+ return this.toolMaterial.getToolCraftingMaterial() == par2ItemStack.itemID ? true
+ : super.getIsRepairable(par1ItemStack, par2ItemStack);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ItemWritableBook.java b/sp-server/src/main/java/net/minecraft/src/ItemWritableBook.java
new file mode 100644
index 0000000..6380cc8
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ItemWritableBook.java
@@ -0,0 +1,49 @@
+package net.minecraft.src;
+
+public class ItemWritableBook extends Item {
+ public ItemWritableBook(int par1) {
+ super(par1);
+ this.setMaxStackSize(1);
+ }
+
+ /**
+ * Called whenever this item is equipped and the right mouse button is pressed.
+ * Args: itemStack, world, entityPlayer
+ */
+ public ItemStack onItemRightClick(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer) {
+ par3EntityPlayer.displayGUIBook(par1ItemStack);
+ return par1ItemStack;
+ }
+
+ /**
+ * If this function returns true (or the item is damageable), the ItemStack's
+ * NBT tag will be sent to the client.
+ */
+ public boolean getShareTag() {
+ return true;
+ }
+
+ public static boolean validBookTagPages(NBTTagCompound par0NBTTagCompound) {
+ if (par0NBTTagCompound == null) {
+ return false;
+ } else if (!par0NBTTagCompound.hasKey("pages")) {
+ return false;
+ } else {
+ NBTTagList var1 = (NBTTagList) par0NBTTagCompound.getTag("pages");
+
+ for (int var2 = 0; var2 < var1.tagCount(); ++var2) {
+ NBTTagString var3 = (NBTTagString) var1.tagAt(var2);
+
+ if (var3.data == null) {
+ return false;
+ }
+
+ if (var3.data.length() > 256) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/LogAgent.java b/sp-server/src/main/java/net/minecraft/src/LogAgent.java
new file mode 100644
index 0000000..5073fe1
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/LogAgent.java
@@ -0,0 +1,81 @@
+package net.minecraft.src;
+
+import java.util.logging.ConsoleHandler;
+import java.util.logging.FileHandler;
+import java.util.logging.Handler;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class LogAgent implements ILogAgent {
+ private final Logger serverLogger;
+ private final String logFile;
+ private final String loggerName;
+ private final String loggerPrefix;
+
+ public LogAgent(String par1Str, String par2Str, String par3Str) {
+ this.serverLogger = Logger.getLogger(par1Str);
+ this.loggerName = par1Str;
+ this.loggerPrefix = par2Str;
+ this.logFile = par3Str;
+ this.setupLogger();
+ }
+
+ /**
+ * Sets up the logger for usage.
+ */
+ private void setupLogger() {
+ this.serverLogger.setUseParentHandlers(false);
+ Handler[] var1 = this.serverLogger.getHandlers();
+ int var2 = var1.length;
+
+ for (int var3 = 0; var3 < var2; ++var3) {
+ Handler var4 = var1[var3];
+ this.serverLogger.removeHandler(var4);
+ }
+
+ LogFormatter var6 = new LogFormatter(this, (LogAgentINNER1) null);
+ ConsoleHandler var7 = new ConsoleHandler();
+ var7.setFormatter(var6);
+ this.serverLogger.addHandler(var7);
+
+ try {
+ FileHandler var8 = new FileHandler(this.logFile, true);
+ var8.setFormatter(var6);
+ this.serverLogger.addHandler(var8);
+ } catch (Exception var5) {
+ this.serverLogger.log(Level.WARNING, "Failed to log " + this.loggerName + " to " + this.logFile, var5);
+ }
+ }
+
+ public Logger getServerLogger() {
+ return this.serverLogger;
+ }
+
+ public void func_98233_a(String par1Str) {
+ this.serverLogger.log(Level.INFO, par1Str);
+ }
+
+ public void func_98236_b(String par1Str) {
+ this.serverLogger.log(Level.WARNING, par1Str);
+ }
+
+ public void logWarningFormatted(String par1Str, Object... par2ArrayOfObj) {
+ this.serverLogger.log(Level.WARNING, par1Str, par2ArrayOfObj);
+ }
+
+ public void logWarningException(String par1Str, Throwable par2Throwable) {
+ this.serverLogger.log(Level.WARNING, par1Str, par2Throwable);
+ }
+
+ public void logSevere(String par1Str) {
+ this.serverLogger.log(Level.SEVERE, par1Str);
+ }
+
+ public void logSevereException(String par1Str, Throwable par2Throwable) {
+ this.serverLogger.log(Level.SEVERE, par1Str, par2Throwable);
+ }
+
+ static String func_98237_a(LogAgent par0LogAgent) {
+ return par0LogAgent.loggerPrefix;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/LogAgentINNER1.java b/sp-server/src/main/java/net/minecraft/src/LogAgentINNER1.java
new file mode 100644
index 0000000..9e23536
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/LogAgentINNER1.java
@@ -0,0 +1,4 @@
+package net.minecraft.src;
+
+class LogAgentINNER1 {
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/LogFormatter.java b/sp-server/src/main/java/net/minecraft/src/LogFormatter.java
new file mode 100644
index 0000000..daeeb5a
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/LogFormatter.java
@@ -0,0 +1,44 @@
+package net.minecraft.src;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.text.SimpleDateFormat;
+import java.util.logging.Formatter;
+import java.util.logging.LogRecord;
+
+class LogFormatter extends Formatter {
+ private SimpleDateFormat field_98228_b;
+
+ final LogAgent field_98229_a;
+
+ private LogFormatter(LogAgent par1LogAgent) {
+ this.field_98229_a = par1LogAgent;
+ this.field_98228_b = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ }
+
+ public String format(LogRecord par1LogRecord) {
+ StringBuilder var2 = new StringBuilder();
+ var2.append(this.field_98228_b.format(Long.valueOf(par1LogRecord.getMillis())));
+
+ if (LogAgent.func_98237_a(this.field_98229_a) != null) {
+ var2.append(LogAgent.func_98237_a(this.field_98229_a));
+ }
+
+ var2.append(" [").append(par1LogRecord.getLevel().getName()).append("] ");
+ var2.append(this.formatMessage(par1LogRecord));
+ var2.append('\n');
+ Throwable var3 = par1LogRecord.getThrown();
+
+ if (var3 != null) {
+ StringWriter var4 = new StringWriter();
+ var3.printStackTrace(new PrintWriter(var4));
+ var2.append(var4.toString());
+ }
+
+ return var2.toString();
+ }
+
+ LogFormatter(LogAgent par1LogAgent, LogAgentINNER1 par2LogAgentINNER1) {
+ this(par1LogAgent);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/LongHashMap.java b/sp-server/src/main/java/net/minecraft/src/LongHashMap.java
new file mode 100644
index 0000000..7348291
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/LongHashMap.java
@@ -0,0 +1,216 @@
+package net.minecraft.src;
+
+import java.util.function.BiConsumer;
+
+public class LongHashMap {
+ /** the array of all elements in the hash */
+ private transient LongHashMapEntry[] hashArray = new LongHashMapEntry[16];
+
+ /** the number of elements in the hash array */
+ private transient int numHashElements;
+
+ /**
+ * the maximum amount of elements in the hash (probably 3/4 the size due to meh
+ * hashing function)
+ */
+ private int capacity = 12;
+
+ /**
+ * percent of the hasharray that can be used without hash colliding probably
+ */
+ private final float percentUseable = 0.75F;
+
+ /** count of times elements have been added/removed */
+ private transient volatile int modCount;
+
+ /**
+ * returns the hashed key given the original key
+ */
+ private static int getHashedKey(long par0) {
+ return hash((int) (par0 ^ par0 >>> 32));
+ }
+
+ /**
+ * the hash function
+ */
+ private static int hash(int par0) {
+ par0 ^= par0 >>> 20 ^ par0 >>> 12;
+ return par0 ^ par0 >>> 7 ^ par0 >>> 4;
+ }
+
+ /**
+ * gets the index in the hash given the array length and the hashed key
+ */
+ private static int getHashIndex(int par0, int par1) {
+ return par0 & par1 - 1;
+ }
+
+ public int getNumHashElements() {
+ return this.numHashElements;
+ }
+
+ /**
+ * get the value from the map given the key
+ */
+ public Object getValueByKey(long par1) {
+ int var3 = getHashedKey(par1);
+
+ for (LongHashMapEntry var4 = this.hashArray[getHashIndex(var3,
+ this.hashArray.length)]; var4 != null; var4 = var4.nextEntry) {
+ if (var4.key == par1) {
+ return var4.value;
+ }
+ }
+
+ return null;
+ }
+
+ public boolean containsItem(long par1) {
+ return this.getEntry(par1) != null;
+ }
+
+ final LongHashMapEntry getEntry(long par1) {
+ int var3 = getHashedKey(par1);
+
+ for (LongHashMapEntry var4 = this.hashArray[getHashIndex(var3,
+ this.hashArray.length)]; var4 != null; var4 = var4.nextEntry) {
+ if (var4.key == par1) {
+ return var4;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Add a key-value pair.
+ */
+ public void add(long par1, Object par3Obj) {
+ int var4 = getHashedKey(par1);
+ int var5 = getHashIndex(var4, this.hashArray.length);
+
+ for (LongHashMapEntry var6 = this.hashArray[var5]; var6 != null; var6 = var6.nextEntry) {
+ if (var6.key == par1) {
+ var6.value = par3Obj;
+ return;
+ }
+ }
+
+ ++this.modCount;
+ this.createKey(var4, par1, par3Obj, var5);
+ }
+
+ /**
+ * resizes the table
+ */
+ private void resizeTable(int par1) {
+ LongHashMapEntry[] var2 = this.hashArray;
+ int var3 = var2.length;
+
+ if (var3 == 1073741824) {
+ this.capacity = Integer.MAX_VALUE;
+ } else {
+ LongHashMapEntry[] var4 = new LongHashMapEntry[par1];
+ this.copyHashTableTo(var4);
+ this.hashArray = var4;
+ this.capacity = (int) ((float) par1 * this.percentUseable);
+ }
+ }
+
+ /**
+ * copies the hash table to the specified array
+ */
+ private void copyHashTableTo(LongHashMapEntry[] par1ArrayOfLongHashMapEntry) {
+ LongHashMapEntry[] var2 = this.hashArray;
+ int var3 = par1ArrayOfLongHashMapEntry.length;
+
+ for (int var4 = 0; var4 < var2.length; ++var4) {
+ LongHashMapEntry var5 = var2[var4];
+
+ if (var5 != null) {
+ var2[var4] = null;
+ LongHashMapEntry var6;
+
+ do {
+ var6 = var5.nextEntry;
+ int var7 = getHashIndex(var5.hash, var3);
+ var5.nextEntry = par1ArrayOfLongHashMapEntry[var7];
+ par1ArrayOfLongHashMapEntry[var7] = var5;
+ var5 = var6;
+ } while (var6 != null);
+ }
+ }
+ }
+
+ /**
+ * calls the removeKey method and returns removed object
+ */
+ public Object remove(long par1) {
+ LongHashMapEntry var3 = this.removeKey(par1);
+ return var3 == null ? null : var3.value;
+ }
+
+ /**
+ * removes the key from the hash linked list
+ */
+ final LongHashMapEntry removeKey(long par1) {
+ int var3 = getHashedKey(par1);
+ int var4 = getHashIndex(var3, this.hashArray.length);
+ LongHashMapEntry var5 = this.hashArray[var4];
+ LongHashMapEntry var6;
+ LongHashMapEntry var7;
+
+ for (var6 = var5; var6 != null; var6 = var7) {
+ var7 = var6.nextEntry;
+
+ if (var6.key == par1) {
+ ++this.modCount;
+ --this.numHashElements;
+
+ if (var5 == var6) {
+ this.hashArray[var4] = var7;
+ } else {
+ var5.nextEntry = var7;
+ }
+
+ return var6;
+ }
+
+ var5 = var6;
+ }
+
+ return var6;
+ }
+
+ public void iterate(BiConsumer con) {
+ for(int i = 0; i < this.hashArray.length; ++i) {
+ LongHashMapEntry var5 = this.hashArray[i];
+ LongHashMapEntry var6;
+ LongHashMapEntry var7;
+
+ for (var6 = var5; var6 != null; var6 = var7) {
+ var7 = var6.nextEntry;
+ con.accept(var6.key, var6.value);
+ }
+ }
+ }
+
+ /**
+ * creates the key in the hash table
+ */
+ private void createKey(int par1, long par2, Object par4Obj, int par5) {
+ LongHashMapEntry var6 = this.hashArray[par5];
+ this.hashArray[par5] = new LongHashMapEntry(par1, par2, par4Obj, var6);
+
+ if (this.numHashElements++ >= this.capacity) {
+ this.resizeTable(2 * this.hashArray.length);
+ }
+ }
+
+ /**
+ * public method to get the hashed key(hashCode)
+ */
+ static int getHashCode(long par0) {
+ return getHashedKey(par0);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/LongHashMapEntry.java b/sp-server/src/main/java/net/minecraft/src/LongHashMapEntry.java
new file mode 100644
index 0000000..83e40f2
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/LongHashMapEntry.java
@@ -0,0 +1,60 @@
+package net.minecraft.src;
+
+class LongHashMapEntry {
+ /**
+ * the key as a long (for playerInstances it is the x in the most significant 32
+ * bits and then y)
+ */
+ final long key;
+
+ /** the value held by the hash at the specified key */
+ Object value;
+
+ /** the next hashentry in the table */
+ LongHashMapEntry nextEntry;
+ final int hash;
+
+ LongHashMapEntry(int par1, long par2, Object par4Obj, LongHashMapEntry par5LongHashMapEntry) {
+ this.value = par4Obj;
+ this.nextEntry = par5LongHashMapEntry;
+ this.key = par2;
+ this.hash = par1;
+ }
+
+ public final long getKey() {
+ return this.key;
+ }
+
+ public final Object getValue() {
+ return this.value;
+ }
+
+ public final boolean equals(Object par1Obj) {
+ if (!(par1Obj instanceof LongHashMapEntry)) {
+ return false;
+ } else {
+ LongHashMapEntry var2 = (LongHashMapEntry) par1Obj;
+ Long var3 = Long.valueOf(this.getKey());
+ Long var4 = Long.valueOf(var2.getKey());
+
+ if (var3 == var4 || var3 != null && var3.equals(var4)) {
+ Object var5 = this.getValue();
+ Object var6 = var2.getValue();
+
+ if (var5 == var6 || var5 != null && var5.equals(var6)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+ }
+
+ public final int hashCode() {
+ return LongHashMap.getHashCode(this.key);
+ }
+
+ public final String toString() {
+ return this.getKey() + "=" + this.getValue();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/LowerStringMap.java b/sp-server/src/main/java/net/minecraft/src/LowerStringMap.java
new file mode 100644
index 0000000..787bdeb
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/LowerStringMap.java
@@ -0,0 +1,71 @@
+package net.minecraft.src;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+public class LowerStringMap implements Map {
+ private final Map internalMap = new LinkedHashMap();
+
+ public int size() {
+ return this.internalMap.size();
+ }
+
+ public boolean isEmpty() {
+ return this.internalMap.isEmpty();
+ }
+
+ public boolean containsKey(Object par1Obj) {
+ return this.internalMap.containsKey(par1Obj.toString().toLowerCase());
+ }
+
+ public boolean containsValue(Object par1Obj) {
+ return this.internalMap.containsKey(par1Obj);
+ }
+
+ public Object get(Object par1Obj) {
+ return this.internalMap.get(par1Obj.toString().toLowerCase());
+ }
+
+ /**
+ * a map already defines a general put
+ */
+ public Object putLower(String par1Str, Object par2Obj) {
+ return this.internalMap.put(par1Str.toLowerCase(), par2Obj);
+ }
+
+ public Object remove(Object par1Obj) {
+ return this.internalMap.remove(par1Obj.toString().toLowerCase());
+ }
+
+ public void putAll(Map par1Map) {
+ Iterator var2 = par1Map.entrySet().iterator();
+
+ while (var2.hasNext()) {
+ Entry var3 = (Entry) var2.next();
+ this.putLower((String) var3.getKey(), var3.getValue());
+ }
+ }
+
+ public void clear() {
+ this.internalMap.clear();
+ }
+
+ public Set keySet() {
+ return this.internalMap.keySet();
+ }
+
+ public Collection values() {
+ return this.internalMap.values();
+ }
+
+ public Set entrySet() {
+ return this.internalMap.entrySet();
+ }
+
+ public Object put(Object par1Obj, Object par2Obj) {
+ return this.putLower((String) par1Obj, par2Obj);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/MapColor.java b/sp-server/src/main/java/net/minecraft/src/MapColor.java
new file mode 100644
index 0000000..298a128
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/MapColor.java
@@ -0,0 +1,62 @@
+package net.minecraft.src;
+
+public class MapColor {
+ /**
+ * Holds all the 16 colors used on maps, very similar of a pallete system.
+ */
+ public static final MapColor[] mapColorArray = new MapColor[16];
+
+ /** The map color for Air blocks */
+ public static final MapColor airColor = new MapColor(0, 0);
+
+ /** this is the grass color in html format */
+ public static final MapColor grassColor = new MapColor(1, 8368696);
+
+ /** This is the color of the sand */
+ public static final MapColor sandColor = new MapColor(2, 16247203);
+
+ /** The map color for Cloth and Sponge blocks */
+ public static final MapColor clothColor = new MapColor(3, 10987431);
+
+ /** The map color for TNT blocks */
+ public static final MapColor tntColor = new MapColor(4, 16711680);
+
+ /** The map color for Ice blocks */
+ public static final MapColor iceColor = new MapColor(5, 10526975);
+
+ /** The map color for Iron blocks */
+ public static final MapColor ironColor = new MapColor(6, 10987431);
+
+ /** The map color for Leaf, Plant, Cactus, and Pumpkin blocks. */
+ public static final MapColor foliageColor = new MapColor(7, 31744);
+
+ /** The map color for Snow Cover and Snow blocks */
+ public static final MapColor snowColor = new MapColor(8, 16777215);
+
+ /** The map color for Clay blocks */
+ public static final MapColor clayColor = new MapColor(9, 10791096);
+
+ /** The map color for Dirt blocks */
+ public static final MapColor dirtColor = new MapColor(10, 12020271);
+
+ /** The map color for Stone blocks */
+ public static final MapColor stoneColor = new MapColor(11, 7368816);
+
+ /** The map color for Water blocks */
+ public static final MapColor waterColor = new MapColor(12, 4210943);
+
+ /** The map color for Wood blocks */
+ public static final MapColor woodColor = new MapColor(13, 6837042);
+
+ /** Holds the color in RGB value that will be rendered on maps. */
+ public final int colorValue;
+
+ /** Holds the index of the color used on map. */
+ public final int colorIndex;
+
+ private MapColor(int par1, int par2) {
+ this.colorIndex = par1;
+ this.colorValue = par2;
+ mapColorArray[par1] = this;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/MapCoord.java b/sp-server/src/main/java/net/minecraft/src/MapCoord.java
new file mode 100644
index 0000000..32f2a91
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/MapCoord.java
@@ -0,0 +1,18 @@
+package net.minecraft.src;
+
+public class MapCoord {
+ public byte iconSize;
+ public byte centerX;
+ public byte centerZ;
+ public byte iconRotation;
+
+ final MapData data;
+
+ public MapCoord(MapData par1MapData, byte par2, byte par3, byte par4, byte par5) {
+ this.data = par1MapData;
+ this.iconSize = par2;
+ this.centerX = par3;
+ this.centerZ = par4;
+ this.iconRotation = par5;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/MapData.java b/sp-server/src/main/java/net/minecraft/src/MapData.java
new file mode 100644
index 0000000..e6f6c9b
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/MapData.java
@@ -0,0 +1,216 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+public class MapData extends WorldSavedData {
+ public int xCenter;
+ public int zCenter;
+ public byte dimension;
+ public byte scale;
+
+ /** colours */
+ public byte[] colors = new byte[16384];
+
+ /**
+ * Holds a reference to the MapInfo of the players who own a copy of the map
+ */
+ public List playersArrayList = new ArrayList();
+
+ /**
+ * Holds a reference to the players who own a copy of the map and a reference to
+ * their MapInfo
+ */
+ private Map playersHashMap = new HashMap();
+ public Map playersVisibleOnMap = new LinkedHashMap();
+
+ public MapData(String par1Str) {
+ super(par1Str);
+ }
+
+ /**
+ * reads in data from the NBTTagCompound into this MapDataBase
+ */
+ public void readFromNBT(NBTTagCompound par1NBTTagCompound) {
+ this.dimension = par1NBTTagCompound.getByte("dimension");
+ this.xCenter = par1NBTTagCompound.getInteger("xCenter");
+ this.zCenter = par1NBTTagCompound.getInteger("zCenter");
+ this.scale = par1NBTTagCompound.getByte("scale");
+
+ if (this.scale < 0) {
+ this.scale = 0;
+ }
+
+ if (this.scale > 4) {
+ this.scale = 4;
+ }
+
+ short var2 = par1NBTTagCompound.getShort("width");
+ short var3 = par1NBTTagCompound.getShort("height");
+
+ if (var2 == 128 && var3 == 128) {
+ this.colors = par1NBTTagCompound.getByteArray("colors");
+ } else {
+ byte[] var4 = par1NBTTagCompound.getByteArray("colors");
+ this.colors = new byte[16384];
+ int var5 = (128 - var2) / 2;
+ int var6 = (128 - var3) / 2;
+
+ for (int var7 = 0; var7 < var3; ++var7) {
+ int var8 = var7 + var6;
+
+ if (var8 >= 0 || var8 < 128) {
+ for (int var9 = 0; var9 < var2; ++var9) {
+ int var10 = var9 + var5;
+
+ if (var10 >= 0 || var10 < 128) {
+ this.colors[var10 + var8 * 128] = var4[var9 + var7 * var2];
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * write data to NBTTagCompound from this MapDataBase, similar to Entities and
+ * TileEntities
+ */
+ public void writeToNBT(NBTTagCompound par1NBTTagCompound) {
+ par1NBTTagCompound.setByte("dimension", this.dimension);
+ par1NBTTagCompound.setInteger("xCenter", this.xCenter);
+ par1NBTTagCompound.setInteger("zCenter", this.zCenter);
+ par1NBTTagCompound.setByte("scale", this.scale);
+ par1NBTTagCompound.setShort("width", (short) 128);
+ par1NBTTagCompound.setShort("height", (short) 128);
+ par1NBTTagCompound.setByteArray("colors", this.colors);
+ }
+
+ /**
+ * Adds the player passed to the list of visible players and checks to see which
+ * players are visible
+ */
+ public void updateVisiblePlayers(EntityPlayer par1EntityPlayer, ItemStack par2ItemStack) {
+ if (!this.playersHashMap.containsKey(par1EntityPlayer)) {
+ MapInfo var3 = new MapInfo(this, par1EntityPlayer);
+ this.playersHashMap.put(par1EntityPlayer, var3);
+ this.playersArrayList.add(var3);
+ }
+
+ if (!par1EntityPlayer.inventory.hasItemStack(par2ItemStack)) {
+ this.playersVisibleOnMap.remove(par1EntityPlayer.getCommandSenderName());
+ }
+
+ for (int var5 = 0; var5 < this.playersArrayList.size(); ++var5) {
+ MapInfo var4 = (MapInfo) this.playersArrayList.get(var5);
+
+ if (!var4.entityplayerObj.isDead
+ && (var4.entityplayerObj.inventory.hasItemStack(par2ItemStack) || par2ItemStack.isOnItemFrame())) {
+ if (!par2ItemStack.isOnItemFrame() && var4.entityplayerObj.dimension == this.dimension) {
+ this.func_82567_a(0, var4.entityplayerObj.worldObj, var4.entityplayerObj.getCommandSenderName(),
+ var4.entityplayerObj.posX, var4.entityplayerObj.posZ,
+ (double) var4.entityplayerObj.rotationYaw);
+ }
+ } else {
+ this.playersHashMap.remove(var4.entityplayerObj);
+ this.playersArrayList.remove(var4);
+ }
+ }
+
+ if (par2ItemStack.isOnItemFrame()) {
+ this.func_82567_a(1, par1EntityPlayer.worldObj, "frame-" + par2ItemStack.getItemFrame().entityId,
+ (double) par2ItemStack.getItemFrame().xPosition, (double) par2ItemStack.getItemFrame().zPosition,
+ (double) (par2ItemStack.getItemFrame().hangingDirection * 90));
+ }
+ }
+
+ private void func_82567_a(int par1, World par2World, String par3Str, double par4, double par6, double par8) {
+ int var10 = 1 << this.scale;
+ float var11 = (float) (par4 - (double) this.xCenter) / (float) var10;
+ float var12 = (float) (par6 - (double) this.zCenter) / (float) var10;
+ byte var13 = (byte) ((int) ((double) (var11 * 2.0F) + 0.5D));
+ byte var14 = (byte) ((int) ((double) (var12 * 2.0F) + 0.5D));
+ byte var16 = 63;
+ byte var15;
+
+ if (var11 >= (float) (-var16) && var12 >= (float) (-var16) && var11 <= (float) var16
+ && var12 <= (float) var16) {
+ par8 += par8 < 0.0D ? -8.0D : 8.0D;
+ var15 = (byte) ((int) (par8 * 16.0D / 360.0D));
+
+ if (this.dimension < 0) {
+ int var17 = (int) (par2World.getWorldInfo().getWorldTime() / 10L);
+ var15 = (byte) (var17 * var17 * 34187121 + var17 * 121 >> 15 & 15);
+ }
+ } else {
+ if (Math.abs(var11) >= 320.0F || Math.abs(var12) >= 320.0F) {
+ this.playersVisibleOnMap.remove(par3Str);
+ return;
+ }
+
+ par1 = 6;
+ var15 = 0;
+
+ if (var11 <= (float) (-var16)) {
+ var13 = (byte) ((int) ((double) (var16 * 2) + 2.5D));
+ }
+
+ if (var12 <= (float) (-var16)) {
+ var14 = (byte) ((int) ((double) (var16 * 2) + 2.5D));
+ }
+
+ if (var11 >= (float) var16) {
+ var13 = (byte) (var16 * 2 + 1);
+ }
+
+ if (var12 >= (float) var16) {
+ var14 = (byte) (var16 * 2 + 1);
+ }
+ }
+
+ this.playersVisibleOnMap.put(par3Str, new MapCoord(this, (byte) par1, var13, var14, var15));
+ }
+
+ /**
+ * Get byte array of packet data to send to players on map for updating map data
+ */
+ public byte[] getUpdatePacketData(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer) {
+ MapInfo var4 = (MapInfo) this.playersHashMap.get(par3EntityPlayer);
+ return var4 == null ? null : var4.getPlayersOnMap(par1ItemStack);
+ }
+
+ /**
+ * Marks a vertical range of pixels as being modified so they will be resent to
+ * clients. Parameters: X, lowest Y, highest Y
+ */
+ public void setColumnDirty(int par1, int par2, int par3) {
+ super.markDirty();
+
+ for (int var4 = 0; var4 < this.playersArrayList.size(); ++var4) {
+ MapInfo var5 = (MapInfo) this.playersArrayList.get(var4);
+
+ if (var5.field_76209_b[par1] < 0 || var5.field_76209_b[par1] > par2) {
+ var5.field_76209_b[par1] = par2;
+ }
+
+ if (var5.field_76210_c[par1] < 0 || var5.field_76210_c[par1] < par3) {
+ var5.field_76210_c[par1] = par3;
+ }
+ }
+ }
+
+ public MapInfo func_82568_a(EntityPlayer par1EntityPlayer) {
+ MapInfo var2 = (MapInfo) this.playersHashMap.get(par1EntityPlayer);
+
+ if (var2 == null) {
+ var2 = new MapInfo(this, par1EntityPlayer);
+ this.playersHashMap.put(par1EntityPlayer, var2);
+ this.playersArrayList.add(var2);
+ }
+
+ return var2;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/MapGenBase.java b/sp-server/src/main/java/net/minecraft/src/MapGenBase.java
new file mode 100644
index 0000000..2269720
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/MapGenBase.java
@@ -0,0 +1,38 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class MapGenBase {
+ /** The number of Chunks to gen-check in any given direction. */
+ protected int range = 8;
+
+ /** The RNG used by the MapGen classes. */
+ protected EaglercraftRandom rand = new EaglercraftRandom();
+
+ /** This world object. */
+ protected World worldObj;
+
+ public void generate(IChunkProvider par1IChunkProvider, World par2World, int par3, int par4,
+ byte[] par5ArrayOfByte) {
+ int var6 = this.range;
+ this.worldObj = par2World;
+ this.rand.setSeed(par2World.getSeed());
+ long var7 = this.rand.nextLong();
+ long var9 = this.rand.nextLong();
+
+ for (int var11 = par3 - var6; var11 <= par3 + var6; ++var11) {
+ for (int var12 = par4 - var6; var12 <= par4 + var6; ++var12) {
+ long var13 = (long) var11 * var7;
+ long var15 = (long) var12 * var9;
+ this.rand.setSeed(var13 ^ var15 ^ par2World.getSeed());
+ this.recursiveGenerate(par2World, var11, var12, par3, par4, par5ArrayOfByte);
+ }
+ }
+ }
+
+ /**
+ * Recursively called by generate() (generate) and optionally by itself.
+ */
+ protected void recursiveGenerate(World par1World, int par2, int par3, int par4, int par5, byte[] par6ArrayOfByte) {
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/MapGenCaves.java b/sp-server/src/main/java/net/minecraft/src/MapGenCaves.java
new file mode 100644
index 0000000..c30a927
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/MapGenCaves.java
@@ -0,0 +1,225 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class MapGenCaves extends MapGenBase {
+ /**
+ * Generates a larger initial cave node than usual. Called 25% of the time.
+ */
+ protected void generateLargeCaveNode(long par1, int par3, int par4, byte[] par5ArrayOfByte, double par6,
+ double par8, double par10) {
+ this.generateCaveNode(par1, par3, par4, par5ArrayOfByte, par6, par8, par10, 1.0F + this.rand.nextFloat() * 6.0F,
+ 0.0F, 0.0F, -1, -1, 0.5D);
+ }
+
+ /**
+ * Generates a node in the current cave system recursion tree.
+ */
+ protected void generateCaveNode(long par1, int par3, int par4, byte[] par5ArrayOfByte, double par6, double par8,
+ double par10, float par12, float par13, float par14, int par15, int par16, double par17) {
+ double var19 = (double) (par3 * 16 + 8);
+ double var21 = (double) (par4 * 16 + 8);
+ float var23 = 0.0F;
+ float var24 = 0.0F;
+ EaglercraftRandom var25 = new EaglercraftRandom(par1);
+
+ if (par16 <= 0) {
+ int var26 = this.range * 16 - 16;
+ par16 = var26 - var25.nextInt(var26 / 4);
+ }
+
+ boolean var54 = false;
+
+ if (par15 == -1) {
+ par15 = par16 / 2;
+ var54 = true;
+ }
+
+ int var27 = var25.nextInt(par16 / 2) + par16 / 4;
+
+ for (boolean var28 = var25.nextInt(6) == 0; par15 < par16; ++par15) {
+ double var29 = 1.5D
+ + (double) (MathHelper.sin((float) par15 * (float) Math.PI / (float) par16) * par12 * 1.0F);
+ double var31 = var29 * par17;
+ float var33 = MathHelper.cos(par14);
+ float var34 = MathHelper.sin(par14);
+ par6 += (double) (MathHelper.cos(par13) * var33);
+ par8 += (double) var34;
+ par10 += (double) (MathHelper.sin(par13) * var33);
+
+ if (var28) {
+ par14 *= 0.92F;
+ } else {
+ par14 *= 0.7F;
+ }
+
+ par14 += var24 * 0.1F;
+ par13 += var23 * 0.1F;
+ var24 *= 0.9F;
+ var23 *= 0.75F;
+ var24 += (var25.nextFloat() - var25.nextFloat()) * var25.nextFloat() * 2.0F;
+ var23 += (var25.nextFloat() - var25.nextFloat()) * var25.nextFloat() * 4.0F;
+
+ if (!var54 && par15 == var27 && par12 > 1.0F && par16 > 0) {
+ this.generateCaveNode(var25.nextLong(), par3, par4, par5ArrayOfByte, par6, par8, par10,
+ var25.nextFloat() * 0.5F + 0.5F, par13 - ((float) Math.PI / 2F), par14 / 3.0F, par15, par16,
+ 1.0D);
+ this.generateCaveNode(var25.nextLong(), par3, par4, par5ArrayOfByte, par6, par8, par10,
+ var25.nextFloat() * 0.5F + 0.5F, par13 + ((float) Math.PI / 2F), par14 / 3.0F, par15, par16,
+ 1.0D);
+ return;
+ }
+
+ if (var54 || var25.nextInt(4) != 0) {
+ double var35 = par6 - var19;
+ double var37 = par10 - var21;
+ double var39 = (double) (par16 - par15);
+ double var41 = (double) (par12 + 2.0F + 16.0F);
+
+ if (var35 * var35 + var37 * var37 - var39 * var39 > var41 * var41) {
+ return;
+ }
+
+ if (par6 >= var19 - 16.0D - var29 * 2.0D && par10 >= var21 - 16.0D - var29 * 2.0D
+ && par6 <= var19 + 16.0D + var29 * 2.0D && par10 <= var21 + 16.0D + var29 * 2.0D) {
+ int var55 = MathHelper.floor_double(par6 - var29) - par3 * 16 - 1;
+ int var36 = MathHelper.floor_double(par6 + var29) - par3 * 16 + 1;
+ int var56 = MathHelper.floor_double(par8 - var31) - 1;
+ int var38 = MathHelper.floor_double(par8 + var31) + 1;
+ int var57 = MathHelper.floor_double(par10 - var29) - par4 * 16 - 1;
+ int var40 = MathHelper.floor_double(par10 + var29) - par4 * 16 + 1;
+
+ if (var55 < 0) {
+ var55 = 0;
+ }
+
+ if (var36 > 16) {
+ var36 = 16;
+ }
+
+ if (var56 < 1) {
+ var56 = 1;
+ }
+
+ if (var38 > 120) {
+ var38 = 120;
+ }
+
+ if (var57 < 0) {
+ var57 = 0;
+ }
+
+ if (var40 > 16) {
+ var40 = 16;
+ }
+
+ boolean var58 = false;
+ int var42;
+ int var45;
+
+ for (var42 = var55; !var58 && var42 < var36; ++var42) {
+ for (int var43 = var57; !var58 && var43 < var40; ++var43) {
+ for (int var44 = var38 + 1; !var58 && var44 >= var56 - 1; --var44) {
+ var45 = (var42 * 16 + var43) * 128 + var44;
+
+ if (var44 >= 0 && var44 < 128) {
+ if (par5ArrayOfByte[var45] == Block.waterMoving.blockID
+ || par5ArrayOfByte[var45] == Block.waterStill.blockID) {
+ var58 = true;
+ }
+
+ if (var44 != var56 - 1 && var42 != var55 && var42 != var36 - 1 && var43 != var57
+ && var43 != var40 - 1) {
+ var44 = var56;
+ }
+ }
+ }
+ }
+ }
+
+ if (!var58) {
+ for (var42 = var55; var42 < var36; ++var42) {
+ double var59 = ((double) (var42 + par3 * 16) + 0.5D - par6) / var29;
+
+ for (var45 = var57; var45 < var40; ++var45) {
+ double var46 = ((double) (var45 + par4 * 16) + 0.5D - par10) / var29;
+ int var48 = (var42 * 16 + var45) * 128 + var38;
+ boolean var49 = false;
+
+ if (var59 * var59 + var46 * var46 < 1.0D) {
+ for (int var50 = var38 - 1; var50 >= var56; --var50) {
+ double var51 = ((double) var50 + 0.5D - par8) / var31;
+
+ if (var51 > -0.7D && var59 * var59 + var51 * var51 + var46 * var46 < 1.0D) {
+ byte var53 = par5ArrayOfByte[var48];
+
+ if (var53 == Block.grass.blockID) {
+ var49 = true;
+ }
+
+ if (var53 == Block.stone.blockID || var53 == Block.dirt.blockID
+ || var53 == Block.grass.blockID) {
+ if (var50 < 10) {
+ par5ArrayOfByte[var48] = (byte) Block.lavaMoving.blockID;
+ } else {
+ par5ArrayOfByte[var48] = 0;
+
+ if (var49 && par5ArrayOfByte[var48 - 1] == Block.dirt.blockID) {
+ par5ArrayOfByte[var48 - 1] = this.worldObj.getBiomeGenForCoords(
+ var42 + par3 * 16, var45 + par4 * 16).topBlock;
+ }
+ }
+ }
+ }
+
+ --var48;
+ }
+ }
+ }
+ }
+
+ if (var54) {
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Recursively called by generate() (generate) and optionally by itself.
+ */
+ protected void recursiveGenerate(World par1World, int par2, int par3, int par4, int par5, byte[] par6ArrayOfByte) {
+ int var7 = this.rand.nextInt(this.rand.nextInt(this.rand.nextInt(40) + 1) + 1);
+
+ if (this.rand.nextInt(15) != 0) {
+ var7 = 0;
+ }
+
+ for (int var8 = 0; var8 < var7; ++var8) {
+ double var9 = (double) (par2 * 16 + this.rand.nextInt(16));
+ double var11 = (double) this.rand.nextInt(this.rand.nextInt(120) + 8);
+ double var13 = (double) (par3 * 16 + this.rand.nextInt(16));
+ int var15 = 1;
+
+ if (this.rand.nextInt(4) == 0) {
+ this.generateLargeCaveNode(this.rand.nextLong(), par4, par5, par6ArrayOfByte, var9, var11, var13);
+ var15 += this.rand.nextInt(4);
+ }
+
+ for (int var16 = 0; var16 < var15; ++var16) {
+ float var17 = this.rand.nextFloat() * (float) Math.PI * 2.0F;
+ float var18 = (this.rand.nextFloat() - 0.5F) * 2.0F / 8.0F;
+ float var19 = this.rand.nextFloat() * 2.0F + this.rand.nextFloat();
+
+ if (this.rand.nextInt(10) == 0) {
+ var19 *= this.rand.nextFloat() * this.rand.nextFloat() * 3.0F + 1.0F;
+ }
+
+ this.generateCaveNode(this.rand.nextLong(), par4, par5, par6ArrayOfByte, var9, var11, var13, var19,
+ var17, var18, 0, 0, 1.0D);
+ }
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/MapGenCavesHell.java b/sp-server/src/main/java/net/minecraft/src/MapGenCavesHell.java
new file mode 100644
index 0000000..431c1aa
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/MapGenCavesHell.java
@@ -0,0 +1,204 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class MapGenCavesHell extends MapGenBase {
+ /**
+ * Generates a larger initial cave node than usual. Called 25% of the time.
+ */
+ protected void generateLargeCaveNode(long par1, int par3, int par4, byte[] par5ArrayOfByte, double par6,
+ double par8, double par10) {
+ this.generateCaveNode(par1, par3, par4, par5ArrayOfByte, par6, par8, par10, 1.0F + this.rand.nextFloat() * 6.0F,
+ 0.0F, 0.0F, -1, -1, 0.5D);
+ }
+
+ /**
+ * Generates a node in the current cave system recursion tree.
+ */
+ protected void generateCaveNode(long par1, int par3, int par4, byte[] par5ArrayOfByte, double par6, double par8,
+ double par10, float par12, float par13, float par14, int par15, int par16, double par17) {
+ double var19 = (double) (par3 * 16 + 8);
+ double var21 = (double) (par4 * 16 + 8);
+ float var23 = 0.0F;
+ float var24 = 0.0F;
+ EaglercraftRandom var25 = new EaglercraftRandom(par1);
+
+ if (par16 <= 0) {
+ int var26 = this.range * 16 - 16;
+ par16 = var26 - var25.nextInt(var26 / 4);
+ }
+
+ boolean var53 = false;
+
+ if (par15 == -1) {
+ par15 = par16 / 2;
+ var53 = true;
+ }
+
+ int var27 = var25.nextInt(par16 / 2) + par16 / 4;
+
+ for (boolean var28 = var25.nextInt(6) == 0; par15 < par16; ++par15) {
+ double var29 = 1.5D
+ + (double) (MathHelper.sin((float) par15 * (float) Math.PI / (float) par16) * par12 * 1.0F);
+ double var31 = var29 * par17;
+ float var33 = MathHelper.cos(par14);
+ float var34 = MathHelper.sin(par14);
+ par6 += (double) (MathHelper.cos(par13) * var33);
+ par8 += (double) var34;
+ par10 += (double) (MathHelper.sin(par13) * var33);
+
+ if (var28) {
+ par14 *= 0.92F;
+ } else {
+ par14 *= 0.7F;
+ }
+
+ par14 += var24 * 0.1F;
+ par13 += var23 * 0.1F;
+ var24 *= 0.9F;
+ var23 *= 0.75F;
+ var24 += (var25.nextFloat() - var25.nextFloat()) * var25.nextFloat() * 2.0F;
+ var23 += (var25.nextFloat() - var25.nextFloat()) * var25.nextFloat() * 4.0F;
+
+ if (!var53 && par15 == var27 && par12 > 1.0F) {
+ this.generateCaveNode(var25.nextLong(), par3, par4, par5ArrayOfByte, par6, par8, par10,
+ var25.nextFloat() * 0.5F + 0.5F, par13 - ((float) Math.PI / 2F), par14 / 3.0F, par15, par16,
+ 1.0D);
+ this.generateCaveNode(var25.nextLong(), par3, par4, par5ArrayOfByte, par6, par8, par10,
+ var25.nextFloat() * 0.5F + 0.5F, par13 + ((float) Math.PI / 2F), par14 / 3.0F, par15, par16,
+ 1.0D);
+ return;
+ }
+
+ if (var53 || var25.nextInt(4) != 0) {
+ double var35 = par6 - var19;
+ double var37 = par10 - var21;
+ double var39 = (double) (par16 - par15);
+ double var41 = (double) (par12 + 2.0F + 16.0F);
+
+ if (var35 * var35 + var37 * var37 - var39 * var39 > var41 * var41) {
+ return;
+ }
+
+ if (par6 >= var19 - 16.0D - var29 * 2.0D && par10 >= var21 - 16.0D - var29 * 2.0D
+ && par6 <= var19 + 16.0D + var29 * 2.0D && par10 <= var21 + 16.0D + var29 * 2.0D) {
+ int var54 = MathHelper.floor_double(par6 - var29) - par3 * 16 - 1;
+ int var36 = MathHelper.floor_double(par6 + var29) - par3 * 16 + 1;
+ int var55 = MathHelper.floor_double(par8 - var31) - 1;
+ int var38 = MathHelper.floor_double(par8 + var31) + 1;
+ int var56 = MathHelper.floor_double(par10 - var29) - par4 * 16 - 1;
+ int var40 = MathHelper.floor_double(par10 + var29) - par4 * 16 + 1;
+
+ if (var54 < 0) {
+ var54 = 0;
+ }
+
+ if (var36 > 16) {
+ var36 = 16;
+ }
+
+ if (var55 < 1) {
+ var55 = 1;
+ }
+
+ if (var38 > 120) {
+ var38 = 120;
+ }
+
+ if (var56 < 0) {
+ var56 = 0;
+ }
+
+ if (var40 > 16) {
+ var40 = 16;
+ }
+
+ boolean var57 = false;
+ int var42;
+ int var45;
+
+ for (var42 = var54; !var57 && var42 < var36; ++var42) {
+ for (int var43 = var56; !var57 && var43 < var40; ++var43) {
+ for (int var44 = var38 + 1; !var57 && var44 >= var55 - 1; --var44) {
+ var45 = (var42 * 16 + var43) * 128 + var44;
+
+ if (var44 >= 0 && var44 < 128) {
+ if (par5ArrayOfByte[var45] == Block.lavaMoving.blockID
+ || par5ArrayOfByte[var45] == Block.lavaStill.blockID) {
+ var57 = true;
+ }
+
+ if (var44 != var55 - 1 && var42 != var54 && var42 != var36 - 1 && var43 != var56
+ && var43 != var40 - 1) {
+ var44 = var55;
+ }
+ }
+ }
+ }
+ }
+
+ if (!var57) {
+ for (var42 = var54; var42 < var36; ++var42) {
+ double var58 = ((double) (var42 + par3 * 16) + 0.5D - par6) / var29;
+
+ for (var45 = var56; var45 < var40; ++var45) {
+ double var46 = ((double) (var45 + par4 * 16) + 0.5D - par10) / var29;
+ int var48 = (var42 * 16 + var45) * 128 + var38;
+
+ for (int var49 = var38 - 1; var49 >= var55; --var49) {
+ double var50 = ((double) var49 + 0.5D - par8) / var31;
+
+ if (var50 > -0.7D && var58 * var58 + var50 * var50 + var46 * var46 < 1.0D) {
+ byte var52 = par5ArrayOfByte[var48];
+
+ if (var52 == Block.netherrack.blockID || var52 == Block.dirt.blockID
+ || var52 == Block.grass.blockID) {
+ par5ArrayOfByte[var48] = 0;
+ }
+ }
+
+ --var48;
+ }
+ }
+ }
+
+ if (var53) {
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Recursively called by generate() (generate) and optionally by itself.
+ */
+ protected void recursiveGenerate(World par1World, int par2, int par3, int par4, int par5, byte[] par6ArrayOfByte) {
+ int var7 = this.rand.nextInt(this.rand.nextInt(this.rand.nextInt(10) + 1) + 1);
+
+ if (this.rand.nextInt(5) != 0) {
+ var7 = 0;
+ }
+
+ for (int var8 = 0; var8 < var7; ++var8) {
+ double var9 = (double) (par2 * 16 + this.rand.nextInt(16));
+ double var11 = (double) this.rand.nextInt(128);
+ double var13 = (double) (par3 * 16 + this.rand.nextInt(16));
+ int var15 = 1;
+
+ if (this.rand.nextInt(4) == 0) {
+ this.generateLargeCaveNode(this.rand.nextLong(), par4, par5, par6ArrayOfByte, var9, var11, var13);
+ var15 += this.rand.nextInt(4);
+ }
+
+ for (int var16 = 0; var16 < var15; ++var16) {
+ float var17 = this.rand.nextFloat() * (float) Math.PI * 2.0F;
+ float var18 = (this.rand.nextFloat() - 0.5F) * 2.0F / 8.0F;
+ float var19 = this.rand.nextFloat() * 2.0F + this.rand.nextFloat();
+ this.generateCaveNode(this.rand.nextLong(), par4, par5, par6ArrayOfByte, var9, var11, var13,
+ var19 * 2.0F, var17, var18, 0, 0, 0.5D);
+ }
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/MapGenMineshaft.java b/sp-server/src/main/java/net/minecraft/src/MapGenMineshaft.java
new file mode 100644
index 0000000..76239bc
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/MapGenMineshaft.java
@@ -0,0 +1,33 @@
+package net.minecraft.src;
+
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+
+public class MapGenMineshaft extends MapGenStructure {
+ private double field_82673_e = 0.01D;
+
+ public MapGenMineshaft() {
+ }
+
+ public MapGenMineshaft(Map par1Map) {
+ Iterator var2 = par1Map.entrySet().iterator();
+
+ while (var2.hasNext()) {
+ Entry var3 = (Entry) var2.next();
+
+ if (((String) var3.getKey()).equals("chance")) {
+ this.field_82673_e = MathHelper.parseDoubleWithDefault((String) var3.getValue(), this.field_82673_e);
+ }
+ }
+ }
+
+ protected boolean canSpawnStructureAtCoords(int par1, int par2) {
+ return this.rand.nextDouble() < this.field_82673_e
+ && this.rand.nextInt(80) < Math.max(Math.abs(par1), Math.abs(par2));
+ }
+
+ protected StructureStart getStructureStart(int par1, int par2) {
+ return new StructureMineshaftStart(this.worldObj, this.rand, par1, par2);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/MapGenNetherBridge.java b/sp-server/src/main/java/net/minecraft/src/MapGenNetherBridge.java
new file mode 100644
index 0000000..923ba36
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/MapGenNetherBridge.java
@@ -0,0 +1,33 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class MapGenNetherBridge extends MapGenStructure {
+ private List spawnList = new ArrayList();
+
+ public MapGenNetherBridge() {
+ this.spawnList.add(new SpawnListEntry((w) -> new EntityBlaze(w), 10, 2, 3));
+ this.spawnList.add(new SpawnListEntry((w) -> new EntityPigZombie(w), 5, 4, 4));
+ this.spawnList.add(new SpawnListEntry((w) -> new EntitySkeleton(w), 10, 4, 4));
+ this.spawnList.add(new SpawnListEntry((w) -> new EntityMagmaCube(w), 3, 4, 4));
+ }
+
+ public List getSpawnList() {
+ return this.spawnList;
+ }
+
+ protected boolean canSpawnStructureAtCoords(int par1, int par2) {
+ int var3 = par1 >> 4;
+ int var4 = par2 >> 4;
+ this.rand.setSeed((long) (var3 ^ var4 << 4) ^ this.worldObj.getSeed());
+ this.rand.nextInt();
+ return this.rand.nextInt(3) != 0 ? false
+ : (par1 != (var3 << 4) + 4 + this.rand.nextInt(8) ? false
+ : par2 == (var4 << 4) + 4 + this.rand.nextInt(8));
+ }
+
+ protected StructureStart getStructureStart(int par1, int par2) {
+ return new StructureNetherBridgeStart(this.worldObj, this.rand, par1, par2);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/MapGenRavine.java b/sp-server/src/main/java/net/minecraft/src/MapGenRavine.java
new file mode 100644
index 0000000..6f3f1ec
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/MapGenRavine.java
@@ -0,0 +1,194 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class MapGenRavine extends MapGenBase {
+ private float[] field_75046_d = new float[1024];
+
+ protected void generateRavine(long par1, int par3, int par4, byte[] par5ArrayOfByte, double par6, double par8,
+ double par10, float par12, float par13, float par14, int par15, int par16, double par17) {
+ EaglercraftRandom var19 = new EaglercraftRandom(par1);
+ double var20 = (double) (par3 * 16 + 8);
+ double var22 = (double) (par4 * 16 + 8);
+ float var24 = 0.0F;
+ float var25 = 0.0F;
+
+ if (par16 <= 0) {
+ int var26 = this.range * 16 - 16;
+ par16 = var26 - var19.nextInt(var26 / 4);
+ }
+
+ boolean var53 = false;
+
+ if (par15 == -1) {
+ par15 = par16 / 2;
+ var53 = true;
+ }
+
+ float var27 = 1.0F;
+
+ for (int var28 = 0; var28 < 128; ++var28) {
+ if (var28 == 0 || var19.nextInt(3) == 0) {
+ var27 = 1.0F + var19.nextFloat() * var19.nextFloat() * 1.0F;
+ }
+
+ this.field_75046_d[var28] = var27 * var27;
+ }
+
+ for (; par15 < par16; ++par15) {
+ double var54 = 1.5D
+ + (double) (MathHelper.sin((float) par15 * (float) Math.PI / (float) par16) * par12 * 1.0F);
+ double var30 = var54 * par17;
+ var54 *= (double) var19.nextFloat() * 0.25D + 0.75D;
+ var30 *= (double) var19.nextFloat() * 0.25D + 0.75D;
+ float var32 = MathHelper.cos(par14);
+ float var33 = MathHelper.sin(par14);
+ par6 += (double) (MathHelper.cos(par13) * var32);
+ par8 += (double) var33;
+ par10 += (double) (MathHelper.sin(par13) * var32);
+ par14 *= 0.7F;
+ par14 += var25 * 0.05F;
+ par13 += var24 * 0.05F;
+ var25 *= 0.8F;
+ var24 *= 0.5F;
+ var25 += (var19.nextFloat() - var19.nextFloat()) * var19.nextFloat() * 2.0F;
+ var24 += (var19.nextFloat() - var19.nextFloat()) * var19.nextFloat() * 4.0F;
+
+ if (var53 || var19.nextInt(4) != 0) {
+ double var34 = par6 - var20;
+ double var36 = par10 - var22;
+ double var38 = (double) (par16 - par15);
+ double var40 = (double) (par12 + 2.0F + 16.0F);
+
+ if (var34 * var34 + var36 * var36 - var38 * var38 > var40 * var40) {
+ return;
+ }
+
+ if (par6 >= var20 - 16.0D - var54 * 2.0D && par10 >= var22 - 16.0D - var54 * 2.0D
+ && par6 <= var20 + 16.0D + var54 * 2.0D && par10 <= var22 + 16.0D + var54 * 2.0D) {
+ int var55 = MathHelper.floor_double(par6 - var54) - par3 * 16 - 1;
+ int var35 = MathHelper.floor_double(par6 + var54) - par3 * 16 + 1;
+ int var56 = MathHelper.floor_double(par8 - var30) - 1;
+ int var37 = MathHelper.floor_double(par8 + var30) + 1;
+ int var57 = MathHelper.floor_double(par10 - var54) - par4 * 16 - 1;
+ int var39 = MathHelper.floor_double(par10 + var54) - par4 * 16 + 1;
+
+ if (var55 < 0) {
+ var55 = 0;
+ }
+
+ if (var35 > 16) {
+ var35 = 16;
+ }
+
+ if (var56 < 1) {
+ var56 = 1;
+ }
+
+ if (var37 > 120) {
+ var37 = 120;
+ }
+
+ if (var57 < 0) {
+ var57 = 0;
+ }
+
+ if (var39 > 16) {
+ var39 = 16;
+ }
+
+ boolean var58 = false;
+ int var41;
+ int var44;
+
+ for (var41 = var55; !var58 && var41 < var35; ++var41) {
+ for (int var42 = var57; !var58 && var42 < var39; ++var42) {
+ for (int var43 = var37 + 1; !var58 && var43 >= var56 - 1; --var43) {
+ var44 = (var41 * 16 + var42) * 128 + var43;
+
+ if (var43 >= 0 && var43 < 128) {
+ if (par5ArrayOfByte[var44] == Block.waterMoving.blockID
+ || par5ArrayOfByte[var44] == Block.waterStill.blockID) {
+ var58 = true;
+ }
+
+ if (var43 != var56 - 1 && var41 != var55 && var41 != var35 - 1 && var42 != var57
+ && var42 != var39 - 1) {
+ var43 = var56;
+ }
+ }
+ }
+ }
+ }
+
+ if (!var58) {
+ for (var41 = var55; var41 < var35; ++var41) {
+ double var59 = ((double) (var41 + par3 * 16) + 0.5D - par6) / var54;
+
+ for (var44 = var57; var44 < var39; ++var44) {
+ double var45 = ((double) (var44 + par4 * 16) + 0.5D - par10) / var54;
+ int var47 = (var41 * 16 + var44) * 128 + var37;
+ boolean var48 = false;
+
+ if (var59 * var59 + var45 * var45 < 1.0D) {
+ for (int var49 = var37 - 1; var49 >= var56; --var49) {
+ double var50 = ((double) var49 + 0.5D - par8) / var30;
+
+ if ((var59 * var59 + var45 * var45) * (double) this.field_75046_d[var49]
+ + var50 * var50 / 6.0D < 1.0D) {
+ byte var52 = par5ArrayOfByte[var47];
+
+ if (var52 == Block.grass.blockID) {
+ var48 = true;
+ }
+
+ if (var52 == Block.stone.blockID || var52 == Block.dirt.blockID
+ || var52 == Block.grass.blockID) {
+ if (var49 < 10) {
+ par5ArrayOfByte[var47] = (byte) Block.lavaMoving.blockID;
+ } else {
+ par5ArrayOfByte[var47] = 0;
+
+ if (var48 && par5ArrayOfByte[var47 - 1] == Block.dirt.blockID) {
+ par5ArrayOfByte[var47 - 1] = this.worldObj.getBiomeGenForCoords(
+ var41 + par3 * 16, var44 + par4 * 16).topBlock;
+ }
+ }
+ }
+ }
+
+ --var47;
+ }
+ }
+ }
+ }
+
+ if (var53) {
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Recursively called by generate() (generate) and optionally by itself.
+ */
+ protected void recursiveGenerate(World par1World, int par2, int par3, int par4, int par5, byte[] par6ArrayOfByte) {
+ if (this.rand.nextInt(50) == 0) {
+ double var7 = (double) (par2 * 16 + this.rand.nextInt(16));
+ double var9 = (double) (this.rand.nextInt(this.rand.nextInt(40) + 8) + 20);
+ double var11 = (double) (par3 * 16 + this.rand.nextInt(16));
+ byte var13 = 1;
+
+ for (int var14 = 0; var14 < var13; ++var14) {
+ float var15 = this.rand.nextFloat() * (float) Math.PI * 2.0F;
+ float var16 = (this.rand.nextFloat() - 0.5F) * 2.0F / 8.0F;
+ float var17 = (this.rand.nextFloat() * 2.0F + this.rand.nextFloat()) * 2.0F;
+ this.generateRavine(this.rand.nextLong(), par4, par5, par6ArrayOfByte, var7, var9, var11, var17, var15,
+ var16, 0, 0, 3.0D);
+ }
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/MapGenScatteredFeature.java b/sp-server/src/main/java/net/minecraft/src/MapGenScatteredFeature.java
new file mode 100644
index 0000000..2842446
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/MapGenScatteredFeature.java
@@ -0,0 +1,93 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class MapGenScatteredFeature extends MapGenStructure {
+ private static List biomelist = Arrays.asList(new BiomeGenBase[] { BiomeGenBase.desert, BiomeGenBase.desertHills,
+ BiomeGenBase.jungle, BiomeGenBase.jungleHills, BiomeGenBase.swampland });
+
+ /** contains possible spawns for scattered features */
+ private List scatteredFeatureSpawnList;
+
+ /** the maximum distance between scattered features */
+ private int maxDistanceBetweenScatteredFeatures;
+
+ /** the minimum distance between scattered features */
+ private int minDistanceBetweenScatteredFeatures;
+
+ public MapGenScatteredFeature() {
+ this.scatteredFeatureSpawnList = new ArrayList();
+ this.maxDistanceBetweenScatteredFeatures = 32;
+ this.minDistanceBetweenScatteredFeatures = 8;
+ this.scatteredFeatureSpawnList.add(new SpawnListEntry((w) -> new EntityWitch(w), 1, 1, 1));
+ }
+
+ public MapGenScatteredFeature(Map par1Map) {
+ this();
+ Iterator var2 = par1Map.entrySet().iterator();
+
+ while (var2.hasNext()) {
+ Entry var3 = (Entry) var2.next();
+
+ if (((String) var3.getKey()).equals("distance")) {
+ this.maxDistanceBetweenScatteredFeatures = MathHelper.parseIntWithDefaultAndMax(
+ (String) var3.getValue(), this.maxDistanceBetweenScatteredFeatures,
+ this.minDistanceBetweenScatteredFeatures + 1);
+ }
+ }
+ }
+
+ protected boolean canSpawnStructureAtCoords(int par1, int par2) {
+ int var3 = par1;
+ int var4 = par2;
+
+ if (par1 < 0) {
+ par1 -= this.maxDistanceBetweenScatteredFeatures - 1;
+ }
+
+ if (par2 < 0) {
+ par2 -= this.maxDistanceBetweenScatteredFeatures - 1;
+ }
+
+ int var5 = par1 / this.maxDistanceBetweenScatteredFeatures;
+ int var6 = par2 / this.maxDistanceBetweenScatteredFeatures;
+ EaglercraftRandom var7 = this.worldObj.setRandomSeed(var5, var6, 14357617);
+ var5 *= this.maxDistanceBetweenScatteredFeatures;
+ var6 *= this.maxDistanceBetweenScatteredFeatures;
+ var5 += var7.nextInt(this.maxDistanceBetweenScatteredFeatures - this.minDistanceBetweenScatteredFeatures);
+ var6 += var7.nextInt(this.maxDistanceBetweenScatteredFeatures - this.minDistanceBetweenScatteredFeatures);
+
+ if (var3 == var5 && var4 == var6) {
+ BiomeGenBase var8 = this.worldObj.getWorldChunkManager().getBiomeGenAt(var3 * 16 + 8, var4 * 16 + 8);
+ Iterator var9 = biomelist.iterator();
+
+ while (var9.hasNext()) {
+ BiomeGenBase var10 = (BiomeGenBase) var9.next();
+
+ if (var8 == var10) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ protected StructureStart getStructureStart(int par1, int par2) {
+ return new StructureScatteredFeatureStart(this.worldObj, this.rand, par1, par2);
+ }
+
+ /**
+ * returns possible spawns for scattered features
+ */
+ public List getScatteredFeatureSpawnList() {
+ return this.scatteredFeatureSpawnList;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/MapGenStronghold.java b/sp-server/src/main/java/net/minecraft/src/MapGenStronghold.java
new file mode 100644
index 0000000..b379735
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/MapGenStronghold.java
@@ -0,0 +1,138 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class MapGenStronghold extends MapGenStructure {
+ private BiomeGenBase[] allowedBiomeGenBases;
+
+ /**
+ * is spawned false and set true once the defined BiomeGenBases were compared
+ * with the present ones
+ */
+ private boolean ranBiomeCheck;
+ private ChunkCoordIntPair[] structureCoords;
+ private double field_82671_h;
+ private int field_82672_i;
+
+ public MapGenStronghold() {
+ this.allowedBiomeGenBases = new BiomeGenBase[] { BiomeGenBase.desert, BiomeGenBase.forest,
+ BiomeGenBase.extremeHills, BiomeGenBase.swampland, BiomeGenBase.taiga, BiomeGenBase.icePlains,
+ BiomeGenBase.iceMountains, BiomeGenBase.desertHills, BiomeGenBase.forestHills,
+ BiomeGenBase.extremeHillsEdge, BiomeGenBase.jungle, BiomeGenBase.jungleHills };
+ this.structureCoords = new ChunkCoordIntPair[3];
+ this.field_82671_h = 32.0D;
+ this.field_82672_i = 3;
+ }
+
+ public MapGenStronghold(Map par1Map) {
+ this.allowedBiomeGenBases = new BiomeGenBase[] { BiomeGenBase.desert, BiomeGenBase.forest,
+ BiomeGenBase.extremeHills, BiomeGenBase.swampland, BiomeGenBase.taiga, BiomeGenBase.icePlains,
+ BiomeGenBase.iceMountains, BiomeGenBase.desertHills, BiomeGenBase.forestHills,
+ BiomeGenBase.extremeHillsEdge, BiomeGenBase.jungle, BiomeGenBase.jungleHills };
+ this.structureCoords = new ChunkCoordIntPair[3];
+ this.field_82671_h = 32.0D;
+ this.field_82672_i = 3;
+ Iterator var2 = par1Map.entrySet().iterator();
+
+ while (var2.hasNext()) {
+ Entry var3 = (Entry) var2.next();
+
+ if (((String) var3.getKey()).equals("distance")) {
+ this.field_82671_h = MathHelper.func_82713_a((String) var3.getValue(), this.field_82671_h, 1.0D);
+ } else if (((String) var3.getKey()).equals("count")) {
+ this.structureCoords = new ChunkCoordIntPair[MathHelper
+ .parseIntWithDefaultAndMax((String) var3.getValue(), this.structureCoords.length, 1)];
+ } else if (((String) var3.getKey()).equals("spread")) {
+ this.field_82672_i = MathHelper.parseIntWithDefaultAndMax((String) var3.getValue(), this.field_82672_i,
+ 1);
+ }
+ }
+ }
+
+ protected boolean canSpawnStructureAtCoords(int par1, int par2) {
+ if (!this.ranBiomeCheck) {
+ EaglercraftRandom var3 = new EaglercraftRandom();
+ var3.setSeed(this.worldObj.getSeed());
+ double var4 = var3.nextDouble() * Math.PI * 2.0D;
+ int var6 = 1;
+
+ for (int var7 = 0; var7 < this.structureCoords.length; ++var7) {
+ double var8 = (1.25D * (double) var6 + var3.nextDouble()) * this.field_82671_h * (double) var6;
+ int var10 = (int) Math.round(Math.cos(var4) * var8);
+ int var11 = (int) Math.round(Math.sin(var4) * var8);
+ ArrayList var12 = new ArrayList();
+ Collections.addAll(var12, this.allowedBiomeGenBases);
+ ChunkPosition var13 = this.worldObj.getWorldChunkManager().findBiomePosition((var10 << 4) + 8,
+ (var11 << 4) + 8, 112, var12, var3);
+
+ if (var13 != null) {
+ var10 = var13.x >> 4;
+ var11 = var13.z >> 4;
+ }
+
+ this.structureCoords[var7] = new ChunkCoordIntPair(var10, var11);
+ var4 += (Math.PI * 2D) * (double) var6 / (double) this.field_82672_i;
+
+ if (var7 == this.field_82672_i) {
+ var6 += 2 + var3.nextInt(5);
+ this.field_82672_i += 1 + var3.nextInt(2);
+ }
+ }
+
+ this.ranBiomeCheck = true;
+ }
+
+ ChunkCoordIntPair[] var14 = this.structureCoords;
+ int var15 = var14.length;
+
+ for (int var5 = 0; var5 < var15; ++var5) {
+ ChunkCoordIntPair var16 = var14[var5];
+
+ if (par1 == var16.chunkXPos && par2 == var16.chunkZPos) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns a list of other locations at which the structure generation has been
+ * run, or null if not relevant to this structure generator.
+ */
+ protected List getCoordList() {
+ ArrayList var1 = new ArrayList();
+ ChunkCoordIntPair[] var2 = this.structureCoords;
+ int var3 = var2.length;
+
+ for (int var4 = 0; var4 < var3; ++var4) {
+ ChunkCoordIntPair var5 = var2[var4];
+
+ if (var5 != null) {
+ var1.add(var5.getChunkPosition(64));
+ }
+ }
+
+ return var1;
+ }
+
+ protected StructureStart getStructureStart(int par1, int par2) {
+ StructureStrongholdStart var3;
+
+ for (var3 = new StructureStrongholdStart(this.worldObj, this.rand, par1, par2); var3.getComponents().isEmpty()
+ || ((ComponentStrongholdStairs2) var3.getComponents()
+ .get(0)).strongholdPortalRoom == null; var3 = new StructureStrongholdStart(this.worldObj,
+ this.rand, par1, par2)) {
+ ;
+ }
+
+ return var3;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/MapGenStructure.java b/sp-server/src/main/java/net/minecraft/src/MapGenStructure.java
new file mode 100644
index 0000000..870de0a
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/MapGenStructure.java
@@ -0,0 +1,156 @@
+package net.minecraft.src;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public abstract class MapGenStructure extends MapGenBase {
+ /**
+ * Used to store a list of all structures that have been recursively generated.
+ * Used so that during recursive generation, the structure generator can avoid
+ * generating structures that intersect ones that have already been placed.
+ */
+ protected Map structureMap = new HashMap();
+
+ /**
+ * Recursively called by generate() (generate) and optionally by itself.
+ */
+ protected void recursiveGenerate(World par1World, int par2, int par3, int par4, int par5, byte[] par6ArrayOfByte) {
+ if (!this.structureMap.containsKey(Long.valueOf(ChunkCoordIntPair.chunkXZ2Int(par2, par3)))) {
+ this.rand.nextInt();
+ if (this.canSpawnStructureAtCoords(par2, par3)) {
+ StructureStart var7 = this.getStructureStart(par2, par3);
+ this.structureMap.put(Long.valueOf(ChunkCoordIntPair.chunkXZ2Int(par2, par3)), var7);
+ }
+ }
+ }
+
+ /**
+ * Generates structures in specified chunk next to existing structures. Does
+ * *not* generate StructureStarts.
+ */
+ public boolean generateStructuresInChunk(World par1World, EaglercraftRandom par2Random, int par3, int par4) {
+ int var5 = (par3 << 4) + 8;
+ int var6 = (par4 << 4) + 8;
+ boolean var7 = false;
+ Iterator var8 = this.structureMap.values().iterator();
+
+ while (var8.hasNext()) {
+ StructureStart var9 = (StructureStart) var8.next();
+
+ if (var9.isSizeableStructure() && var9.getBoundingBox().intersectsWith(var5, var6, var5 + 15, var6 + 15)) {
+ var9.generateStructure(par1World, par2Random,
+ new StructureBoundingBox(var5, var6, var5 + 15, var6 + 15));
+ var7 = true;
+ }
+ }
+
+ return var7;
+ }
+
+ /**
+ * Returns true if the structure generator has generated a structure located at
+ * the given position tuple.
+ */
+ public boolean hasStructureAt(int par1, int par2, int par3) {
+ Iterator var4 = this.structureMap.values().iterator();
+
+ while (var4.hasNext()) {
+ StructureStart var5 = (StructureStart) var4.next();
+
+ if (var5.isSizeableStructure() && var5.getBoundingBox().intersectsWith(par1, par3, par1, par3)) {
+ Iterator var6 = var5.getComponents().iterator();
+
+ while (var6.hasNext()) {
+ StructureComponent var7 = (StructureComponent) var6.next();
+
+ if (var7.getBoundingBox().isVecInside(par1, par2, par3)) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+ public ChunkPosition getNearestInstance(World par1World, int par2, int par3, int par4) {
+ this.worldObj = par1World;
+ this.rand.setSeed(par1World.getSeed());
+ long var5 = this.rand.nextLong();
+ long var7 = this.rand.nextLong();
+ long var9 = (long) (par2 >> 4) * var5;
+ long var11 = (long) (par4 >> 4) * var7;
+ this.rand.setSeed(var9 ^ var11 ^ par1World.getSeed());
+ this.recursiveGenerate(par1World, par2 >> 4, par4 >> 4, 0, 0, (byte[]) null);
+ double var13 = Double.MAX_VALUE;
+ ChunkPosition var15 = null;
+ Iterator var16 = this.structureMap.values().iterator();
+ ChunkPosition var19;
+ int var20;
+ int var21;
+ int var22;
+ double var23;
+
+ while (var16.hasNext()) {
+ StructureStart var17 = (StructureStart) var16.next();
+
+ if (var17.isSizeableStructure()) {
+ StructureComponent var18 = (StructureComponent) var17.getComponents().get(0);
+ var19 = var18.getCenter();
+ var20 = var19.x - par2;
+ var21 = var19.y - par3;
+ var22 = var19.z - par4;
+ var23 = (double) (var20 + var20 * var21 * var21 + var22 * var22);
+
+ if (var23 < var13) {
+ var13 = var23;
+ var15 = var19;
+ }
+ }
+ }
+
+ if (var15 != null) {
+ return var15;
+ } else {
+ List var25 = this.getCoordList();
+
+ if (var25 != null) {
+ ChunkPosition var26 = null;
+ Iterator var27 = var25.iterator();
+
+ while (var27.hasNext()) {
+ var19 = (ChunkPosition) var27.next();
+ var20 = var19.x - par2;
+ var21 = var19.y - par3;
+ var22 = var19.z - par4;
+ var23 = (double) (var20 + var20 * var21 * var21 + var22 * var22);
+
+ if (var23 < var13) {
+ var13 = var23;
+ var26 = var19;
+ }
+ }
+
+ return var26;
+ } else {
+ return null;
+ }
+ }
+ }
+
+ /**
+ * Returns a list of other locations at which the structure generation has been
+ * run, or null if not relevant to this structure generator.
+ */
+ protected List getCoordList() {
+ return null;
+ }
+
+ protected abstract boolean canSpawnStructureAtCoords(int var1, int var2);
+
+ protected abstract StructureStart getStructureStart(int var1, int var2);
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/MapGenVillage.java b/sp-server/src/main/java/net/minecraft/src/MapGenVillage.java
new file mode 100644
index 0000000..35aa1e3
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/MapGenVillage.java
@@ -0,0 +1,78 @@
+package net.minecraft.src;
+
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class MapGenVillage extends MapGenStructure {
+ /** A list of all the biomes villages can spawn in. */
+ public static final List villageSpawnBiomes = Arrays
+ .asList(new BiomeGenBase[] { BiomeGenBase.plains, BiomeGenBase.desert });
+
+ /** World terrain type, 0 for normal, 1 for flat map */
+ private int terrainType;
+ private int field_82665_g;
+ private int field_82666_h;
+
+ public MapGenVillage() {
+ this.terrainType = 0;
+ this.field_82665_g = 32;
+ this.field_82666_h = 8;
+ }
+
+ public MapGenVillage(Map par1Map) {
+ this();
+ Iterator var2 = par1Map.entrySet().iterator();
+
+ while (var2.hasNext()) {
+ Entry var3 = (Entry) var2.next();
+
+ if (((String) var3.getKey()).equals("size")) {
+ this.terrainType = MathHelper.parseIntWithDefaultAndMax((String) var3.getValue(), this.terrainType, 0);
+ } else if (((String) var3.getKey()).equals("distance")) {
+ this.field_82665_g = MathHelper.parseIntWithDefaultAndMax((String) var3.getValue(), this.field_82665_g,
+ this.field_82666_h + 1);
+ }
+ }
+ }
+
+ protected boolean canSpawnStructureAtCoords(int par1, int par2) {
+ int var3 = par1;
+ int var4 = par2;
+
+ if (par1 < 0) {
+ par1 -= this.field_82665_g - 1;
+ }
+
+ if (par2 < 0) {
+ par2 -= this.field_82665_g - 1;
+ }
+
+ int var5 = par1 / this.field_82665_g;
+ int var6 = par2 / this.field_82665_g;
+ EaglercraftRandom var7 = this.worldObj.setRandomSeed(var5, var6, 10387312);
+ var5 *= this.field_82665_g;
+ var6 *= this.field_82665_g;
+ var5 += var7.nextInt(this.field_82665_g - this.field_82666_h);
+ var6 += var7.nextInt(this.field_82665_g - this.field_82666_h);
+
+ if (var3 == var5 && var4 == var6) {
+ boolean var8 = this.worldObj.getWorldChunkManager().areBiomesViable(var3 * 16 + 8, var4 * 16 + 8, 0,
+ villageSpawnBiomes);
+
+ if (var8) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ protected StructureStart getStructureStart(int par1, int par2) {
+ return new StructureVillageStart(this.worldObj, this.rand, par1, par2, this.terrainType);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/MapInfo.java b/sp-server/src/main/java/net/minecraft/src/MapInfo.java
new file mode 100644
index 0000000..b58d21f
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/MapInfo.java
@@ -0,0 +1,115 @@
+package net.minecraft.src;
+
+import java.util.Iterator;
+
+public class MapInfo {
+ /** Reference for EntityPlayer object in MapInfo */
+ public final EntityPlayer entityplayerObj;
+ public int[] field_76209_b;
+ public int[] field_76210_c;
+
+ /**
+ * updated by x = mod(x*11,128) +1 x-1 is used to index field_76209_b and
+ * field_76210_c
+ */
+ private int currentRandomNumber;
+ private int ticksUntilPlayerLocationMapUpdate;
+
+ /**
+ * a cache of the result from getPlayersOnMap so that it is not resent when
+ * nothing changes
+ */
+ private byte[] lastPlayerLocationOnMap;
+ public int field_82569_d;
+ private boolean field_82570_i;
+
+ /** reference in MapInfo to MapData object */
+ final MapData mapDataObj;
+
+ public MapInfo(MapData par1MapData, EntityPlayer par2EntityPlayer) {
+ this.mapDataObj = par1MapData;
+ this.field_76209_b = new int[128];
+ this.field_76210_c = new int[128];
+ this.currentRandomNumber = 0;
+ this.ticksUntilPlayerLocationMapUpdate = 0;
+ this.field_82570_i = false;
+ this.entityplayerObj = par2EntityPlayer;
+
+ for (int var3 = 0; var3 < this.field_76209_b.length; ++var3) {
+ this.field_76209_b[var3] = 0;
+ this.field_76210_c[var3] = 127;
+ }
+ }
+
+ /**
+ * returns a 1+players*3 array, of x,y, and color . the name of this function
+ * may be partially wrong, as there is a second branch to the code here
+ */
+ public byte[] getPlayersOnMap(ItemStack par1ItemStack) {
+ byte[] var2;
+
+ if (!this.field_82570_i) {
+ var2 = new byte[] { (byte) 2, this.mapDataObj.scale };
+ this.field_82570_i = true;
+ return var2;
+ } else {
+ int var3;
+ int var10;
+
+ if (--this.ticksUntilPlayerLocationMapUpdate < 0) {
+ this.ticksUntilPlayerLocationMapUpdate = 4;
+ var2 = new byte[this.mapDataObj.playersVisibleOnMap.size() * 3 + 1];
+ var2[0] = 1;
+ var3 = 0;
+
+ for (Iterator var4 = this.mapDataObj.playersVisibleOnMap.values().iterator(); var4.hasNext(); ++var3) {
+ MapCoord var5 = (MapCoord) var4.next();
+ var2[var3 * 3 + 1] = (byte) (var5.iconSize << 4 | var5.iconRotation & 15);
+ var2[var3 * 3 + 2] = var5.centerX;
+ var2[var3 * 3 + 3] = var5.centerZ;
+ }
+
+ boolean var9 = !par1ItemStack.isOnItemFrame();
+
+ if (this.lastPlayerLocationOnMap != null && this.lastPlayerLocationOnMap.length == var2.length) {
+ for (var10 = 0; var10 < var2.length; ++var10) {
+ if (var2[var10] != this.lastPlayerLocationOnMap[var10]) {
+ var9 = false;
+ break;
+ }
+ }
+ } else {
+ var9 = false;
+ }
+
+ if (!var9) {
+ this.lastPlayerLocationOnMap = var2;
+ return var2;
+ }
+ }
+
+ for (int var8 = 0; var8 < 1; ++var8) {
+ var3 = this.currentRandomNumber++ * 11 % 128;
+
+ if (this.field_76209_b[var3] >= 0) {
+ int var11 = this.field_76210_c[var3] - this.field_76209_b[var3] + 1;
+ var10 = this.field_76209_b[var3];
+ byte[] var6 = new byte[var11 + 3];
+ var6[0] = 0;
+ var6[1] = (byte) var3;
+ var6[2] = (byte) var10;
+
+ for (int var7 = 0; var7 < var6.length - 3; ++var7) {
+ var6[var7 + 3] = this.mapDataObj.colors[(var7 + var10) * 128 + var3];
+ }
+
+ this.field_76210_c[var3] = -1;
+ this.field_76209_b[var3] = -1;
+ return var6;
+ }
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/MapStorage.java b/sp-server/src/main/java/net/minecraft/src/MapStorage.java
new file mode 100644
index 0000000..ad891df
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/MapStorage.java
@@ -0,0 +1,206 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+
+import net.lax1dude.eaglercraft.sp.VFile;
+
+public class MapStorage {
+ private ISaveHandler saveHandler;
+
+ /** Map of item data String id to loaded MapDataBases */
+ private Map loadedDataMap = new HashMap();
+
+ /** List of loaded MapDataBases. */
+ private List loadedDataList = new ArrayList();
+
+ /**
+ * Map of MapDataBase id String prefixes ('map' etc) to max known unique Short
+ * id (the 0 part etc) for that prefix
+ */
+ private Map idCounts = new HashMap();
+
+ public MapStorage(ISaveHandler par1ISaveHandler) {
+ this.saveHandler = par1ISaveHandler;
+ this.loadIdCounts();
+ }
+
+ /**
+ * Loads an existing MapDataBase corresponding to the given String id from disk,
+ * instantiating the given Class, or returns null if none such file exists.
+ * args: Class to instantiate, String dataid
+ */
+ public WorldSavedData loadData(Function par1Class, String par2Str) {
+ WorldSavedData var3 = (WorldSavedData) this.loadedDataMap.get(par2Str);
+
+ if (var3 != null) {
+ return var3;
+ } else {
+ if (this.saveHandler != null) {
+ try {
+ VFile var4 = this.saveHandler.getMapFileFromName(par2Str);
+
+ if (var4 != null && var4.exists()) {
+ try {
+ var3 = (WorldSavedData) par1Class.apply(par2Str);
+ } catch (Exception var7) {
+ throw new RuntimeException("Failed to instantiate " + par1Class.toString(), var7);
+ }
+
+ NBTTagCompound var6 = CompressedStreamTools.readCompressed(var4.getInputStream());
+ var3.readFromNBT(var6.getCompoundTag("data"));
+ }
+ } catch (Exception var8) {
+ var8.printStackTrace();
+ }
+ }
+
+ if (var3 != null) {
+ this.loadedDataMap.put(par2Str, var3);
+ this.loadedDataList.add(var3);
+ }
+
+ return var3;
+ }
+ }
+
+ /**
+ * Assigns the given String id to the given MapDataBase, removing any existing
+ * ones of the same id.
+ */
+ public void setData(String par1Str, WorldSavedData par2WorldSavedData) {
+ if (par2WorldSavedData == null) {
+ throw new RuntimeException("Can\'t set null data");
+ } else {
+ if (this.loadedDataMap.containsKey(par1Str)) {
+ this.loadedDataList.remove(this.loadedDataMap.remove(par1Str));
+ }
+
+ this.loadedDataMap.put(par1Str, par2WorldSavedData);
+ this.loadedDataList.add(par2WorldSavedData);
+ }
+ }
+
+ /**
+ * Saves all dirty loaded MapDataBases to disk.
+ */
+ public void saveAllData() {
+ for (int var1 = 0; var1 < this.loadedDataList.size(); ++var1) {
+ WorldSavedData var2 = (WorldSavedData) this.loadedDataList.get(var1);
+
+ if (var2.isDirty()) {
+ this.saveData(var2);
+ var2.setDirty(false);
+ }
+ }
+ }
+
+ /**
+ * Saves the given MapDataBase to disk.
+ */
+ private void saveData(WorldSavedData par1WorldSavedData) {
+ if (this.saveHandler != null) {
+ try {
+ VFile var2 = this.saveHandler.getMapFileFromName(par1WorldSavedData.mapName);
+
+ if (var2 != null) {
+ NBTTagCompound var3 = new NBTTagCompound();
+ par1WorldSavedData.writeToNBT(var3);
+ NBTTagCompound var4 = new NBTTagCompound();
+ var4.setCompoundTag("data", var3);
+ OutputStream st = var2.getOutputStream();
+ CompressedStreamTools.writeCompressed(var4, st);
+ st.close();
+ }
+ } catch (Exception var6) {
+ var6.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * Loads the idCounts Map from the 'idcounts' file.
+ */
+ private void loadIdCounts() {
+ try {
+ this.idCounts.clear();
+
+ if (this.saveHandler == null) {
+ return;
+ }
+
+ VFile var1 = this.saveHandler.getMapFileFromName("idcounts");
+
+ if (var1 != null && var1.exists()) {
+ DataInputStream var2 = new DataInputStream(var1.getInputStream());
+ NBTTagCompound var3 = CompressedStreamTools.read(var2);
+ var2.close();
+ Iterator var4 = var3.getTags().iterator();
+
+ while (var4.hasNext()) {
+ NBTBase var5 = (NBTBase) var4.next();
+
+ if (var5 instanceof NBTTagShort) {
+ NBTTagShort var6 = (NBTTagShort) var5;
+ String var7 = var6.getName();
+ short var8 = var6.data;
+ this.idCounts.put(var7, Short.valueOf(var8));
+ }
+ }
+ }
+ } catch (Exception var9) {
+ var9.printStackTrace();
+ }
+ }
+
+ /**
+ * Returns an unique new data id for the given prefix and saves the idCounts map
+ * to the 'idcounts' file.
+ */
+ public int getUniqueDataId(String par1Str) {
+ Short var2 = (Short) this.idCounts.get(par1Str);
+
+ if (var2 == null) {
+ var2 = Short.valueOf((short) 0);
+ } else {
+ var2 = Short.valueOf((short) (var2.shortValue() + 1));
+ }
+
+ this.idCounts.put(par1Str, var2);
+
+ if (this.saveHandler == null) {
+ return var2.shortValue();
+ } else {
+ try {
+ VFile var3 = this.saveHandler.getMapFileFromName("idcounts");
+
+ if (var3 != null) {
+ NBTTagCompound var4 = new NBTTagCompound();
+ Iterator var5 = this.idCounts.keySet().iterator();
+
+ while (var5.hasNext()) {
+ String var6 = (String) var5.next();
+ short var7 = ((Short) this.idCounts.get(var6)).shortValue();
+ var4.setShort(var6, var7);
+ }
+
+ OutputStream os = var3.getOutputStream();
+ DataOutputStream var9 = new DataOutputStream(os);
+ CompressedStreamTools.write(var4, var9);
+ os.close();
+ }
+ } catch (Exception var8) {
+ var8.printStackTrace();
+ }
+
+ return var2.shortValue();
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Material.java b/sp-server/src/main/java/net/minecraft/src/Material.java
new file mode 100644
index 0000000..65b938c
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Material.java
@@ -0,0 +1,212 @@
+package net.minecraft.src;
+
+public class Material {
+ public static final Material air = new MaterialTransparent(MapColor.airColor);
+
+ /** The material used by BlockGrass. */
+ public static final Material grass = new Material(MapColor.grassColor);
+ public static final Material ground = new Material(MapColor.dirtColor);
+ public static final Material wood = (new Material(MapColor.woodColor)).setBurning();
+ public static final Material rock = (new Material(MapColor.stoneColor)).setRequiresTool();
+ public static final Material iron = (new Material(MapColor.ironColor)).setRequiresTool();
+ public static final Material anvil = (new Material(MapColor.ironColor)).setRequiresTool().setImmovableMobility();
+ public static final Material water = (new MaterialLiquid(MapColor.waterColor)).setNoPushMobility();
+ public static final Material lava = (new MaterialLiquid(MapColor.tntColor)).setNoPushMobility();
+ public static final Material leaves = (new Material(MapColor.foliageColor)).setBurning().setTranslucent()
+ .setNoPushMobility();
+ public static final Material plants = (new MaterialLogic(MapColor.foliageColor)).setNoPushMobility();
+ public static final Material vine = (new MaterialLogic(MapColor.foliageColor)).setBurning().setNoPushMobility()
+ .setReplaceable();
+ public static final Material sponge = new Material(MapColor.clothColor);
+ public static final Material cloth = (new Material(MapColor.clothColor)).setBurning();
+ public static final Material fire = (new MaterialTransparent(MapColor.airColor)).setNoPushMobility();
+ public static final Material sand = new Material(MapColor.sandColor);
+ public static final Material circuits = (new MaterialLogic(MapColor.airColor)).setNoPushMobility();
+ public static final Material glass = (new Material(MapColor.airColor)).setTranslucent().setAlwaysHarvested();
+ public static final Material redstoneLight = (new Material(MapColor.airColor)).setAlwaysHarvested();
+ public static final Material tnt = (new Material(MapColor.tntColor)).setBurning().setTranslucent();
+ public static final Material coral = (new Material(MapColor.foliageColor)).setNoPushMobility();
+ public static final Material ice = (new Material(MapColor.iceColor)).setTranslucent().setAlwaysHarvested();
+ public static final Material snow = (new MaterialLogic(MapColor.snowColor)).setReplaceable().setTranslucent()
+ .setRequiresTool().setNoPushMobility();
+
+ /** The material for crafted snow. */
+ public static final Material craftedSnow = (new Material(MapColor.snowColor)).setRequiresTool();
+ public static final Material cactus = (new Material(MapColor.foliageColor)).setTranslucent().setNoPushMobility();
+ public static final Material clay = new Material(MapColor.clayColor);
+
+ /** pumpkin */
+ public static final Material pumpkin = (new Material(MapColor.foliageColor)).setNoPushMobility();
+ public static final Material dragonEgg = (new Material(MapColor.foliageColor)).setNoPushMobility();
+
+ /** Material used for portals */
+ public static final Material portal = (new MaterialPortal(MapColor.airColor)).setImmovableMobility();
+
+ /** Cake's material, see BlockCake */
+ public static final Material cake = (new Material(MapColor.airColor)).setNoPushMobility();
+
+ /** Web's material. */
+ public static final Material web = (new MaterialWeb(MapColor.clothColor)).setRequiresTool().setNoPushMobility();
+
+ /** Pistons' material. */
+ public static final Material piston = (new Material(MapColor.stoneColor)).setImmovableMobility();
+
+ /** Bool defining if the block can burn or not. */
+ private boolean canBurn;
+
+ /**
+ * Determines whether blocks with this material can be "overwritten" by other
+ * blocks when placed - eg snow, vines and tall grass.
+ */
+ private boolean replaceable;
+
+ /** Indicates if the material is translucent */
+ private boolean isTranslucent;
+
+ /** The color index used to draw the blocks of this material on maps. */
+ public final MapColor materialMapColor;
+
+ /**
+ * Determines if the material can be harvested without a tool (or with the wrong
+ * tool)
+ */
+ private boolean requiresNoTool = true;
+
+ /**
+ * Mobility information flag. 0 indicates that this block is normal, 1 indicates
+ * that it can't push other blocks, 2 indicates that it can't be pushed.
+ */
+ private int mobilityFlag;
+ private boolean field_85159_M;
+
+ public Material(MapColor par1MapColor) {
+ this.materialMapColor = par1MapColor;
+ }
+
+ /**
+ * Returns if blocks of these materials are liquids.
+ */
+ public boolean isLiquid() {
+ return false;
+ }
+
+ public boolean isSolid() {
+ return true;
+ }
+
+ /**
+ * Will prevent grass from growing on dirt underneath and kill any grass below
+ * it if it returns true
+ */
+ public boolean getCanBlockGrass() {
+ return true;
+ }
+
+ /**
+ * Returns if this material is considered solid or not
+ */
+ public boolean blocksMovement() {
+ return true;
+ }
+
+ /**
+ * Marks the material as translucent
+ */
+ private Material setTranslucent() {
+ this.isTranslucent = true;
+ return this;
+ }
+
+ /**
+ * Makes blocks with this material require the correct tool to be harvested.
+ */
+ protected Material setRequiresTool() {
+ this.requiresNoTool = false;
+ return this;
+ }
+
+ /**
+ * Set the canBurn bool to True and return the current object.
+ */
+ protected Material setBurning() {
+ this.canBurn = true;
+ return this;
+ }
+
+ /**
+ * Returns if the block can burn or not.
+ */
+ public boolean getCanBurn() {
+ return this.canBurn;
+ }
+
+ /**
+ * Sets {@link #replaceable} to true.
+ */
+ public Material setReplaceable() {
+ this.replaceable = true;
+ return this;
+ }
+
+ /**
+ * Returns whether the material can be replaced by other blocks when placed - eg
+ * snow, vines and tall grass.
+ */
+ public boolean isReplaceable() {
+ return this.replaceable;
+ }
+
+ /**
+ * Indicate if the material is opaque
+ */
+ public boolean isOpaque() {
+ return this.isTranslucent ? false : this.blocksMovement();
+ }
+
+ /**
+ * Returns true if the material can be harvested without a tool (or with the
+ * wrong tool)
+ */
+ public boolean isToolNotRequired() {
+ return this.requiresNoTool;
+ }
+
+ /**
+ * Returns the mobility information of the material, 0 = free, 1 = can't push
+ * but can move over, 2 = total immobility and stop pistons.
+ */
+ public int getMaterialMobility() {
+ return this.mobilityFlag;
+ }
+
+ /**
+ * This type of material can't be pushed, but pistons can move over it.
+ */
+ protected Material setNoPushMobility() {
+ this.mobilityFlag = 1;
+ return this;
+ }
+
+ /**
+ * This type of material can't be pushed, and pistons are blocked to move.
+ */
+ protected Material setImmovableMobility() {
+ this.mobilityFlag = 2;
+ return this;
+ }
+
+ /**
+ * Set as harvestable in any case.
+ */
+ protected Material setAlwaysHarvested() {
+ this.field_85159_M = true;
+ return this;
+ }
+
+ /**
+ * Check to see if we can harvest it in any case.
+ */
+ public boolean isAlwaysHarvested() {
+ return this.field_85159_M;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/MaterialLiquid.java b/sp-server/src/main/java/net/minecraft/src/MaterialLiquid.java
new file mode 100644
index 0000000..5d2fbd3
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/MaterialLiquid.java
@@ -0,0 +1,27 @@
+package net.minecraft.src;
+
+public class MaterialLiquid extends Material {
+ public MaterialLiquid(MapColor par1MapColor) {
+ super(par1MapColor);
+ this.setReplaceable();
+ this.setNoPushMobility();
+ }
+
+ /**
+ * Returns if blocks of these materials are liquids.
+ */
+ public boolean isLiquid() {
+ return true;
+ }
+
+ /**
+ * Returns if this material is considered solid or not
+ */
+ public boolean blocksMovement() {
+ return false;
+ }
+
+ public boolean isSolid() {
+ return false;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/MaterialLogic.java b/sp-server/src/main/java/net/minecraft/src/MaterialLogic.java
new file mode 100644
index 0000000..eb91420
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/MaterialLogic.java
@@ -0,0 +1,27 @@
+package net.minecraft.src;
+
+public class MaterialLogic extends Material {
+ public MaterialLogic(MapColor par1MapColor) {
+ super(par1MapColor);
+ this.setAlwaysHarvested();
+ }
+
+ public boolean isSolid() {
+ return false;
+ }
+
+ /**
+ * Will prevent grass from growing on dirt underneath and kill any grass below
+ * it if it returns true
+ */
+ public boolean getCanBlockGrass() {
+ return false;
+ }
+
+ /**
+ * Returns if this material is considered solid or not
+ */
+ public boolean blocksMovement() {
+ return false;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/MaterialPortal.java b/sp-server/src/main/java/net/minecraft/src/MaterialPortal.java
new file mode 100644
index 0000000..38e335c
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/MaterialPortal.java
@@ -0,0 +1,26 @@
+package net.minecraft.src;
+
+public class MaterialPortal extends Material {
+ public MaterialPortal(MapColor par1MapColor) {
+ super(par1MapColor);
+ }
+
+ public boolean isSolid() {
+ return false;
+ }
+
+ /**
+ * Will prevent grass from growing on dirt underneath and kill any grass below
+ * it if it returns true
+ */
+ public boolean getCanBlockGrass() {
+ return false;
+ }
+
+ /**
+ * Returns if this material is considered solid or not
+ */
+ public boolean blocksMovement() {
+ return false;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/MaterialTransparent.java b/sp-server/src/main/java/net/minecraft/src/MaterialTransparent.java
new file mode 100644
index 0000000..8ff5995
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/MaterialTransparent.java
@@ -0,0 +1,27 @@
+package net.minecraft.src;
+
+public class MaterialTransparent extends Material {
+ public MaterialTransparent(MapColor par1MapColor) {
+ super(par1MapColor);
+ this.setReplaceable();
+ }
+
+ public boolean isSolid() {
+ return false;
+ }
+
+ /**
+ * Will prevent grass from growing on dirt underneath and kill any grass below
+ * it if it returns true
+ */
+ public boolean getCanBlockGrass() {
+ return false;
+ }
+
+ /**
+ * Returns if this material is considered solid or not
+ */
+ public boolean blocksMovement() {
+ return false;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/MaterialWeb.java b/sp-server/src/main/java/net/minecraft/src/MaterialWeb.java
new file mode 100644
index 0000000..4b1b6d0
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/MaterialWeb.java
@@ -0,0 +1,14 @@
+package net.minecraft.src;
+
+final class MaterialWeb extends Material {
+ MaterialWeb(MapColor par1MapColor) {
+ super(par1MapColor);
+ }
+
+ /**
+ * Returns if this material is considered solid or not
+ */
+ public boolean blocksMovement() {
+ return false;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/MathHelper.java b/sp-server/src/main/java/net/minecraft/src/MathHelper.java
new file mode 100644
index 0000000..89b074b
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/MathHelper.java
@@ -0,0 +1,230 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class MathHelper {
+ /**
+ * A table of sin values computed from 0 (inclusive) to 2*pi (exclusive), with
+ * steps of 2*PI / 65536.
+ */
+ private static float[] SIN_TABLE = new float[65536];
+
+ /**
+ * sin looked up in a table
+ */
+ public static final float sin(float par0) {
+ return SIN_TABLE[(int) (par0 * 10430.378F) & 65535];
+ }
+
+ /**
+ * cos looked up in the sin table with the appropriate offset
+ */
+ public static final float cos(float par0) {
+ return SIN_TABLE[(int) (par0 * 10430.378F + 16384.0F) & 65535];
+ }
+
+ public static final float sqrt_float(float par0) {
+ return (float) Math.sqrt((double) par0);
+ }
+
+ public static final float sqrt_double(double par0) {
+ return (float) Math.sqrt(par0);
+ }
+
+ /**
+ * Returns the greatest integer less than or equal to the float argument
+ */
+ public static int floor_float(float par0) {
+ int var1 = (int) par0;
+ return par0 < (float) var1 ? var1 - 1 : var1;
+ }
+
+ /**
+ * Returns the greatest integer less than or equal to the double argument
+ */
+ public static int floor_double(double par0) {
+ int var2 = (int) par0;
+ return par0 < (double) var2 ? var2 - 1 : var2;
+ }
+
+ /**
+ * Long version of floor_double
+ */
+ public static long floor_double_long(double par0) {
+ long var2 = (long) par0;
+ return par0 < (double) var2 ? var2 - 1L : var2;
+ }
+
+ public static float abs(float par0) {
+ return par0 >= 0.0F ? par0 : -par0;
+ }
+
+ /**
+ * Returns the unsigned value of an int.
+ */
+ public static int abs_int(int par0) {
+ return par0 >= 0 ? par0 : -par0;
+ }
+
+ public static int ceiling_float_int(float par0) {
+ int var1 = (int) par0;
+ return par0 > (float) var1 ? var1 + 1 : var1;
+ }
+
+ public static int ceiling_double_int(double par0) {
+ int var2 = (int) par0;
+ return par0 > (double) var2 ? var2 + 1 : var2;
+ }
+
+ /**
+ * Returns the value of the first parameter, clamped to be within the lower and
+ * upper limits given by the second and third parameters.
+ */
+ public static int clamp_int(int par0, int par1, int par2) {
+ return par0 < par1 ? par1 : (par0 > par2 ? par2 : par0);
+ }
+
+ /**
+ * Maximum of the absolute value of two numbers.
+ */
+ public static double abs_max(double par0, double par2) {
+ if (par0 < 0.0D) {
+ par0 = -par0;
+ }
+
+ if (par2 < 0.0D) {
+ par2 = -par2;
+ }
+
+ return par0 > par2 ? par0 : par2;
+ }
+
+ public static int getRandomIntegerInRange(EaglercraftRandom par0Random, int par1, int par2) {
+ return par1 >= par2 ? par1 : par0Random.nextInt(par2 - par1 + 1) + par1;
+ }
+
+ public static double getRandomDoubleInRange(EaglercraftRandom par0Random, double par1, double par3) {
+ return par1 >= par3 ? par1 : par0Random.nextDouble() * (par3 - par1) + par1;
+ }
+
+ public static double average(long[] par0ArrayOfLong) {
+ long var1 = 0L;
+ long[] var3 = par0ArrayOfLong;
+ int var4 = par0ArrayOfLong.length;
+
+ for (int var5 = 0; var5 < var4; ++var5) {
+ long var6 = var3[var5];
+ var1 += var6;
+ }
+
+ return (double) var1 / (double) par0ArrayOfLong.length;
+ }
+
+ /**
+ * the angle is reduced to an angle between -180 and +180 by mod, and a 360
+ * check
+ */
+ public static float wrapAngleTo180_float(float par0) {
+ par0 %= 360.0F;
+
+ if (par0 >= 180.0F) {
+ par0 -= 360.0F;
+ }
+
+ if (par0 < -180.0F) {
+ par0 += 360.0F;
+ }
+
+ return par0;
+ }
+
+ /**
+ * the angle is reduced to an angle between -180 and +180 by mod, and a 360
+ * check
+ */
+ public static double wrapAngleTo180_double(double par0) {
+ par0 %= 360.0D;
+
+ if (par0 >= 180.0D) {
+ par0 -= 360.0D;
+ }
+
+ if (par0 < -180.0D) {
+ par0 += 360.0D;
+ }
+
+ return par0;
+ }
+
+ /**
+ * parses the string as integer or returns the second parameter if it fails
+ */
+ public static int parseIntWithDefault(String par0Str, int par1) {
+ int var2 = par1;
+
+ try {
+ var2 = Integer.parseInt(par0Str);
+ } catch (Throwable var4) {
+ ;
+ }
+
+ return var2;
+ }
+
+ /**
+ * parses the string as integer or returns the second parameter if it fails.
+ * this value is capped to par2
+ */
+ public static int parseIntWithDefaultAndMax(String par0Str, int par1, int par2) {
+ int var3 = par1;
+
+ try {
+ var3 = Integer.parseInt(par0Str);
+ } catch (Throwable var5) {
+ ;
+ }
+
+ if (var3 < par2) {
+ var3 = par2;
+ }
+
+ return var3;
+ }
+
+ /**
+ * parses the string as double or returns the second parameter if it fails.
+ */
+ public static double parseDoubleWithDefault(String par0Str, double par1) {
+ double var3 = par1;
+
+ try {
+ var3 = Double.parseDouble(par0Str);
+ } catch (Throwable var6) {
+ ;
+ }
+
+ return var3;
+ }
+
+ public static double func_82713_a(String par0Str, double par1, double par3) {
+ double var5 = par1;
+
+ try {
+ var5 = Double.parseDouble(par0Str);
+ } catch (Throwable var8) {
+ ;
+ }
+
+ if (var5 < par3) {
+ var5 = par3;
+ }
+
+ return var5;
+ }
+
+ static {
+ for (int var0 = 0; var0 < 65536; ++var0) {
+ SIN_TABLE[var0] = (float) Math.sin((double) var0 * Math.PI * 2.0D / 65536.0D);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/MemoryConnection.java b/sp-server/src/main/java/net/minecraft/src/MemoryConnection.java
new file mode 100644
index 0000000..b26ed18
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/MemoryConnection.java
@@ -0,0 +1,113 @@
+package net.minecraft.src;
+
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class MemoryConnection implements INetworkManager {
+ private static final SocketAddress mySocketAddress = new InetSocketAddress("127.0.0.1", 0);
+ private final List readPacketCache = Collections.synchronizedList(new ArrayList());
+ private final ILogAgent field_98214_c;
+ private MemoryConnection pairedConnection;
+ private NetHandler myNetHandler;
+
+ /** set to true by {server,network}Shutdown */
+ private boolean shuttingDown;
+ private String shutdownReason;
+ private Object[] field_74439_g;
+
+ public MemoryConnection(ILogAgent par1ILogAgent, NetHandler par2NetHandler) {
+ this.myNetHandler = par2NetHandler;
+ this.field_98214_c = par1ILogAgent;
+ }
+
+ /**
+ * Sets the NetHandler for this NetworkManager. Server-only.
+ */
+ public void setNetHandler(NetHandler par1NetHandler) {
+ this.myNetHandler = par1NetHandler;
+ }
+
+ /**
+ * Adds the packet to the correct send queue (chunk data packets go to a
+ * separate queue).
+ */
+ public void addToSendQueue(Packet par1Packet) {
+ if (!this.shuttingDown) {
+ this.pairedConnection.processOrCachePacket(par1Packet);
+ }
+ }
+
+ /**
+ * Wakes reader and writer threads
+ */
+ public void wakeThreads() {
+ }
+
+ /**
+ * Checks timeouts and processes all pending read packets.
+ */
+ public void processReadPackets() {
+ int var1 = 2500;
+
+ while (var1-- >= 0 && !this.readPacketCache.isEmpty()) {
+ Packet var2 = (Packet) this.readPacketCache.remove(0);
+ var2.processPacket(this.myNetHandler);
+ }
+
+ if (this.readPacketCache.size() > var1) {
+ this.field_98214_c
+ .func_98236_b("Memory connection overburdened; after processing 2500 packets, we still have "
+ + this.readPacketCache.size() + " to go!");
+ }
+
+ if (this.shuttingDown && this.readPacketCache.isEmpty()) {
+ this.myNetHandler.handleErrorMessage(this.shutdownReason, this.field_74439_g);
+ }
+ }
+
+ /**
+ * Returns the socket address of the remote side. Server-only.
+ */
+ public SocketAddress getRemoteAddress() {
+ return mySocketAddress;
+ }
+
+ /**
+ * Shuts down the server. (Only actually used on the server)
+ */
+ public void serverShutdown() {
+ this.shuttingDown = true;
+ }
+
+ /**
+ * Shuts down the network with the specified reason. Closes all streams and
+ * sockets, spawns NetworkMasterThread to stop reading and writing threads.
+ */
+ public void networkShutdown(String par1Str, Object... par2ArrayOfObj) {
+ this.shuttingDown = true;
+ this.shutdownReason = par1Str;
+ this.field_74439_g = par2ArrayOfObj;
+ }
+
+ /**
+ * Returns the number of chunk data packets waiting to be sent.
+ */
+ public int getNumChunkDataPackets() {
+ return 0;
+ }
+
+ /**
+ * acts immiditally if isWritePacket, otherwise adds it to the readCache to be
+ * processed next tick
+ */
+ public void processOrCachePacket(Packet par1Packet) {
+ if (par1Packet.canProcessAsync() && this.myNetHandler.canProcessPacketsAsync()) {
+ par1Packet.processPacket(this.myNetHandler);
+ } else {
+ this.readPacketCache.add(par1Packet);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/MerchantRecipe.java b/sp-server/src/main/java/net/minecraft/src/MerchantRecipe.java
new file mode 100644
index 0000000..998e985
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/MerchantRecipe.java
@@ -0,0 +1,135 @@
+package net.minecraft.src;
+
+public class MerchantRecipe {
+ /** Item the Villager buys. */
+ private ItemStack itemToBuy;
+
+ /** Second Item the Villager buys. */
+ private ItemStack secondItemToBuy;
+
+ /** Item the Villager sells. */
+ private ItemStack itemToSell;
+
+ /**
+ * Saves how much has been tool used when put into to slot to be enchanted.
+ */
+ private int toolUses;
+
+ /** Maximum times this trade can be used. */
+ private int maxTradeUses;
+
+ public MerchantRecipe(NBTTagCompound par1NBTTagCompound) {
+ this.readFromTags(par1NBTTagCompound);
+ }
+
+ public MerchantRecipe(ItemStack par1ItemStack, ItemStack par2ItemStack, ItemStack par3ItemStack) {
+ this.itemToBuy = par1ItemStack;
+ this.secondItemToBuy = par2ItemStack;
+ this.itemToSell = par3ItemStack;
+ this.maxTradeUses = 7;
+ }
+
+ public MerchantRecipe(ItemStack par1ItemStack, ItemStack par2ItemStack) {
+ this(par1ItemStack, (ItemStack) null, par2ItemStack);
+ }
+
+ public MerchantRecipe(ItemStack par1ItemStack, Item par2Item) {
+ this(par1ItemStack, new ItemStack(par2Item));
+ }
+
+ /**
+ * Gets the itemToBuy.
+ */
+ public ItemStack getItemToBuy() {
+ return this.itemToBuy;
+ }
+
+ /**
+ * Gets secondItemToBuy.
+ */
+ public ItemStack getSecondItemToBuy() {
+ return this.secondItemToBuy;
+ }
+
+ /**
+ * Gets if Villager has secondItemToBuy.
+ */
+ public boolean hasSecondItemToBuy() {
+ return this.secondItemToBuy != null;
+ }
+
+ /**
+ * Gets itemToSell.
+ */
+ public ItemStack getItemToSell() {
+ return this.itemToSell;
+ }
+
+ /**
+ * checks if both the first and second ItemToBuy IDs are the same
+ */
+ public boolean hasSameIDsAs(MerchantRecipe par1MerchantRecipe) {
+ return this.itemToBuy.itemID == par1MerchantRecipe.itemToBuy.itemID
+ && this.itemToSell.itemID == par1MerchantRecipe.itemToSell.itemID
+ ? this.secondItemToBuy == null && par1MerchantRecipe.secondItemToBuy == null
+ || this.secondItemToBuy != null && par1MerchantRecipe.secondItemToBuy != null
+ && this.secondItemToBuy.itemID == par1MerchantRecipe.secondItemToBuy.itemID
+ : false;
+ }
+
+ /**
+ * checks first and second ItemToBuy ID's and count. Calls hasSameIDs
+ */
+ public boolean hasSameItemsAs(MerchantRecipe par1MerchantRecipe) {
+ return this.hasSameIDsAs(par1MerchantRecipe)
+ && (this.itemToBuy.stackSize < par1MerchantRecipe.itemToBuy.stackSize || this.secondItemToBuy != null
+ && this.secondItemToBuy.stackSize < par1MerchantRecipe.secondItemToBuy.stackSize);
+ }
+
+ public void incrementToolUses() {
+ ++this.toolUses;
+ }
+
+ public void func_82783_a(int par1) {
+ this.maxTradeUses += par1;
+ }
+
+ public boolean func_82784_g() {
+ return this.toolUses >= this.maxTradeUses;
+ }
+
+ public void readFromTags(NBTTagCompound par1NBTTagCompound) {
+ NBTTagCompound var2 = par1NBTTagCompound.getCompoundTag("buy");
+ this.itemToBuy = ItemStack.loadItemStackFromNBT(var2);
+ NBTTagCompound var3 = par1NBTTagCompound.getCompoundTag("sell");
+ this.itemToSell = ItemStack.loadItemStackFromNBT(var3);
+
+ if (par1NBTTagCompound.hasKey("buyB")) {
+ this.secondItemToBuy = ItemStack.loadItemStackFromNBT(par1NBTTagCompound.getCompoundTag("buyB"));
+ }
+
+ if (par1NBTTagCompound.hasKey("uses")) {
+ this.toolUses = par1NBTTagCompound.getInteger("uses");
+ }
+
+ if (par1NBTTagCompound.hasKey("maxUses")) {
+ this.maxTradeUses = par1NBTTagCompound.getInteger("maxUses");
+ } else {
+ this.maxTradeUses = 7;
+ }
+ }
+
+ public NBTTagCompound writeToTags() {
+ NBTTagCompound var1 = new NBTTagCompound();
+ var1.setCompoundTag("buy", this.itemToBuy.writeToNBT(new NBTTagCompound("buy")));
+ var1.setCompoundTag("sell", this.itemToSell.writeToNBT(new NBTTagCompound("sell")));
+
+ if (this.secondItemToBuy != null) {
+ var1.setCompoundTag("buyB", this.secondItemToBuy.writeToNBT(new NBTTagCompound("buyB")));
+ }
+
+ var1.setInteger("uses", this.toolUses);
+ var1.setInteger("maxUses", this.maxTradeUses);
+ return var1;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/MerchantRecipeList.java b/sp-server/src/main/java/net/minecraft/src/MerchantRecipeList.java
new file mode 100644
index 0000000..a48e8aa
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/MerchantRecipeList.java
@@ -0,0 +1,104 @@
+package net.minecraft.src;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+
+public class MerchantRecipeList extends ArrayList {
+ public MerchantRecipeList() {
+ }
+
+ public MerchantRecipeList(NBTTagCompound par1NBTTagCompound) {
+ this.readRecipiesFromTags(par1NBTTagCompound);
+ }
+
+ /**
+ * can par1,par2 be used to in crafting recipe par3
+ */
+ public MerchantRecipe canRecipeBeUsed(ItemStack par1ItemStack, ItemStack par2ItemStack, int par3) {
+ if (par3 > 0 && par3 < this.size()) {
+ MerchantRecipe var6 = (MerchantRecipe) this.get(par3);
+ return par1ItemStack.itemID == var6.getItemToBuy().itemID
+ && (par2ItemStack == null && !var6.hasSecondItemToBuy() || var6.hasSecondItemToBuy()
+ && par2ItemStack != null && var6.getSecondItemToBuy().itemID == par2ItemStack.itemID)
+ && par1ItemStack.stackSize >= var6.getItemToBuy().stackSize
+ && (!var6.hasSecondItemToBuy() || par2ItemStack.stackSize >= var6.getSecondItemToBuy().stackSize)
+ ? var6
+ : null;
+ } else {
+ for (int var4 = 0; var4 < this.size(); ++var4) {
+ MerchantRecipe var5 = (MerchantRecipe) this.get(var4);
+
+ if (par1ItemStack.itemID == var5.getItemToBuy().itemID
+ && par1ItemStack.stackSize >= var5.getItemToBuy().stackSize
+ && (!var5.hasSecondItemToBuy() && par2ItemStack == null || var5.hasSecondItemToBuy()
+ && par2ItemStack != null && var5.getSecondItemToBuy().itemID == par2ItemStack.itemID
+ && par2ItemStack.stackSize >= var5.getSecondItemToBuy().stackSize)) {
+ return var5;
+ }
+ }
+
+ return null;
+ }
+ }
+
+ /**
+ * checks if there is a recipie for the same ingredients already on the list,
+ * and replaces it. otherwise, adds it
+ */
+ public void addToListWithCheck(MerchantRecipe par1MerchantRecipe) {
+ for (int var2 = 0; var2 < this.size(); ++var2) {
+ MerchantRecipe var3 = (MerchantRecipe) this.get(var2);
+
+ if (par1MerchantRecipe.hasSameIDsAs(var3)) {
+ if (par1MerchantRecipe.hasSameItemsAs(var3)) {
+ this.set(var2, par1MerchantRecipe);
+ }
+
+ return;
+ }
+ }
+
+ this.add(par1MerchantRecipe);
+ }
+
+ public void writeRecipiesToStream(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeByte((byte) (this.size() & 255));
+
+ for (int var2 = 0; var2 < this.size(); ++var2) {
+ MerchantRecipe var3 = (MerchantRecipe) this.get(var2);
+ Packet.writeItemStack(var3.getItemToBuy(), par1DataOutputStream);
+ Packet.writeItemStack(var3.getItemToSell(), par1DataOutputStream);
+ ItemStack var4 = var3.getSecondItemToBuy();
+ par1DataOutputStream.writeBoolean(var4 != null);
+
+ if (var4 != null) {
+ Packet.writeItemStack(var4, par1DataOutputStream);
+ }
+
+ par1DataOutputStream.writeBoolean(var3.func_82784_g());
+ }
+ }
+
+ public void readRecipiesFromTags(NBTTagCompound par1NBTTagCompound) {
+ NBTTagList var2 = par1NBTTagCompound.getTagList("Recipes");
+
+ for (int var3 = 0; var3 < var2.tagCount(); ++var3) {
+ NBTTagCompound var4 = (NBTTagCompound) var2.tagAt(var3);
+ this.add(new MerchantRecipe(var4));
+ }
+ }
+
+ public NBTTagCompound getRecipiesAsTags() {
+ NBTTagCompound var1 = new NBTTagCompound();
+ NBTTagList var2 = new NBTTagList("Recipes");
+
+ for (int var3 = 0; var3 < this.size(); ++var3) {
+ MerchantRecipe var4 = (MerchantRecipe) this.get(var3);
+ var2.appendTag(var4.writeToTags());
+ }
+
+ var1.setTag("Recipes", var2);
+ return var1;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/MinecraftException.java b/sp-server/src/main/java/net/minecraft/src/MinecraftException.java
new file mode 100644
index 0000000..ca9e1f3
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/MinecraftException.java
@@ -0,0 +1,7 @@
+package net.minecraft.src;
+
+public class MinecraftException extends Exception {
+ public MinecraftException(String par1Str) {
+ super(par1Str);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/MobSpawnerBaseLogic.java b/sp-server/src/main/java/net/minecraft/src/MobSpawnerBaseLogic.java
new file mode 100644
index 0000000..1a9c5a8
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/MobSpawnerBaseLogic.java
@@ -0,0 +1,308 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+public abstract class MobSpawnerBaseLogic {
+ /** The delay to spawn. */
+ public int spawnDelay = 20;
+ private String mobID = "Pig";
+
+ /** List of minecart to spawn. */
+ private List minecartToSpawn = null;
+ private WeightedRandomMinecart randomMinecart = null;
+ public double field_98287_c;
+ public double field_98284_d = 0.0D;
+ private int minSpawnDelay = 200;
+ private int maxSpawnDelay = 800;
+ private int spawnCount = 4;
+ private Entity field_98291_j;
+ private int maxNearbyEntities = 6;
+
+ /** The distance from which a player activates the spawner. */
+ private int activatingRangeFromPlayer = 16;
+
+ /** The range coefficient for spawning entities around. */
+ private int spawnRange = 4;
+
+ /**
+ * Gets the entity name that should be spawned.
+ */
+ public String getEntityNameToSpawn() {
+ if (this.getRandomMinecart() == null) {
+ if (this.mobID.equals("Minecart")) {
+ this.mobID = "MinecartRideable";
+ }
+
+ return this.mobID;
+ } else {
+ return this.getRandomMinecart().minecartName;
+ }
+ }
+
+ public void setMobID(String par1Str) {
+ this.mobID = par1Str;
+ }
+
+ /**
+ * Returns true if there's a player close enough to this mob spawner to activate
+ * it.
+ */
+ public boolean canRun() {
+ return this.getSpawnerWorld().getClosestPlayer((double) this.getSpawnerX() + 0.5D,
+ (double) this.getSpawnerY() + 0.5D, (double) this.getSpawnerZ() + 0.5D,
+ (double) this.activatingRangeFromPlayer) != null;
+ }
+
+ public void updateSpawner() {
+ if (this.canRun()) {
+ double var5;
+
+ if (this.getSpawnerWorld().isRemote) {
+ double var1 = (double) ((float) this.getSpawnerX() + this.getSpawnerWorld().rand.nextFloat());
+ double var3 = (double) ((float) this.getSpawnerY() + this.getSpawnerWorld().rand.nextFloat());
+ var5 = (double) ((float) this.getSpawnerZ() + this.getSpawnerWorld().rand.nextFloat());
+ this.getSpawnerWorld().spawnParticle("smoke", var1, var3, var5, 0.0D, 0.0D, 0.0D);
+ this.getSpawnerWorld().spawnParticle("flame", var1, var3, var5, 0.0D, 0.0D, 0.0D);
+
+ if (this.spawnDelay > 0) {
+ --this.spawnDelay;
+ }
+
+ this.field_98284_d = this.field_98287_c;
+ this.field_98287_c = (this.field_98287_c + (double) (1000.0F / ((float) this.spawnDelay + 200.0F)))
+ % 360.0D;
+ } else {
+ if (this.spawnDelay == -1) {
+ this.func_98273_j();
+ }
+
+ if (this.spawnDelay > 0) {
+ --this.spawnDelay;
+ return;
+ }
+
+ boolean var12 = false;
+
+ for (int var2 = 0; var2 < this.spawnCount; ++var2) {
+ Entity var13 = EntityList.createEntityByName(this.getEntityNameToSpawn(), this.getSpawnerWorld());
+
+ if (var13 == null) {
+ return;
+ }
+
+ int var4 = this.getSpawnerWorld()
+ .getEntitiesWithinAABB(var13.getClass(), AxisAlignedBB.getAABBPool()
+ .getAABB((double) this.getSpawnerX(), (double) this.getSpawnerY(),
+ (double) this.getSpawnerZ(), (double) (this.getSpawnerX() + 1),
+ (double) (this.getSpawnerY() + 1), (double) (this.getSpawnerZ() + 1))
+ .expand((double) (this.spawnRange * 2), 4.0D, (double) (this.spawnRange * 2)))
+ .size();
+
+ if (var4 >= this.maxNearbyEntities) {
+ this.func_98273_j();
+ return;
+ }
+
+ var5 = (double) this.getSpawnerX()
+ + (this.getSpawnerWorld().rand.nextDouble() - this.getSpawnerWorld().rand.nextDouble())
+ * (double) this.spawnRange;
+ double var7 = (double) (this.getSpawnerY() + this.getSpawnerWorld().rand.nextInt(3) - 1);
+ double var9 = (double) this.getSpawnerZ()
+ + (this.getSpawnerWorld().rand.nextDouble() - this.getSpawnerWorld().rand.nextDouble())
+ * (double) this.spawnRange;
+ EntityLiving var11 = var13 instanceof EntityLiving ? (EntityLiving) var13 : null;
+ var13.setLocationAndAngles(var5, var7, var9, this.getSpawnerWorld().rand.nextFloat() * 360.0F,
+ 0.0F);
+
+ if (var11 == null || var11.getCanSpawnHere()) {
+ this.func_98265_a(var13);
+ this.getSpawnerWorld().playAuxSFX(2004, this.getSpawnerX(), this.getSpawnerY(),
+ this.getSpawnerZ(), 0);
+
+ if (var11 != null) {
+ var11.spawnExplosionParticle();
+ }
+
+ var12 = true;
+ }
+ }
+
+ if (var12) {
+ this.func_98273_j();
+ }
+ }
+ }
+ }
+
+ public Entity func_98265_a(Entity par1Entity) {
+ if (this.getRandomMinecart() != null) {
+ NBTTagCompound var2 = new NBTTagCompound();
+ par1Entity.addEntityID(var2);
+ Iterator var3 = this.getRandomMinecart().field_98222_b.getTags().iterator();
+
+ while (var3.hasNext()) {
+ NBTBase var4 = (NBTBase) var3.next();
+ var2.setTag(var4.getName(), var4.copy());
+ }
+
+ par1Entity.readFromNBT(var2);
+
+ if (par1Entity.worldObj != null) {
+ par1Entity.worldObj.spawnEntityInWorld(par1Entity);
+ }
+
+ NBTTagCompound var10;
+
+ for (Entity var9 = par1Entity; var2.hasKey("Riding"); var2 = var10) {
+ var10 = var2.getCompoundTag("Riding");
+ Entity var5 = EntityList.createEntityByName(var10.getString("id"), this.getSpawnerWorld());
+
+ if (var5 != null) {
+ NBTTagCompound var6 = new NBTTagCompound();
+ var5.addEntityID(var6);
+ Iterator var7 = var10.getTags().iterator();
+
+ while (var7.hasNext()) {
+ NBTBase var8 = (NBTBase) var7.next();
+ var6.setTag(var8.getName(), var8.copy());
+ }
+
+ var5.readFromNBT(var6);
+ var5.setLocationAndAngles(var9.posX, var9.posY, var9.posZ, var9.rotationYaw, var9.rotationPitch);
+ this.getSpawnerWorld().spawnEntityInWorld(var5);
+ var9.mountEntity(var5);
+ }
+
+ var9 = var5;
+ }
+ } else if (par1Entity instanceof EntityLiving && par1Entity.worldObj != null) {
+ ((EntityLiving) par1Entity).initCreature();
+ this.getSpawnerWorld().spawnEntityInWorld(par1Entity);
+ }
+
+ return par1Entity;
+ }
+
+ private void func_98273_j() {
+ if (this.maxSpawnDelay <= this.minSpawnDelay) {
+ this.spawnDelay = this.minSpawnDelay;
+ } else {
+ int var10003 = this.maxSpawnDelay - this.minSpawnDelay;
+ this.spawnDelay = this.minSpawnDelay + this.getSpawnerWorld().rand.nextInt(var10003);
+ }
+
+ if (this.minecartToSpawn != null && this.minecartToSpawn.size() > 0) {
+ this.setRandomMinecart((WeightedRandomMinecart) WeightedRandom.getRandomItem(this.getSpawnerWorld().rand,
+ this.minecartToSpawn));
+ }
+
+ this.func_98267_a(1);
+ }
+
+ public void readFromNBT(NBTTagCompound par1NBTTagCompound) {
+ this.mobID = par1NBTTagCompound.getString("EntityId");
+ this.spawnDelay = par1NBTTagCompound.getShort("Delay");
+
+ if (par1NBTTagCompound.hasKey("SpawnPotentials")) {
+ this.minecartToSpawn = new ArrayList();
+ NBTTagList var2 = par1NBTTagCompound.getTagList("SpawnPotentials");
+
+ for (int var3 = 0; var3 < var2.tagCount(); ++var3) {
+ this.minecartToSpawn.add(new WeightedRandomMinecart(this, (NBTTagCompound) var2.tagAt(var3)));
+ }
+ } else {
+ this.minecartToSpawn = null;
+ }
+
+ if (par1NBTTagCompound.hasKey("SpawnData")) {
+ this.setRandomMinecart(
+ new WeightedRandomMinecart(this, par1NBTTagCompound.getCompoundTag("SpawnData"), this.mobID));
+ } else {
+ this.setRandomMinecart((WeightedRandomMinecart) null);
+ }
+
+ if (par1NBTTagCompound.hasKey("MinSpawnDelay")) {
+ this.minSpawnDelay = par1NBTTagCompound.getShort("MinSpawnDelay");
+ this.maxSpawnDelay = par1NBTTagCompound.getShort("MaxSpawnDelay");
+ this.spawnCount = par1NBTTagCompound.getShort("SpawnCount");
+ }
+
+ if (par1NBTTagCompound.hasKey("MaxNearbyEntities")) {
+ this.maxNearbyEntities = par1NBTTagCompound.getShort("MaxNearbyEntities");
+ this.activatingRangeFromPlayer = par1NBTTagCompound.getShort("RequiredPlayerRange");
+ }
+
+ if (par1NBTTagCompound.hasKey("SpawnRange")) {
+ this.spawnRange = par1NBTTagCompound.getShort("SpawnRange");
+ }
+
+ if (this.getSpawnerWorld() != null && this.getSpawnerWorld().isRemote) {
+ this.field_98291_j = null;
+ }
+ }
+
+ public void writeToNBT(NBTTagCompound par1NBTTagCompound) {
+ par1NBTTagCompound.setString("EntityId", this.getEntityNameToSpawn());
+ par1NBTTagCompound.setShort("Delay", (short) this.spawnDelay);
+ par1NBTTagCompound.setShort("MinSpawnDelay", (short) this.minSpawnDelay);
+ par1NBTTagCompound.setShort("MaxSpawnDelay", (short) this.maxSpawnDelay);
+ par1NBTTagCompound.setShort("SpawnCount", (short) this.spawnCount);
+ par1NBTTagCompound.setShort("MaxNearbyEntities", (short) this.maxNearbyEntities);
+ par1NBTTagCompound.setShort("RequiredPlayerRange", (short) this.activatingRangeFromPlayer);
+ par1NBTTagCompound.setShort("SpawnRange", (short) this.spawnRange);
+
+ if (this.getRandomMinecart() != null) {
+ par1NBTTagCompound.setCompoundTag("SpawnData",
+ (NBTTagCompound) this.getRandomMinecart().field_98222_b.copy());
+ }
+
+ if (this.getRandomMinecart() != null || this.minecartToSpawn != null && this.minecartToSpawn.size() > 0) {
+ NBTTagList var2 = new NBTTagList();
+
+ if (this.minecartToSpawn != null && this.minecartToSpawn.size() > 0) {
+ Iterator var3 = this.minecartToSpawn.iterator();
+
+ while (var3.hasNext()) {
+ WeightedRandomMinecart var4 = (WeightedRandomMinecart) var3.next();
+ var2.appendTag(var4.func_98220_a());
+ }
+ } else {
+ var2.appendTag(this.getRandomMinecart().func_98220_a());
+ }
+
+ par1NBTTagCompound.setTag("SpawnPotentials", var2);
+ }
+ }
+
+ /**
+ * Sets the delay to minDelay if parameter given is 1, else return false.
+ */
+ public boolean setDelayToMin(int par1) {
+ if (par1 == 1 && this.getSpawnerWorld().isRemote) {
+ this.spawnDelay = this.minSpawnDelay;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public WeightedRandomMinecart getRandomMinecart() {
+ return this.randomMinecart;
+ }
+
+ public void setRandomMinecart(WeightedRandomMinecart par1WeightedRandomMinecart) {
+ this.randomMinecart = par1WeightedRandomMinecart;
+ }
+
+ public abstract void func_98267_a(int var1);
+
+ public abstract World getSpawnerWorld();
+
+ public abstract int getSpawnerX();
+
+ public abstract int getSpawnerY();
+
+ public abstract int getSpawnerZ();
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/MovingObjectPosition.java b/sp-server/src/main/java/net/minecraft/src/MovingObjectPosition.java
new file mode 100644
index 0000000..9f48dfc
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/MovingObjectPosition.java
@@ -0,0 +1,43 @@
+package net.minecraft.src;
+
+public class MovingObjectPosition {
+ /** What type of ray trace hit was this? 0 = block, 1 = entity */
+ public EnumMovingObjectType typeOfHit;
+
+ /** x coordinate of the block ray traced against */
+ public int blockX;
+
+ /** y coordinate of the block ray traced against */
+ public int blockY;
+
+ /** z coordinate of the block ray traced against */
+ public int blockZ;
+
+ /**
+ * Which side was hit. If its -1 then it went the full length of the ray trace.
+ * Bottom = 0, Top = 1, East = 2, West = 3, North = 4, South = 5.
+ */
+ public int sideHit;
+
+ /** The vector position of the hit */
+ public Vec3 hitVec;
+
+ /** The hit entity */
+ public Entity entityHit;
+
+ public MovingObjectPosition(int par1, int par2, int par3, int par4, Vec3 par5Vec3) {
+ this.typeOfHit = EnumMovingObjectType.TILE;
+ this.blockX = par1;
+ this.blockY = par2;
+ this.blockZ = par3;
+ this.sideHit = par4;
+ this.hitVec = par5Vec3.myVec3LocalPool.getVecFromPool(par5Vec3.xCoord, par5Vec3.yCoord, par5Vec3.zCoord);
+ }
+
+ public MovingObjectPosition(Entity par1Entity) {
+ this.typeOfHit = EnumMovingObjectType.ENTITY;
+ this.entityHit = par1Entity;
+ this.hitVec = par1Entity.worldObj.getWorldVec3Pool().getVecFromPool(par1Entity.posX, par1Entity.posY,
+ par1Entity.posZ);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/NBTBase.java b/sp-server/src/main/java/net/minecraft/src/NBTBase.java
new file mode 100644
index 0000000..a63c7ef
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/NBTBase.java
@@ -0,0 +1,202 @@
+package net.minecraft.src;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+public abstract class NBTBase {
+ public static final String[] NBTTypes = new String[] { "END", "BYTE", "SHORT", "INT", "LONG", "FLOAT", "DOUBLE",
+ "BYTE[]", "STRING", "LIST", "COMPOUND", "INT[]" };
+
+ /** The UTF string key used to lookup values. */
+ private String name;
+
+ /**
+ * Write the actual data contents of the tag, implemented in NBT extension
+ * classes
+ */
+ abstract void write(DataOutput var1) throws IOException;
+
+ /**
+ * Read the actual data contents of the tag, implemented in NBT extension
+ * classes
+ */
+ abstract void load(DataInput var1) throws IOException;
+
+ /**
+ * Gets the type byte for the tag.
+ */
+ public abstract byte getId();
+
+ protected NBTBase(String par1Str) {
+ if (par1Str == null) {
+ this.name = "";
+ } else {
+ this.name = par1Str;
+ }
+ }
+
+ /**
+ * Sets the name for this tag and returns this for convenience.
+ */
+ public NBTBase setName(String par1Str) {
+ if (par1Str == null) {
+ this.name = "";
+ } else {
+ this.name = par1Str;
+ }
+
+ return this;
+ }
+
+ /**
+ * Gets the name corresponding to the tag, or an empty string if none set.
+ */
+ public String getName() {
+ return this.name == null ? "" : this.name;
+ }
+
+ /**
+ * Reads and returns a tag from the given DataInput, or the End tag if no tag
+ * could be read.
+ */
+ public static NBTBase readNamedTag(DataInput par0DataInput) throws IOException {
+ byte var1 = par0DataInput.readByte();
+
+ if (var1 == 0) {
+ return new NBTTagEnd();
+ } else {
+ String var2 = par0DataInput.readUTF();
+ NBTBase var3 = newTag(var1, var2);
+ var3.load(par0DataInput);
+ return var3;
+ }
+ }
+
+ /**
+ * Writes the specified tag to the given DataOutput, writing the type byte, the
+ * UTF string key and then calling the tag to write its data.
+ */
+ public static void writeNamedTag(NBTBase par0NBTBase, DataOutput par1DataOutput) throws IOException {
+ par1DataOutput.writeByte(par0NBTBase.getId());
+
+ if (par0NBTBase.getId() != 0) {
+ par1DataOutput.writeUTF(par0NBTBase.getName());
+ par0NBTBase.write(par1DataOutput);
+ }
+ }
+
+ /**
+ * Creates and returns a new tag of the specified type, or null if invalid.
+ */
+ public static NBTBase newTag(byte par0, String par1Str) {
+ switch (par0) {
+ case 0:
+ return new NBTTagEnd();
+
+ case 1:
+ return new NBTTagByte(par1Str);
+
+ case 2:
+ return new NBTTagShort(par1Str);
+
+ case 3:
+ return new NBTTagInt(par1Str);
+
+ case 4:
+ return new NBTTagLong(par1Str);
+
+ case 5:
+ return new NBTTagFloat(par1Str);
+
+ case 6:
+ return new NBTTagDouble(par1Str);
+
+ case 7:
+ return new NBTTagByteArray(par1Str);
+
+ case 8:
+ return new NBTTagString(par1Str);
+
+ case 9:
+ return new NBTTagList(par1Str);
+
+ case 10:
+ return new NBTTagCompound(par1Str);
+
+ case 11:
+ return new NBTTagIntArray(par1Str);
+
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Returns the string name of a tag with the specified type, or 'UNKNOWN' if
+ * invalid.
+ */
+ public static String getTagName(byte par0) {
+ switch (par0) {
+ case 0:
+ return "TAG_End";
+
+ case 1:
+ return "TAG_Byte";
+
+ case 2:
+ return "TAG_Short";
+
+ case 3:
+ return "TAG_Int";
+
+ case 4:
+ return "TAG_Long";
+
+ case 5:
+ return "TAG_Float";
+
+ case 6:
+ return "TAG_Double";
+
+ case 7:
+ return "TAG_Byte_Array";
+
+ case 8:
+ return "TAG_String";
+
+ case 9:
+ return "TAG_List";
+
+ case 10:
+ return "TAG_Compound";
+
+ case 11:
+ return "TAG_Int_Array";
+
+ default:
+ return "UNKNOWN";
+ }
+ }
+
+ /**
+ * Creates a clone of the tag.
+ */
+ public abstract NBTBase copy();
+
+ public boolean equals(Object par1Obj) {
+ if (!(par1Obj instanceof NBTBase)) {
+ return false;
+ } else {
+ NBTBase var2 = (NBTBase) par1Obj;
+ return this.getId() != var2.getId() ? false
+ : ((this.name != null || var2.name == null) && (this.name == null || var2.name != null)
+ ? this.name == null || this.name.equals(var2.name)
+ : false);
+ }
+ }
+
+ public int hashCode() {
+ return this.name.hashCode() ^ this.getId();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/NBTTagByte.java b/sp-server/src/main/java/net/minecraft/src/NBTTagByte.java
new file mode 100644
index 0000000..35dc311
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/NBTTagByte.java
@@ -0,0 +1,66 @@
+package net.minecraft.src;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+public class NBTTagByte extends NBTBase {
+ /** The byte value for the tag. */
+ public byte data;
+
+ public NBTTagByte(String par1Str) {
+ super(par1Str);
+ }
+
+ public NBTTagByte(String par1Str, byte par2) {
+ super(par1Str);
+ this.data = par2;
+ }
+
+ /**
+ * Write the actual data contents of the tag, implemented in NBT extension
+ * classes
+ */
+ void write(DataOutput par1DataOutput) throws IOException {
+ par1DataOutput.writeByte(this.data);
+ }
+
+ /**
+ * Read the actual data contents of the tag, implemented in NBT extension
+ * classes
+ */
+ void load(DataInput par1DataInput) throws IOException {
+ this.data = par1DataInput.readByte();
+ }
+
+ /**
+ * Gets the type byte for the tag.
+ */
+ public byte getId() {
+ return (byte) 1;
+ }
+
+ public String toString() {
+ return "" + this.data;
+ }
+
+ /**
+ * Creates a clone of the tag.
+ */
+ public NBTBase copy() {
+ return new NBTTagByte(this.getName(), this.data);
+ }
+
+ public boolean equals(Object par1Obj) {
+ if (super.equals(par1Obj)) {
+ NBTTagByte var2 = (NBTTagByte) par1Obj;
+ return this.data == var2.data;
+ } else {
+ return false;
+ }
+ }
+
+ public int hashCode() {
+ return super.hashCode() ^ this.data;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/NBTTagByteArray.java b/sp-server/src/main/java/net/minecraft/src/NBTTagByteArray.java
new file mode 100644
index 0000000..06d58eb
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/NBTTagByteArray.java
@@ -0,0 +1,67 @@
+package net.minecraft.src;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.Arrays;
+
+public class NBTTagByteArray extends NBTBase {
+ /** The byte array stored in the tag. */
+ public byte[] byteArray;
+
+ public NBTTagByteArray(String par1Str) {
+ super(par1Str);
+ }
+
+ public NBTTagByteArray(String par1Str, byte[] par2ArrayOfByte) {
+ super(par1Str);
+ this.byteArray = par2ArrayOfByte;
+ }
+
+ /**
+ * Write the actual data contents of the tag, implemented in NBT extension
+ * classes
+ */
+ void write(DataOutput par1DataOutput) throws IOException {
+ par1DataOutput.writeInt(this.byteArray.length);
+ par1DataOutput.write(this.byteArray);
+ }
+
+ /**
+ * Read the actual data contents of the tag, implemented in NBT extension
+ * classes
+ */
+ void load(DataInput par1DataInput) throws IOException {
+ int var2 = par1DataInput.readInt();
+ this.byteArray = new byte[var2];
+ par1DataInput.readFully(this.byteArray);
+ }
+
+ /**
+ * Gets the type byte for the tag.
+ */
+ public byte getId() {
+ return (byte) 7;
+ }
+
+ public String toString() {
+ return "[" + this.byteArray.length + " bytes]";
+ }
+
+ /**
+ * Creates a clone of the tag.
+ */
+ public NBTBase copy() {
+ byte[] var1 = new byte[this.byteArray.length];
+ System.arraycopy(this.byteArray, 0, var1, 0, this.byteArray.length);
+ return new NBTTagByteArray(this.getName(), var1);
+ }
+
+ public boolean equals(Object par1Obj) {
+ return super.equals(par1Obj) ? Arrays.equals(this.byteArray, ((NBTTagByteArray) par1Obj).byteArray) : false;
+ }
+
+ public int hashCode() {
+ return super.hashCode() ^ Arrays.hashCode(this.byteArray);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/NBTTagCompound.java b/sp-server/src/main/java/net/minecraft/src/NBTTagCompound.java
new file mode 100644
index 0000000..bc442d3
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/NBTTagCompound.java
@@ -0,0 +1,337 @@
+package net.minecraft.src;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+public class NBTTagCompound extends NBTBase {
+ /**
+ * The key-value pairs for the tag. Each key is a UTF string, each value is a
+ * tag.
+ */
+ private Map tagMap = new HashMap();
+
+ public NBTTagCompound() {
+ super("");
+ }
+
+ public NBTTagCompound(String par1Str) {
+ super(par1Str);
+ }
+
+ /**
+ * Write the actual data contents of the tag, implemented in NBT extension
+ * classes
+ */
+ void write(DataOutput par1DataOutput) throws IOException {
+ Iterator var2 = this.tagMap.values().iterator();
+
+ while (var2.hasNext()) {
+ NBTBase var3 = (NBTBase) var2.next();
+ NBTBase.writeNamedTag(var3, par1DataOutput);
+ }
+
+ par1DataOutput.writeByte(0);
+ }
+
+ /**
+ * Read the actual data contents of the tag, implemented in NBT extension
+ * classes
+ */
+ void load(DataInput par1DataInput) throws IOException {
+ this.tagMap.clear();
+ NBTBase var2;
+
+ while ((var2 = NBTBase.readNamedTag(par1DataInput)).getId() != 0) {
+ this.tagMap.put(var2.getName(), var2);
+ }
+ }
+
+ /**
+ * Returns all the values in the tagMap HashMap.
+ */
+ public Collection getTags() {
+ return this.tagMap.values();
+ }
+
+ /**
+ * Gets the type byte for the tag.
+ */
+ public byte getId() {
+ return (byte) 10;
+ }
+
+ /**
+ * Stores the given tag into the map with the given string key. This is mostly
+ * used to store tag lists.
+ */
+ public void setTag(String par1Str, NBTBase par2NBTBase) {
+ this.tagMap.put(par1Str, par2NBTBase.setName(par1Str));
+ }
+
+ /**
+ * Stores a new NBTTagByte with the given byte value into the map with the given
+ * string key.
+ */
+ public void setByte(String par1Str, byte par2) {
+ this.tagMap.put(par1Str, new NBTTagByte(par1Str, par2));
+ }
+
+ /**
+ * Stores a new NBTTagShort with the given short value into the map with the
+ * given string key.
+ */
+ public void setShort(String par1Str, short par2) {
+ this.tagMap.put(par1Str, new NBTTagShort(par1Str, par2));
+ }
+
+ /**
+ * Stores a new NBTTagInt with the given integer value into the map with the
+ * given string key.
+ */
+ public void setInteger(String par1Str, int par2) {
+ this.tagMap.put(par1Str, new NBTTagInt(par1Str, par2));
+ }
+
+ /**
+ * Stores a new NBTTagLong with the given long value into the map with the given
+ * string key.
+ */
+ public void setLong(String par1Str, long par2) {
+ this.tagMap.put(par1Str, new NBTTagLong(par1Str, par2));
+ }
+
+ /**
+ * Stores a new NBTTagFloat with the given float value into the map with the
+ * given string key.
+ */
+ public void setFloat(String par1Str, float par2) {
+ this.tagMap.put(par1Str, new NBTTagFloat(par1Str, par2));
+ }
+
+ /**
+ * Stores a new NBTTagDouble with the given double value into the map with the
+ * given string key.
+ */
+ public void setDouble(String par1Str, double par2) {
+ this.tagMap.put(par1Str, new NBTTagDouble(par1Str, par2));
+ }
+
+ /**
+ * Stores a new NBTTagString with the given string value into the map with the
+ * given string key.
+ */
+ public void setString(String par1Str, String par2Str) {
+ this.tagMap.put(par1Str, new NBTTagString(par1Str, par2Str));
+ }
+
+ /**
+ * Stores a new NBTTagByteArray with the given array as data into the map with
+ * the given string key.
+ */
+ public void setByteArray(String par1Str, byte[] par2ArrayOfByte) {
+ this.tagMap.put(par1Str, new NBTTagByteArray(par1Str, par2ArrayOfByte));
+ }
+
+ /**
+ * Stores a new NBTTagIntArray with the given array as data into the map with
+ * the given string key.
+ */
+ public void setIntArray(String par1Str, int[] par2ArrayOfInteger) {
+ this.tagMap.put(par1Str, new NBTTagIntArray(par1Str, par2ArrayOfInteger));
+ }
+
+ /**
+ * Stores the given NBTTagCompound into the map with the given string key.
+ */
+ public void setCompoundTag(String par1Str, NBTTagCompound par2NBTTagCompound) {
+ this.tagMap.put(par1Str, par2NBTTagCompound.setName(par1Str));
+ }
+
+ /**
+ * Stores the given boolean value as a NBTTagByte, storing 1 for true and 0 for
+ * false, using the given string key.
+ */
+ public void setBoolean(String par1Str, boolean par2) {
+ this.setByte(par1Str, (byte) (par2 ? 1 : 0));
+ }
+
+ /**
+ * gets a generic tag with the specified name
+ */
+ public NBTBase getTag(String par1Str) {
+ return (NBTBase) this.tagMap.get(par1Str);
+ }
+
+ /**
+ * Returns whether the given string has been previously stored as a key in the
+ * map.
+ */
+ public boolean hasKey(String par1Str) {
+ return this.tagMap.containsKey(par1Str);
+ }
+
+ /**
+ * Retrieves a byte value using the specified key, or 0 if no such key was
+ * stored.
+ */
+ public byte getByte(String par1Str) {
+ return !this.tagMap.containsKey(par1Str) ? 0 : ((NBTTagByte) this.tagMap.get(par1Str)).data;
+ }
+
+ /**
+ * Retrieves a short value using the specified key, or 0 if no such key was
+ * stored.
+ */
+ public short getShort(String par1Str) {
+ return !this.tagMap.containsKey(par1Str) ? 0 : ((NBTTagShort) this.tagMap.get(par1Str)).data;
+ }
+
+ /**
+ * Retrieves an integer value using the specified key, or 0 if no such key was
+ * stored.
+ */
+ public int getInteger(String par1Str) {
+ return !this.tagMap.containsKey(par1Str) ? 0 : ((NBTTagInt) this.tagMap.get(par1Str)).data;
+ }
+
+ /**
+ * Retrieves a long value using the specified key, or 0 if no such key was
+ * stored.
+ */
+ public long getLong(String par1Str) {
+ return !this.tagMap.containsKey(par1Str) ? 0L : ((NBTTagLong) this.tagMap.get(par1Str)).data;
+ }
+
+ /**
+ * Retrieves a float value using the specified key, or 0 if no such key was
+ * stored.
+ */
+ public float getFloat(String par1Str) {
+ return !this.tagMap.containsKey(par1Str) ? 0.0F : ((NBTTagFloat) this.tagMap.get(par1Str)).data;
+ }
+
+ /**
+ * Retrieves a double value using the specified key, or 0 if no such key was
+ * stored.
+ */
+ public double getDouble(String par1Str) {
+ return !this.tagMap.containsKey(par1Str) ? 0.0D : ((NBTTagDouble) this.tagMap.get(par1Str)).data;
+ }
+
+ /**
+ * Retrieves a string value using the specified key, or an empty string if no
+ * such key was stored.
+ */
+ public String getString(String par1Str) {
+ return !this.tagMap.containsKey(par1Str) ? "" : ((NBTTagString) this.tagMap.get(par1Str)).data;
+ }
+
+ /**
+ * Retrieves a byte array using the specified key, or a zero-length array if no
+ * such key was stored.
+ */
+ public byte[] getByteArray(String par1Str) {
+ return !this.tagMap.containsKey(par1Str) ? new byte[0]
+ : ((NBTTagByteArray) this.tagMap.get(par1Str)).byteArray;
+ }
+
+ /**
+ * Retrieves an int array using the specified key, or a zero-length array if no
+ * such key was stored.
+ */
+ public int[] getIntArray(String par1Str) {
+ return !this.tagMap.containsKey(par1Str) ? new int[0]
+ : ((NBTTagIntArray) this.tagMap.get(par1Str)).intArray;
+ }
+
+ /**
+ * Retrieves a NBTTagCompound subtag matching the specified key, or a new empty
+ * NBTTagCompound if no such key was stored.
+ */
+ public NBTTagCompound getCompoundTag(String par1Str) {
+ return !this.tagMap.containsKey(par1Str) ? new NBTTagCompound(par1Str)
+ : (NBTTagCompound) this.tagMap.get(par1Str);
+ }
+
+ /**
+ * Retrieves a NBTTagList subtag matching the specified key, or a new empty
+ * NBTTagList if no such key was stored.
+ */
+ public NBTTagList getTagList(String par1Str) {
+ return !this.tagMap.containsKey(par1Str) ? new NBTTagList(par1Str) : (NBTTagList) this.tagMap.get(par1Str);
+ }
+
+ /**
+ * Retrieves a boolean value using the specified key, or false if no such key
+ * was stored. This uses the getByte method.
+ */
+ public boolean getBoolean(String par1Str) {
+ return this.getByte(par1Str) != 0;
+ }
+
+ /**
+ * Remove the specified tag.
+ */
+ public void removeTag(String par1Str) {
+ this.tagMap.remove(par1Str);
+ }
+
+ public String toString() {
+ String var1 = this.getName() + ":[";
+ String var3;
+
+ for (Iterator var2 = this.tagMap.keySet().iterator(); var2
+ .hasNext(); var1 = var1 + var3 + ":" + this.tagMap.get(var3) + ",") {
+ var3 = (String) var2.next();
+ }
+
+ return var1 + "]";
+ }
+
+ /**
+ * Return whether this compound has no tags.
+ */
+ public boolean hasNoTags() {
+ return this.tagMap.isEmpty();
+ }
+
+ /**
+ * Creates a clone of the tag.
+ */
+ public NBTBase copy() {
+ NBTTagCompound var1 = new NBTTagCompound(this.getName());
+ Iterator var2 = this.tagMap.keySet().iterator();
+
+ while (var2.hasNext()) {
+ String var3 = (String) var2.next();
+ var1.setTag(var3, ((NBTBase) this.tagMap.get(var3)).copy());
+ }
+
+ return var1;
+ }
+
+ public boolean equals(Object par1Obj) {
+ if (super.equals(par1Obj)) {
+ NBTTagCompound var2 = (NBTTagCompound) par1Obj;
+ return this.tagMap.entrySet().equals(var2.tagMap.entrySet());
+ } else {
+ return false;
+ }
+ }
+
+ public int hashCode() {
+ return super.hashCode() ^ this.tagMap.hashCode();
+ }
+
+ /**
+ * Return the tag map for this compound.
+ */
+ static Map getTagMap(NBTTagCompound par0NBTTagCompound) {
+ return par0NBTTagCompound.tagMap;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/NBTTagDouble.java b/sp-server/src/main/java/net/minecraft/src/NBTTagDouble.java
new file mode 100644
index 0000000..5d89b64
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/NBTTagDouble.java
@@ -0,0 +1,67 @@
+package net.minecraft.src;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+public class NBTTagDouble extends NBTBase {
+ /** The double value for the tag. */
+ public double data;
+
+ public NBTTagDouble(String par1Str) {
+ super(par1Str);
+ }
+
+ public NBTTagDouble(String par1Str, double par2) {
+ super(par1Str);
+ this.data = par2;
+ }
+
+ /**
+ * Write the actual data contents of the tag, implemented in NBT extension
+ * classes
+ */
+ void write(DataOutput par1DataOutput) throws IOException {
+ par1DataOutput.writeDouble(this.data);
+ }
+
+ /**
+ * Read the actual data contents of the tag, implemented in NBT extension
+ * classes
+ */
+ void load(DataInput par1DataInput) throws IOException {
+ this.data = par1DataInput.readDouble();
+ }
+
+ /**
+ * Gets the type byte for the tag.
+ */
+ public byte getId() {
+ return (byte) 6;
+ }
+
+ public String toString() {
+ return "" + this.data;
+ }
+
+ /**
+ * Creates a clone of the tag.
+ */
+ public NBTBase copy() {
+ return new NBTTagDouble(this.getName(), this.data);
+ }
+
+ public boolean equals(Object par1Obj) {
+ if (super.equals(par1Obj)) {
+ NBTTagDouble var2 = (NBTTagDouble) par1Obj;
+ return this.data == var2.data;
+ } else {
+ return false;
+ }
+ }
+
+ public int hashCode() {
+ long var1 = Double.doubleToLongBits(this.data);
+ return super.hashCode() ^ (int) (var1 ^ var1 >>> 32);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/NBTTagEnd.java b/sp-server/src/main/java/net/minecraft/src/NBTTagEnd.java
new file mode 100644
index 0000000..9bc8ed2
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/NBTTagEnd.java
@@ -0,0 +1,43 @@
+package net.minecraft.src;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+public class NBTTagEnd extends NBTBase {
+ public NBTTagEnd() {
+ super((String) null);
+ }
+
+ /**
+ * Read the actual data contents of the tag, implemented in NBT extension
+ * classes
+ */
+ void load(DataInput par1DataInput) throws IOException {
+ }
+
+ /**
+ * Write the actual data contents of the tag, implemented in NBT extension
+ * classes
+ */
+ void write(DataOutput par1DataOutput) throws IOException {
+ }
+
+ /**
+ * Gets the type byte for the tag.
+ */
+ public byte getId() {
+ return (byte) 0;
+ }
+
+ public String toString() {
+ return "END";
+ }
+
+ /**
+ * Creates a clone of the tag.
+ */
+ public NBTBase copy() {
+ return new NBTTagEnd();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/NBTTagFloat.java b/sp-server/src/main/java/net/minecraft/src/NBTTagFloat.java
new file mode 100644
index 0000000..3e2ef67
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/NBTTagFloat.java
@@ -0,0 +1,66 @@
+package net.minecraft.src;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+public class NBTTagFloat extends NBTBase {
+ /** The float value for the tag. */
+ public float data;
+
+ public NBTTagFloat(String par1Str) {
+ super(par1Str);
+ }
+
+ public NBTTagFloat(String par1Str, float par2) {
+ super(par1Str);
+ this.data = par2;
+ }
+
+ /**
+ * Write the actual data contents of the tag, implemented in NBT extension
+ * classes
+ */
+ void write(DataOutput par1DataOutput) throws IOException {
+ par1DataOutput.writeFloat(this.data);
+ }
+
+ /**
+ * Read the actual data contents of the tag, implemented in NBT extension
+ * classes
+ */
+ void load(DataInput par1DataInput) throws IOException {
+ this.data = par1DataInput.readFloat();
+ }
+
+ /**
+ * Gets the type byte for the tag.
+ */
+ public byte getId() {
+ return (byte) 5;
+ }
+
+ public String toString() {
+ return "" + this.data;
+ }
+
+ /**
+ * Creates a clone of the tag.
+ */
+ public NBTBase copy() {
+ return new NBTTagFloat(this.getName(), this.data);
+ }
+
+ public boolean equals(Object par1Obj) {
+ if (super.equals(par1Obj)) {
+ NBTTagFloat var2 = (NBTTagFloat) par1Obj;
+ return this.data == var2.data;
+ } else {
+ return false;
+ }
+ }
+
+ public int hashCode() {
+ return super.hashCode() ^ Float.floatToIntBits(this.data);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/NBTTagInt.java b/sp-server/src/main/java/net/minecraft/src/NBTTagInt.java
new file mode 100644
index 0000000..4a621dd
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/NBTTagInt.java
@@ -0,0 +1,66 @@
+package net.minecraft.src;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+public class NBTTagInt extends NBTBase {
+ /** The integer value for the tag. */
+ public int data;
+
+ public NBTTagInt(String par1Str) {
+ super(par1Str);
+ }
+
+ public NBTTagInt(String par1Str, int par2) {
+ super(par1Str);
+ this.data = par2;
+ }
+
+ /**
+ * Write the actual data contents of the tag, implemented in NBT extension
+ * classes
+ */
+ void write(DataOutput par1DataOutput) throws IOException {
+ par1DataOutput.writeInt(this.data);
+ }
+
+ /**
+ * Read the actual data contents of the tag, implemented in NBT extension
+ * classes
+ */
+ void load(DataInput par1DataInput) throws IOException {
+ this.data = par1DataInput.readInt();
+ }
+
+ /**
+ * Gets the type byte for the tag.
+ */
+ public byte getId() {
+ return (byte) 3;
+ }
+
+ public String toString() {
+ return "" + this.data;
+ }
+
+ /**
+ * Creates a clone of the tag.
+ */
+ public NBTBase copy() {
+ return new NBTTagInt(this.getName(), this.data);
+ }
+
+ public boolean equals(Object par1Obj) {
+ if (super.equals(par1Obj)) {
+ NBTTagInt var2 = (NBTTagInt) par1Obj;
+ return this.data == var2.data;
+ } else {
+ return false;
+ }
+ }
+
+ public int hashCode() {
+ return super.hashCode() ^ this.data;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/NBTTagIntArray.java b/sp-server/src/main/java/net/minecraft/src/NBTTagIntArray.java
new file mode 100644
index 0000000..e6d3066
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/NBTTagIntArray.java
@@ -0,0 +1,79 @@
+package net.minecraft.src;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.Arrays;
+
+public class NBTTagIntArray extends NBTBase {
+ /** The array of saved integers */
+ public int[] intArray;
+
+ public NBTTagIntArray(String par1Str) {
+ super(par1Str);
+ }
+
+ public NBTTagIntArray(String par1Str, int[] par2ArrayOfInteger) {
+ super(par1Str);
+ this.intArray = par2ArrayOfInteger;
+ }
+
+ /**
+ * Write the actual data contents of the tag, implemented in NBT extension
+ * classes
+ */
+ void write(DataOutput par1DataOutput) throws IOException {
+ par1DataOutput.writeInt(this.intArray.length);
+
+ for (int var2 = 0; var2 < this.intArray.length; ++var2) {
+ par1DataOutput.writeInt(this.intArray[var2]);
+ }
+ }
+
+ /**
+ * Read the actual data contents of the tag, implemented in NBT extension
+ * classes
+ */
+ void load(DataInput par1DataInput) throws IOException {
+ int var2 = par1DataInput.readInt();
+ this.intArray = new int[var2];
+
+ for (int var3 = 0; var3 < var2; ++var3) {
+ this.intArray[var3] = par1DataInput.readInt();
+ }
+ }
+
+ /**
+ * Gets the type byte for the tag.
+ */
+ public byte getId() {
+ return (byte) 11;
+ }
+
+ public String toString() {
+ return "[" + this.intArray.length + " bytes]";
+ }
+
+ /**
+ * Creates a clone of the tag.
+ */
+ public NBTBase copy() {
+ int[] var1 = new int[this.intArray.length];
+ System.arraycopy(this.intArray, 0, var1, 0, this.intArray.length);
+ return new NBTTagIntArray(this.getName(), var1);
+ }
+
+ public boolean equals(Object par1Obj) {
+ if (!super.equals(par1Obj)) {
+ return false;
+ } else {
+ NBTTagIntArray var2 = (NBTTagIntArray) par1Obj;
+ return this.intArray == null && var2.intArray == null
+ || this.intArray != null && Arrays.equals(this.intArray, var2.intArray);
+ }
+ }
+
+ public int hashCode() {
+ return super.hashCode() ^ Arrays.hashCode(this.intArray);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/NBTTagList.java b/sp-server/src/main/java/net/minecraft/src/NBTTagList.java
new file mode 100644
index 0000000..356827d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/NBTTagList.java
@@ -0,0 +1,128 @@
+package net.minecraft.src;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+public class NBTTagList extends NBTBase {
+ /** The array list containing the tags encapsulated in this list. */
+ private List tagList = new ArrayList();
+
+ /**
+ * The type byte for the tags in the list - they must all be of the same type.
+ */
+ private byte tagType;
+
+ public NBTTagList() {
+ super("");
+ }
+
+ public NBTTagList(String par1Str) {
+ super(par1Str);
+ }
+
+ /**
+ * Write the actual data contents of the tag, implemented in NBT extension
+ * classes
+ */
+ void write(DataOutput par1DataOutput) throws IOException {
+ if (!this.tagList.isEmpty()) {
+ this.tagType = ((NBTBase) this.tagList.get(0)).getId();
+ } else {
+ this.tagType = 1;
+ }
+
+ par1DataOutput.writeByte(this.tagType);
+ par1DataOutput.writeInt(this.tagList.size());
+
+ for (int var2 = 0; var2 < this.tagList.size(); ++var2) {
+ ((NBTBase) this.tagList.get(var2)).write(par1DataOutput);
+ }
+ }
+
+ /**
+ * Read the actual data contents of the tag, implemented in NBT extension
+ * classes
+ */
+ void load(DataInput par1DataInput) throws IOException {
+ this.tagType = par1DataInput.readByte();
+ int var2 = par1DataInput.readInt();
+ this.tagList = new ArrayList();
+
+ for (int var3 = 0; var3 < var2; ++var3) {
+ NBTBase var4 = NBTBase.newTag(this.tagType, (String) null);
+ var4.load(par1DataInput);
+ this.tagList.add(var4);
+ }
+ }
+
+ /**
+ * Gets the type byte for the tag.
+ */
+ public byte getId() {
+ return (byte) 9;
+ }
+
+ public String toString() {
+ return "" + this.tagList.size() + " entries of type " + NBTBase.getTagName(this.tagType);
+ }
+
+ /**
+ * Adds the provided tag to the end of the list. There is no check to verify
+ * this tag is of the same type as any previous tag.
+ */
+ public void appendTag(NBTBase par1NBTBase) {
+ this.tagType = par1NBTBase.getId();
+ this.tagList.add(par1NBTBase);
+ }
+
+ /**
+ * Retrieves the tag at the specified index from the list.
+ */
+ public NBTBase tagAt(int par1) {
+ return (NBTBase) this.tagList.get(par1);
+ }
+
+ /**
+ * Returns the number of tags in the list.
+ */
+ public int tagCount() {
+ return this.tagList.size();
+ }
+
+ /**
+ * Creates a clone of the tag.
+ */
+ public NBTBase copy() {
+ NBTTagList var1 = new NBTTagList(this.getName());
+ var1.tagType = this.tagType;
+ Iterator var2 = this.tagList.iterator();
+
+ while (var2.hasNext()) {
+ NBTBase var3 = (NBTBase) var2.next();
+ NBTBase var4 = var3.copy();
+ var1.tagList.add(var4);
+ }
+
+ return var1;
+ }
+
+ public boolean equals(Object par1Obj) {
+ if (super.equals(par1Obj)) {
+ NBTTagList var2 = (NBTTagList) par1Obj;
+
+ if (this.tagType == var2.tagType) {
+ return this.tagList.equals(var2.tagList);
+ }
+ }
+
+ return false;
+ }
+
+ public int hashCode() {
+ return super.hashCode() ^ this.tagList.hashCode();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/NBTTagLong.java b/sp-server/src/main/java/net/minecraft/src/NBTTagLong.java
new file mode 100644
index 0000000..c48b532
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/NBTTagLong.java
@@ -0,0 +1,66 @@
+package net.minecraft.src;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+public class NBTTagLong extends NBTBase {
+ /** The long value for the tag. */
+ public long data;
+
+ public NBTTagLong(String par1Str) {
+ super(par1Str);
+ }
+
+ public NBTTagLong(String par1Str, long par2) {
+ super(par1Str);
+ this.data = par2;
+ }
+
+ /**
+ * Write the actual data contents of the tag, implemented in NBT extension
+ * classes
+ */
+ void write(DataOutput par1DataOutput) throws IOException {
+ par1DataOutput.writeLong(this.data);
+ }
+
+ /**
+ * Read the actual data contents of the tag, implemented in NBT extension
+ * classes
+ */
+ void load(DataInput par1DataInput) throws IOException {
+ this.data = par1DataInput.readLong();
+ }
+
+ /**
+ * Gets the type byte for the tag.
+ */
+ public byte getId() {
+ return (byte) 4;
+ }
+
+ public String toString() {
+ return "" + this.data;
+ }
+
+ /**
+ * Creates a clone of the tag.
+ */
+ public NBTBase copy() {
+ return new NBTTagLong(this.getName(), this.data);
+ }
+
+ public boolean equals(Object par1Obj) {
+ if (super.equals(par1Obj)) {
+ NBTTagLong var2 = (NBTTagLong) par1Obj;
+ return this.data == var2.data;
+ } else {
+ return false;
+ }
+ }
+
+ public int hashCode() {
+ return super.hashCode() ^ (int) (this.data ^ this.data >>> 32);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/NBTTagShort.java b/sp-server/src/main/java/net/minecraft/src/NBTTagShort.java
new file mode 100644
index 0000000..15f328e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/NBTTagShort.java
@@ -0,0 +1,66 @@
+package net.minecraft.src;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+public class NBTTagShort extends NBTBase {
+ /** The short value for the tag. */
+ public short data;
+
+ public NBTTagShort(String par1Str) {
+ super(par1Str);
+ }
+
+ public NBTTagShort(String par1Str, short par2) {
+ super(par1Str);
+ this.data = par2;
+ }
+
+ /**
+ * Write the actual data contents of the tag, implemented in NBT extension
+ * classes
+ */
+ void write(DataOutput par1DataOutput) throws IOException {
+ par1DataOutput.writeShort(this.data);
+ }
+
+ /**
+ * Read the actual data contents of the tag, implemented in NBT extension
+ * classes
+ */
+ void load(DataInput par1DataInput) throws IOException {
+ this.data = par1DataInput.readShort();
+ }
+
+ /**
+ * Gets the type byte for the tag.
+ */
+ public byte getId() {
+ return (byte) 2;
+ }
+
+ public String toString() {
+ return "" + this.data;
+ }
+
+ /**
+ * Creates a clone of the tag.
+ */
+ public NBTBase copy() {
+ return new NBTTagShort(this.getName(), this.data);
+ }
+
+ public boolean equals(Object par1Obj) {
+ if (super.equals(par1Obj)) {
+ NBTTagShort var2 = (NBTTagShort) par1Obj;
+ return this.data == var2.data;
+ } else {
+ return false;
+ }
+ }
+
+ public int hashCode() {
+ return super.hashCode() ^ this.data;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/NBTTagString.java b/sp-server/src/main/java/net/minecraft/src/NBTTagString.java
new file mode 100644
index 0000000..0d2e214
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/NBTTagString.java
@@ -0,0 +1,70 @@
+package net.minecraft.src;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+public class NBTTagString extends NBTBase {
+ /** The string value for the tag (cannot be empty). */
+ public String data;
+
+ public NBTTagString(String par1Str) {
+ super(par1Str);
+ }
+
+ public NBTTagString(String par1Str, String par2Str) {
+ super(par1Str);
+ this.data = par2Str;
+
+ if (par2Str == null) {
+ throw new IllegalArgumentException("Empty string not allowed");
+ }
+ }
+
+ /**
+ * Write the actual data contents of the tag, implemented in NBT extension
+ * classes
+ */
+ void write(DataOutput par1DataOutput) throws IOException {
+ par1DataOutput.writeUTF(this.data);
+ }
+
+ /**
+ * Read the actual data contents of the tag, implemented in NBT extension
+ * classes
+ */
+ void load(DataInput par1DataInput) throws IOException {
+ this.data = par1DataInput.readUTF();
+ }
+
+ /**
+ * Gets the type byte for the tag.
+ */
+ public byte getId() {
+ return (byte) 8;
+ }
+
+ public String toString() {
+ return "" + this.data;
+ }
+
+ /**
+ * Creates a clone of the tag.
+ */
+ public NBTBase copy() {
+ return new NBTTagString(this.getName(), this.data);
+ }
+
+ public boolean equals(Object par1Obj) {
+ if (!super.equals(par1Obj)) {
+ return false;
+ } else {
+ NBTTagString var2 = (NBTTagString) par1Obj;
+ return this.data == null && var2.data == null || this.data != null && this.data.equals(var2.data);
+ }
+ }
+
+ public int hashCode() {
+ return super.hashCode() ^ this.data.hashCode();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/NetHandler.java b/sp-server/src/main/java/net/minecraft/src/NetHandler.java
new file mode 100644
index 0000000..8748687
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/NetHandler.java
@@ -0,0 +1,399 @@
+package net.minecraft.src;
+
+public abstract class NetHandler {
+ /**
+ * determine if it is a server handler
+ */
+ public abstract boolean isServerHandler();
+
+ /**
+ * Handle Packet51MapChunk (full chunk update of blocks, metadata, light levels,
+ * and optionally biome data)
+ */
+ public void handleMapChunk(Packet51MapChunk par1Packet51MapChunk) {
+ }
+
+ public void handlePackets() {
+ }
+
+ public boolean shouldBeRemoved() {
+ return true;
+ }
+
+ /**
+ * Default handler called for packets that don't have their own handlers in
+ * NetServerHandler; kicks player from the server.
+ */
+ public void unexpectedPacket(Packet par1Packet) {
+ }
+
+ public void handleErrorMessage(String par1Str, Object[] par2ArrayOfObj) {
+ }
+
+ public void handleKickDisconnect(Packet255KickDisconnect par1Packet255KickDisconnect) {
+ this.unexpectedPacket(par1Packet255KickDisconnect);
+ }
+
+ public void handleLogin(Packet1Login par1Packet1Login) {
+ this.unexpectedPacket(par1Packet1Login);
+ }
+
+ public void handleFlying(Packet10Flying par1Packet10Flying) {
+ this.unexpectedPacket(par1Packet10Flying);
+ }
+
+ public void handleMultiBlockChange(Packet52MultiBlockChange par1Packet52MultiBlockChange) {
+ this.unexpectedPacket(par1Packet52MultiBlockChange);
+ }
+
+ public void handleBlockDig(Packet14BlockDig par1Packet14BlockDig) {
+ this.unexpectedPacket(par1Packet14BlockDig);
+ }
+
+ public void handleBlockChange(Packet53BlockChange par1Packet53BlockChange) {
+ this.unexpectedPacket(par1Packet53BlockChange);
+ }
+
+ public void handleNamedEntitySpawn(Packet20NamedEntitySpawn par1Packet20NamedEntitySpawn) {
+ this.unexpectedPacket(par1Packet20NamedEntitySpawn);
+ }
+
+ public void handleEntity(Packet30Entity par1Packet30Entity) {
+ this.unexpectedPacket(par1Packet30Entity);
+ }
+
+ public void handleEntityTeleport(Packet34EntityTeleport par1Packet34EntityTeleport) {
+ this.unexpectedPacket(par1Packet34EntityTeleport);
+ }
+
+ public void handlePlace(Packet15Place par1Packet15Place) {
+ this.unexpectedPacket(par1Packet15Place);
+ }
+
+ public void handleBlockItemSwitch(Packet16BlockItemSwitch par1Packet16BlockItemSwitch) {
+ this.unexpectedPacket(par1Packet16BlockItemSwitch);
+ }
+
+ public void handleDestroyEntity(Packet29DestroyEntity par1Packet29DestroyEntity) {
+ this.unexpectedPacket(par1Packet29DestroyEntity);
+ }
+
+ public void handleCollect(Packet22Collect par1Packet22Collect) {
+ this.unexpectedPacket(par1Packet22Collect);
+ }
+
+ public void handleChat(Packet3Chat par1Packet3Chat) {
+ this.unexpectedPacket(par1Packet3Chat);
+ }
+
+ public void handleVehicleSpawn(Packet23VehicleSpawn par1Packet23VehicleSpawn) {
+ this.unexpectedPacket(par1Packet23VehicleSpawn);
+ }
+
+ public void handleAnimation(Packet18Animation par1Packet18Animation) {
+ this.unexpectedPacket(par1Packet18Animation);
+ }
+
+ /**
+ * runs registerPacket on the given Packet19EntityAction
+ */
+ public void handleEntityAction(Packet19EntityAction par1Packet19EntityAction) {
+ this.unexpectedPacket(par1Packet19EntityAction);
+ }
+
+ public void handleClientProtocol(Packet2ClientProtocol par1Packet2ClientProtocol) {
+ this.unexpectedPacket(par1Packet2ClientProtocol);
+ }
+
+ public void handleMobSpawn(Packet24MobSpawn par1Packet24MobSpawn) {
+ this.unexpectedPacket(par1Packet24MobSpawn);
+ }
+
+ public void handleUpdateTime(Packet4UpdateTime par1Packet4UpdateTime) {
+ this.unexpectedPacket(par1Packet4UpdateTime);
+ }
+
+ public void handleSpawnPosition(Packet6SpawnPosition par1Packet6SpawnPosition) {
+ this.unexpectedPacket(par1Packet6SpawnPosition);
+ }
+
+ /**
+ * Packet handler
+ */
+ public void handleEntityVelocity(Packet28EntityVelocity par1Packet28EntityVelocity) {
+ this.unexpectedPacket(par1Packet28EntityVelocity);
+ }
+
+ /**
+ * Packet handler
+ */
+ public void handleEntityMetadata(Packet40EntityMetadata par1Packet40EntityMetadata) {
+ this.unexpectedPacket(par1Packet40EntityMetadata);
+ }
+
+ /**
+ * Packet handler
+ */
+ public void handleAttachEntity(Packet39AttachEntity par1Packet39AttachEntity) {
+ this.unexpectedPacket(par1Packet39AttachEntity);
+ }
+
+ public void handleUseEntity(Packet7UseEntity par1Packet7UseEntity) {
+ this.unexpectedPacket(par1Packet7UseEntity);
+ }
+
+ /**
+ * Packet handler
+ */
+ public void handleEntityStatus(Packet38EntityStatus par1Packet38EntityStatus) {
+ this.unexpectedPacket(par1Packet38EntityStatus);
+ }
+
+ /**
+ * Recieves player health from the server and then proceeds to set it locally on
+ * the client.
+ */
+ public void handleUpdateHealth(Packet8UpdateHealth par1Packet8UpdateHealth) {
+ this.unexpectedPacket(par1Packet8UpdateHealth);
+ }
+
+ /**
+ * respawns the player
+ */
+ public void handleRespawn(Packet9Respawn par1Packet9Respawn) {
+ this.unexpectedPacket(par1Packet9Respawn);
+ }
+
+ public void handleExplosion(Packet60Explosion par1Packet60Explosion) {
+ this.unexpectedPacket(par1Packet60Explosion);
+ }
+
+ public void handleOpenWindow(Packet100OpenWindow par1Packet100OpenWindow) {
+ this.unexpectedPacket(par1Packet100OpenWindow);
+ }
+
+ public void handleCloseWindow(Packet101CloseWindow par1Packet101CloseWindow) {
+ this.unexpectedPacket(par1Packet101CloseWindow);
+ }
+
+ public void handleWindowClick(Packet102WindowClick par1Packet102WindowClick) {
+ this.unexpectedPacket(par1Packet102WindowClick);
+ }
+
+ public void handleSetSlot(Packet103SetSlot par1Packet103SetSlot) {
+ this.unexpectedPacket(par1Packet103SetSlot);
+ }
+
+ public void handleWindowItems(Packet104WindowItems par1Packet104WindowItems) {
+ this.unexpectedPacket(par1Packet104WindowItems);
+ }
+
+ /**
+ * Updates Client side signs
+ */
+ public void handleUpdateSign(Packet130UpdateSign par1Packet130UpdateSign) {
+ this.unexpectedPacket(par1Packet130UpdateSign);
+ }
+
+ public void handleUpdateProgressbar(Packet105UpdateProgressbar par1Packet105UpdateProgressbar) {
+ this.unexpectedPacket(par1Packet105UpdateProgressbar);
+ }
+
+ public void handlePlayerInventory(Packet5PlayerInventory par1Packet5PlayerInventory) {
+ this.unexpectedPacket(par1Packet5PlayerInventory);
+ }
+
+ public void handleTransaction(Packet106Transaction par1Packet106Transaction) {
+ this.unexpectedPacket(par1Packet106Transaction);
+ }
+
+ /**
+ * Packet handler
+ */
+ public void handleEntityPainting(Packet25EntityPainting par1Packet25EntityPainting) {
+ this.unexpectedPacket(par1Packet25EntityPainting);
+ }
+
+ public void handleBlockEvent(Packet54PlayNoteBlock par1Packet54PlayNoteBlock) {
+ this.unexpectedPacket(par1Packet54PlayNoteBlock);
+ }
+
+ /**
+ * runs registerPacket on the given Packet200Statistic
+ */
+ public void handleStatistic(Packet200Statistic par1Packet200Statistic) {
+ this.unexpectedPacket(par1Packet200Statistic);
+ }
+
+ public void handleSleep(Packet17Sleep par1Packet17Sleep) {
+ this.unexpectedPacket(par1Packet17Sleep);
+ }
+
+ public void handleGameEvent(Packet70GameEvent par1Packet70GameEvent) {
+ this.unexpectedPacket(par1Packet70GameEvent);
+ }
+
+ /**
+ * Handles weather packet
+ */
+ public void handleWeather(Packet71Weather par1Packet71Weather) {
+ this.unexpectedPacket(par1Packet71Weather);
+ }
+
+ /**
+ * Contains logic for handling packets containing arbitrary unique item data.
+ * Currently this is only for maps.
+ */
+ public void handleMapData(Packet131MapData par1Packet131MapData) {
+ this.unexpectedPacket(par1Packet131MapData);
+ }
+
+ public void handleDoorChange(Packet61DoorChange par1Packet61DoorChange) {
+ this.unexpectedPacket(par1Packet61DoorChange);
+ }
+
+ /**
+ * Handle a server ping packet.
+ */
+ public void handleServerPing(Packet254ServerPing par1Packet254ServerPing) {
+ this.unexpectedPacket(par1Packet254ServerPing);
+ }
+
+ /**
+ * Handle an entity effect packet.
+ */
+ public void handleEntityEffect(Packet41EntityEffect par1Packet41EntityEffect) {
+ this.unexpectedPacket(par1Packet41EntityEffect);
+ }
+
+ /**
+ * Handle a remove entity effect packet.
+ */
+ public void handleRemoveEntityEffect(Packet42RemoveEntityEffect par1Packet42RemoveEntityEffect) {
+ this.unexpectedPacket(par1Packet42RemoveEntityEffect);
+ }
+
+ /**
+ * Handle a player information packet.
+ */
+ public void handlePlayerInfo(Packet201PlayerInfo par1Packet201PlayerInfo) {
+ this.unexpectedPacket(par1Packet201PlayerInfo);
+ }
+
+ /**
+ * Handle a keep alive packet.
+ */
+ public void handleKeepAlive(Packet0KeepAlive par1Packet0KeepAlive) {
+ this.unexpectedPacket(par1Packet0KeepAlive);
+ }
+
+ /**
+ * Handle an experience packet.
+ */
+ public void handleExperience(Packet43Experience par1Packet43Experience) {
+ this.unexpectedPacket(par1Packet43Experience);
+ }
+
+ /**
+ * Handle a creative slot packet.
+ */
+ public void handleCreativeSetSlot(Packet107CreativeSetSlot par1Packet107CreativeSetSlot) {
+ this.unexpectedPacket(par1Packet107CreativeSetSlot);
+ }
+
+ /**
+ * Handle a entity experience orb packet.
+ */
+ public void handleEntityExpOrb(Packet26EntityExpOrb par1Packet26EntityExpOrb) {
+ this.unexpectedPacket(par1Packet26EntityExpOrb);
+ }
+
+ public void handleEnchantItem(Packet108EnchantItem par1Packet108EnchantItem) {
+ }
+
+ public void handleCustomPayload(Packet250CustomPayload par1Packet250CustomPayload) {
+ }
+
+ public void handleEntityHeadRotation(Packet35EntityHeadRotation par1Packet35EntityHeadRotation) {
+ this.unexpectedPacket(par1Packet35EntityHeadRotation);
+ }
+
+ public void handleTileEntityData(Packet132TileEntityData par1Packet132TileEntityData) {
+ this.unexpectedPacket(par1Packet132TileEntityData);
+ }
+
+ /**
+ * Handle a player abilities packet.
+ */
+ public void handlePlayerAbilities(Packet202PlayerAbilities par1Packet202PlayerAbilities) {
+ this.unexpectedPacket(par1Packet202PlayerAbilities);
+ }
+
+ public void handleAutoComplete(Packet203AutoComplete par1Packet203AutoComplete) {
+ this.unexpectedPacket(par1Packet203AutoComplete);
+ }
+
+ public void handleClientInfo(Packet204ClientInfo par1Packet204ClientInfo) {
+ this.unexpectedPacket(par1Packet204ClientInfo);
+ }
+
+ public void handleLevelSound(Packet62LevelSound par1Packet62LevelSound) {
+ this.unexpectedPacket(par1Packet62LevelSound);
+ }
+
+ public void handleBlockDestroy(Packet55BlockDestroy par1Packet55BlockDestroy) {
+ this.unexpectedPacket(par1Packet55BlockDestroy);
+ }
+
+ public void handleClientCommand(Packet205ClientCommand par1Packet205ClientCommand) {
+ }
+
+ public void handleMapChunks(Packet56MapChunks par1Packet56MapChunks) {
+ this.unexpectedPacket(par1Packet56MapChunks);
+ }
+
+ /**
+ * If this returns false, all packets will be queued for the main thread to
+ * handle, even if they would otherwise be processed asynchronously. Used to
+ * avoid processing packets on the client before the world has been downloaded
+ * (which happens on the main thread)
+ */
+ public boolean canProcessPacketsAsync() {
+ return false;
+ }
+
+ /**
+ * Handle a set objective packet.
+ */
+ public void handleSetObjective(Packet206SetObjective par1Packet206SetObjective) {
+ this.unexpectedPacket(par1Packet206SetObjective);
+ }
+
+ /**
+ * Handle a set score packet.
+ */
+ public void handleSetScore(Packet207SetScore par1Packet207SetScore) {
+ this.unexpectedPacket(par1Packet207SetScore);
+ }
+
+ /**
+ * Handle a set display objective packet.
+ */
+ public void handleSetDisplayObjective(Packet208SetDisplayObjective par1Packet208SetDisplayObjective) {
+ this.unexpectedPacket(par1Packet208SetDisplayObjective);
+ }
+
+ /**
+ * Handle a set player team packet.
+ */
+ public void handleSetPlayerTeam(Packet209SetPlayerTeam par1Packet209SetPlayerTeam) {
+ this.unexpectedPacket(par1Packet209SetPlayerTeam);
+ }
+
+ /**
+ * Handle a world particles packet.
+ */
+ public void handleWorldParticles(Packet63WorldParticles par1Packet63WorldParticles) {
+ this.unexpectedPacket(par1Packet63WorldParticles);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/NetLoginHandler.java b/sp-server/src/main/java/net/minecraft/src/NetLoginHandler.java
new file mode 100644
index 0000000..7bcbcf3
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/NetLoginHandler.java
@@ -0,0 +1,243 @@
+package net.minecraft.src;
+
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+import net.lax1dude.eaglercraft.sp.WorkerNetworkManager;
+import net.minecraft.server.MinecraftServer;
+
+public class NetLoginHandler extends NetHandler {
+ /** The Random object used to generate serverId hex strings. */
+ private static EaglercraftRandom rand = new EaglercraftRandom();
+
+ /** Reference to the MinecraftServer object. */
+ private final MinecraftServer mcServer;
+ public final WorkerNetworkManager myTCPConnection;
+
+ /**
+ * Returns if the login handler is finished and can be removed. It is set to
+ * true on either error or successful login.
+ */
+ public boolean finishedProcessing = false;
+
+ /** While waiting to login, if this field ++'s to 600 it will kick you. */
+ private int loginTimer = 0;
+ private String clientUsername = null;
+ private volatile boolean field_72544_i = false;
+
+ private boolean field_92079_k = false;
+
+ private int hash = 0;
+ private static int hashBase = 69696969;
+
+ private int viewDistance = 2;
+
+ public NetLoginHandler(MinecraftServer par1MinecraftServer, WorkerNetworkManager par2Socket) {
+ this.mcServer = par1MinecraftServer;
+ this.myTCPConnection = par2Socket;
+ hash = ++hashBase;
+ }
+
+ public boolean shouldBeRemoved() {
+ return this.finishedProcessing;
+ }
+
+ /**
+ * Logs the user in if a login packet is found, otherwise keeps processing
+ * network packets unless the timeout has occurred.
+ */
+ public void handlePackets() {
+ System.out.println("[Server][LOGIN][HANDLE][" + clientUsername + "]");
+ if (this.field_72544_i) {
+ this.initializePlayerConnection();
+ return;
+ }
+
+ if (this.loginTimer++ == 600) {
+ this.kickUser("Took too long to log in");
+ } else {
+ this.myTCPConnection.processReadPackets();
+ }
+ }
+
+ public boolean equals(Object o) {
+ return (o instanceof NetLoginHandler) && ((NetLoginHandler)o).hash == hash;
+ }
+
+ public int hashCode() {
+ return hash;
+ }
+
+ /**
+ * Disconnects the user with the given reason.
+ */
+ public void kickUser(String par1Str) {
+ try {
+ this.mcServer.getLogAgent().func_98233_a("Disconnecting " + this.getUsernameAndAddress() + ": " + par1Str);
+ this.myTCPConnection.addToSendQueue(new Packet255KickDisconnect(par1Str));
+ this.myTCPConnection.serverShutdown();
+ this.finishedProcessing = true;
+ } catch (Exception var3) {
+ var3.printStackTrace();
+ }
+ }
+
+ public void handleClientProtocol(Packet2ClientProtocol par1Packet2ClientProtocol) {
+ this.clientUsername = par1Packet2ClientProtocol.getUsername();
+ int var2 = 64 << 3 - par1Packet2ClientProtocol.getViewDistance();
+ if(var2 > 400) {
+ var2 = 400;
+ }
+ var2 = (var2 >> 5) + 2;
+ this.viewDistance = var2;
+ System.out.println("[Server][HANDSHAKE][" + this.clientUsername + "]");
+
+ if (!this.clientUsername.equals(StringUtils.stripControlCodes(this.clientUsername))) {
+ this.kickUser("Invalid username!");
+ } else {
+ if (par1Packet2ClientProtocol.getProtocolVersion() != 61) {
+ if (par1Packet2ClientProtocol.getProtocolVersion() > 61) {
+ this.kickUser("Outdated server!");
+ } else {
+ this.kickUser("Outdated client!");
+ }
+ }else {
+ this.initializePlayerConnection();
+ }
+ }
+ }
+
+ public void handleClientCommand(Packet205ClientCommand par1Packet205ClientCommand) {
+ if (par1Packet205ClientCommand.forceRespawn == 0) {
+ if (this.field_92079_k) {
+ this.kickUser("Duplicate login");
+ return;
+ }
+
+ this.field_92079_k = true;
+ this.field_72544_i = true;
+ }
+ }
+
+ public void handleLogin(Packet1Login par1Packet1Login) {
+ }
+
+ /**
+ * on success the specified username is connected to the minecraftInstance,
+ * otherwise they are packet255'd
+ */
+ public void initializePlayerConnection() {
+ String var1 = this.mcServer.getConfigurationManager()
+ .allowUserToConnect(this.clientUsername);
+
+ if (var1 != null) {
+ this.kickUser(var1);
+ } else {
+ EntityPlayerMP var2 = this.mcServer.getConfigurationManager().createPlayerForUser(this.clientUsername);
+ if (var2 != null) {
+ if (this.mcServer.getServerOwner().equals(this.clientUsername)) {
+ var2.renderDistance = this.viewDistance;
+ } else {
+ EntityPlayerMP fard = this.mcServer.getConfigurationManager().getPlayerEntity(this.mcServer.getServerOwner());
+ int maxRenderDistance = fard == null ? 10 : (fard.renderDistance > 10 ? 10 : fard.renderDistance);
+ var2.renderDistance = this.viewDistance > maxRenderDistance ? maxRenderDistance : this.viewDistance;
+ }
+ this.mcServer.getConfigurationManager().initializeConnectionToPlayer(this.myTCPConnection, var2);
+ }else {
+ this.kickUser("Could not construct EntityPlayerMP for '" + var1 + "'");
+ }
+ }
+
+ this.finishedProcessing = true;
+ }
+
+ public void handleErrorMessage(String par1Str, Object[] par2ArrayOfObj) {
+ this.mcServer.getLogAgent().func_98233_a(this.getUsernameAndAddress() + " lost connection");
+ this.finishedProcessing = true;
+ }
+
+ /**
+ * Handle a server ping packet.
+ */
+ public void handleServerPing(Packet254ServerPing par1Packet254ServerPing) {
+ try {
+ ServerConfigurationManager var2 = this.mcServer.getConfigurationManager();
+ String var3 = null;
+
+ if (par1Packet254ServerPing.readSuccessfully == 1) {
+ List var4 = Arrays.asList(new Serializable[] { Integer.valueOf(1), Integer.valueOf(61),
+ this.mcServer.getMinecraftVersion(), this.mcServer.getMOTD(),
+ Integer.valueOf(var2.getCurrentPlayerCount()), Integer.valueOf(var2.getMaxPlayers()) });
+ Object var6;
+
+ for (Iterator var5 = var4.iterator(); var5
+ .hasNext(); var3 = var3 + var6.toString().replaceAll("\u0000", "")) {
+ var6 = var5.next();
+
+ if (var3 == null) {
+ var3 = "\u00a7";
+ } else {
+ var3 = var3 + "\u0000";
+ }
+ }
+ } else {
+ var3 = this.mcServer.getMOTD() + "\u00a7" + var2.getCurrentPlayerCount() + "\u00a7"
+ + var2.getMaxPlayers();
+ }
+
+ this.myTCPConnection.addToSendQueue(new Packet255KickDisconnect(var3));
+ this.myTCPConnection.serverShutdown();
+
+ this.finishedProcessing = true;
+ } catch (Exception var7) {
+ var7.printStackTrace();
+ }
+ }
+
+ /**
+ * Default handler called for packets that don't have their own handlers in
+ * NetServerHandler; kicks player from the server.
+ */
+ public void unexpectedPacket(Packet par1Packet) {
+ this.kickUser("Protocol error");
+ }
+
+ public String getUsernameAndAddress() {
+ return this.clientUsername + "[EAG]";
+ }
+
+ /**
+ * determine if it is a server handler
+ */
+ public boolean isServerHandler() {
+ return true;
+ }
+
+ /**
+ * Returns the server Id randomly generated by this login handler.
+ */
+ static String getServerId(NetLoginHandler par0NetLoginHandler) {
+ return "you eagler";
+ }
+
+ /**
+ * Returns the reference to Minecraft Server.
+ */
+ static MinecraftServer getLoginMinecraftServer(NetLoginHandler par0NetLoginHandler) {
+ return par0NetLoginHandler.mcServer;
+ }
+
+ /**
+ * Returns the connecting client username.
+ */
+ static String getClientUsername(NetLoginHandler par0NetLoginHandler) {
+ return par0NetLoginHandler.clientUsername;
+ }
+
+ static boolean func_72531_a(NetLoginHandler par0NetLoginHandler, boolean par1) {
+ return par0NetLoginHandler.field_72544_i = par1;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/NetServerHandler.java b/sp-server/src/main/java/net/minecraft/src/NetServerHandler.java
new file mode 100644
index 0000000..8532631
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/NetServerHandler.java
@@ -0,0 +1,1013 @@
+package net.minecraft.src;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+import net.lax1dude.eaglercraft.sp.SkinsPlugin;
+import net.lax1dude.eaglercraft.sp.VoiceChatPlugin;
+import net.minecraft.server.MinecraftServer;
+
+public class NetServerHandler extends NetHandler {
+ /** The underlying network manager for this server handler. */
+ public final INetworkManager netManager;
+
+ /** Reference to the MinecraftServer object. */
+ private final MinecraftServer mcServer;
+
+ /** This is set to true whenever a player disconnects from the server. */
+ public boolean connectionClosed = false;
+
+ /** Reference to the EntityPlayerMP object. */
+ public EntityPlayerMP playerEntity;
+
+ /** incremented each tick */
+ private int currentTicks;
+
+ /** holds the amount of tick the player is floating */
+ private int playerInAirTime;
+ private boolean field_72584_h;
+ private int keepAliveRandomID;
+ private long keepAliveTimeSent;
+
+ /** The Java Random object. */
+ private static EaglercraftRandom rndmObj = new EaglercraftRandom();
+ private long ticksOfLastKeepAlive;
+ private int chatSpamThresholdCount = 0;
+ private int creativeItemCreationSpamThresholdTally = 0;
+
+ /** The last known x position for this connection. */
+ private double lastPosX;
+
+ /** The last known y position for this connection. */
+ private double lastPosY;
+
+ /** The last known z position for this connection. */
+ private double lastPosZ;
+
+ /** is true when the player has moved since his last movement packet */
+ private boolean hasMoved = true;
+ private IntHashMap field_72586_s = new IntHashMap();
+ private int hash = 0;
+ private static int hashCounter = 0;
+
+ public NetServerHandler(MinecraftServer par1, INetworkManager par2, EntityPlayerMP par3) {
+ this.hash = ++hashCounter;
+ this.mcServer = par1;
+ this.netManager = par2;
+ this.playerEntity = par3;
+ par3.playerNetServerHandler = this;
+ System.out.println("made nethandlerserver for '" + par3.username + "'");
+ par2.setNetHandler(this);
+ }
+
+ public boolean equals(Object o) {
+ return (o instanceof NetServerHandler) && ((NetServerHandler)o).hash == hash;
+ }
+
+ public int hashCode() {
+ return hash;
+ }
+
+ /**
+ * handle all the packets for the connection
+ */
+ public void handlePackets() {
+ this.field_72584_h = false;
+ ++this.currentTicks;
+ this.netManager.processReadPackets();
+
+ if ((long) this.currentTicks - this.ticksOfLastKeepAlive > 20L) {
+ this.ticksOfLastKeepAlive = (long) this.currentTicks;
+ this.keepAliveTimeSent = System.nanoTime() / 1000000L;
+ this.keepAliveRandomID = rndmObj.nextInt();
+ this.sendPacket(new Packet0KeepAlive(this.keepAliveRandomID));
+ }
+
+ if (this.chatSpamThresholdCount > 0) {
+ --this.chatSpamThresholdCount;
+ }
+
+ if (this.creativeItemCreationSpamThresholdTally > 0) {
+ --this.creativeItemCreationSpamThresholdTally;
+ }
+ }
+
+ public boolean shouldBeRemoved() {
+ return connectionClosed;
+ }
+
+ /**
+ * Kick the offending player and give a reason why
+ */
+ public void kickPlayer(String par1Str) {
+ if (!this.connectionClosed) {
+ this.connectionClosed = true;
+ this.playerEntity.mountEntityAndWakeUp();
+ if(par1Str != null) {
+ this.sendPacket(new Packet255KickDisconnect(par1Str));
+ }
+ this.netManager.serverShutdown();
+ this.mcServer.getConfigurationManager().sendPacketToAllPlayers(
+ new Packet3Chat(EnumChatFormatting.YELLOW + this.playerEntity.username + " left the game."));
+ this.mcServer.getConfigurationManager().playerLoggedOut(this.playerEntity);
+ }
+ }
+
+ public void handleFlying(Packet10Flying par1Packet10Flying) {
+ WorldServer var2 = this.mcServer.worldServerForDimension(this.playerEntity.dimension);
+ this.field_72584_h = true;
+
+ if (!this.playerEntity.playerConqueredTheEnd) {
+ double var3;
+
+ if (!this.hasMoved) {
+ var3 = par1Packet10Flying.yPosition - this.lastPosY;
+
+ if (par1Packet10Flying.xPosition == this.lastPosX && var3 * var3 < 0.01D
+ && par1Packet10Flying.zPosition == this.lastPosZ) {
+ this.hasMoved = true;
+ }
+ }
+
+ if (this.hasMoved) {
+ double var5;
+ double var7;
+ double var9;
+ double var13;
+
+ if (this.playerEntity.ridingEntity != null) {
+ float var34 = this.playerEntity.rotationYaw;
+ float var4 = this.playerEntity.rotationPitch;
+ this.playerEntity.ridingEntity.updateRiderPosition();
+ var5 = this.playerEntity.posX;
+ var7 = this.playerEntity.posY;
+ var9 = this.playerEntity.posZ;
+ double var35 = 0.0D;
+ var13 = 0.0D;
+
+ if (par1Packet10Flying.rotating) {
+ var34 = par1Packet10Flying.yaw;
+ var4 = par1Packet10Flying.pitch;
+ }
+
+ if (par1Packet10Flying.moving && par1Packet10Flying.yPosition == -999.0D
+ && par1Packet10Flying.stance == -999.0D) {
+ if (Math.abs(par1Packet10Flying.xPosition) > 1.0D
+ || Math.abs(par1Packet10Flying.zPosition) > 1.0D) {
+ System.err.println(this.playerEntity.username
+ + " was caught trying to crash the server with an invalid position.");
+ this.kickPlayer("Nope!");
+ return;
+ }
+
+ var35 = par1Packet10Flying.xPosition;
+ var13 = par1Packet10Flying.zPosition;
+ }
+
+ this.playerEntity.onGround = par1Packet10Flying.onGround;
+ this.playerEntity.onUpdateEntity();
+ this.playerEntity.moveEntity(var35, 0.0D, var13);
+ this.playerEntity.setPositionAndRotation(var5, var7, var9, var34, var4);
+ this.playerEntity.motionX = var35;
+ this.playerEntity.motionZ = var13;
+
+ if (this.playerEntity.ridingEntity != null) {
+ var2.uncheckedUpdateEntity(this.playerEntity.ridingEntity, true);
+ }
+
+ if (this.playerEntity.ridingEntity != null) {
+ this.playerEntity.ridingEntity.updateRiderPosition();
+ }
+
+ this.mcServer.getConfigurationManager().serverUpdateMountedMovingPlayer(this.playerEntity);
+ this.lastPosX = this.playerEntity.posX;
+ this.lastPosY = this.playerEntity.posY;
+ this.lastPosZ = this.playerEntity.posZ;
+ var2.updateEntity(this.playerEntity);
+ return;
+ }
+
+ if (this.playerEntity.isPlayerSleeping()) {
+ this.playerEntity.onUpdateEntity();
+ this.playerEntity.setPositionAndRotation(this.lastPosX, this.lastPosY, this.lastPosZ,
+ this.playerEntity.rotationYaw, this.playerEntity.rotationPitch);
+ var2.updateEntity(this.playerEntity);
+ return;
+ }
+
+ var3 = this.playerEntity.posY;
+ this.lastPosX = this.playerEntity.posX;
+ this.lastPosY = this.playerEntity.posY;
+ this.lastPosZ = this.playerEntity.posZ;
+ var5 = this.playerEntity.posX;
+ var7 = this.playerEntity.posY;
+ var9 = this.playerEntity.posZ;
+ float var11 = this.playerEntity.rotationYaw;
+ float var12 = this.playerEntity.rotationPitch;
+
+ if (par1Packet10Flying.moving && par1Packet10Flying.yPosition == -999.0D
+ && par1Packet10Flying.stance == -999.0D) {
+ par1Packet10Flying.moving = false;
+ }
+
+ if (par1Packet10Flying.moving) {
+ var5 = par1Packet10Flying.xPosition;
+ var7 = par1Packet10Flying.yPosition;
+ var9 = par1Packet10Flying.zPosition;
+ var13 = par1Packet10Flying.stance - par1Packet10Flying.yPosition;
+
+ if (!this.playerEntity.isPlayerSleeping() && (var13 > 1.65D || var13 < 0.1D)) {
+ this.kickPlayer("Illegal stance");
+ this.mcServer.getLogAgent()
+ .func_98236_b(this.playerEntity.username + " had an illegal stance: " + var13);
+ return;
+ }
+
+ if (Math.abs(par1Packet10Flying.xPosition) > 3.2E7D
+ || Math.abs(par1Packet10Flying.zPosition) > 3.2E7D) {
+ this.kickPlayer("Illegal position");
+ return;
+ }
+ }
+
+ if (par1Packet10Flying.rotating) {
+ var11 = par1Packet10Flying.yaw;
+ var12 = par1Packet10Flying.pitch;
+ }
+
+ this.playerEntity.onUpdateEntity();
+ this.playerEntity.ySize = 0.0F;
+ this.playerEntity.setPositionAndRotation(this.lastPosX, this.lastPosY, this.lastPosZ, var11, var12);
+
+ if (!this.hasMoved) {
+ return;
+ }
+
+ var13 = var5 - this.playerEntity.posX;
+ double var15 = var7 - this.playerEntity.posY;
+ double var17 = var9 - this.playerEntity.posZ;
+ double var19 = Math.min(Math.abs(var13), Math.abs(this.playerEntity.motionX));
+ double var21 = Math.min(Math.abs(var15), Math.abs(this.playerEntity.motionY));
+ double var23 = Math.min(Math.abs(var17), Math.abs(this.playerEntity.motionZ));
+ double var25 = var19 * var19 + var21 * var21 + var23 * var23;
+
+ if (var25 > 100.0D && (!this.mcServer.isSinglePlayer()
+ || !this.mcServer.getServerOwner().equals(this.playerEntity.username))) {
+ this.mcServer.getLogAgent().func_98236_b(this.playerEntity.username + " moved too quickly! " + var13
+ + "," + var15 + "," + var17 + " (" + var19 + ", " + var21 + ", " + var23 + ")");
+ this.setPlayerLocation(this.lastPosX, this.lastPosY, this.lastPosZ, this.playerEntity.rotationYaw,
+ this.playerEntity.rotationPitch);
+ return;
+ }
+
+ float var27 = 0.0625F;
+ boolean var28 = var2.getCollidingBoundingBoxes(this.playerEntity,
+ this.playerEntity.boundingBox.copy().contract((double) var27, (double) var27, (double) var27))
+ .isEmpty();
+
+ if (this.playerEntity.onGround && !par1Packet10Flying.onGround && var15 > 0.0D) {
+ this.playerEntity.addExhaustion(0.2F);
+ }
+
+ this.playerEntity.moveEntity(var13, var15, var17);
+ this.playerEntity.onGround = par1Packet10Flying.onGround;
+ this.playerEntity.addMovementStat(var13, var15, var17);
+ double var29 = var15;
+ var13 = var5 - this.playerEntity.posX;
+ var15 = var7 - this.playerEntity.posY;
+
+ if (var15 > -0.5D || var15 < 0.5D) {
+ var15 = 0.0D;
+ }
+
+ var17 = var9 - this.playerEntity.posZ;
+ var25 = var13 * var13 + var15 * var15 + var17 * var17;
+ boolean var31 = false;
+
+ if (var25 > 0.0625D && !this.playerEntity.isPlayerSleeping()
+ && !this.playerEntity.theItemInWorldManager.isCreative()) {
+ var31 = true;
+ this.mcServer.getLogAgent().func_98236_b(this.playerEntity.username + " moved wrongly!");
+ }
+
+ this.playerEntity.setPositionAndRotation(var5, var7, var9, var11, var12);
+ boolean var32 = var2.getCollidingBoundingBoxes(this.playerEntity,
+ this.playerEntity.boundingBox.copy().contract((double) var27, (double) var27, (double) var27))
+ .isEmpty();
+
+ if (var28 && (var31 || !var32) && !this.playerEntity.isPlayerSleeping()) {
+ this.setPlayerLocation(this.lastPosX, this.lastPosY, this.lastPosZ, var11, var12);
+ return;
+ }
+
+ AxisAlignedBB var33 = this.playerEntity.boundingBox.copy()
+ .expand((double) var27, (double) var27, (double) var27).addCoord(0.0D, -0.55D, 0.0D);
+
+ if (!this.mcServer.isFlightAllowed() && !this.playerEntity.theItemInWorldManager.isCreative()
+ && !var2.checkBlockCollision(var33)) {
+ if (var29 >= -0.03125D) {
+ ++this.playerInAirTime;
+
+ if (this.playerInAirTime > 80) {
+ this.mcServer.getLogAgent()
+ .func_98236_b(this.playerEntity.username + " was kicked for floating too long!");
+ this.kickPlayer("Flying is not enabled on this server");
+ return;
+ }
+ }
+ } else {
+ this.playerInAirTime = 0;
+ }
+
+ this.playerEntity.onGround = par1Packet10Flying.onGround;
+ this.mcServer.getConfigurationManager().serverUpdateMountedMovingPlayer(this.playerEntity);
+ this.playerEntity.handleFalling(this.playerEntity.posY - var3, par1Packet10Flying.onGround);
+ }
+ }
+ }
+
+ /**
+ * Moves the player to the specified destination and rotation
+ */
+ public void setPlayerLocation(double par1, double par3, double par5, float par7, float par8) {
+ this.hasMoved = false;
+ this.lastPosX = par1;
+ this.lastPosY = par3;
+ this.lastPosZ = par5;
+ this.playerEntity.setPositionAndRotation(par1, par3, par5, par7, par8);
+ this.playerEntity.playerNetServerHandler.sendPacket(
+ new Packet13PlayerLookMove(par1, par3 + 1.6200000047683716D, par3, par5, par7, par8, false));
+ }
+
+ public void handleBlockDig(Packet14BlockDig par1Packet14BlockDig) {
+ WorldServer var2 = this.mcServer.worldServerForDimension(this.playerEntity.dimension);
+
+ if (par1Packet14BlockDig.status == 4) {
+ this.playerEntity.dropOneItem(false);
+ } else if (par1Packet14BlockDig.status == 3) {
+ this.playerEntity.dropOneItem(true);
+ } else if (par1Packet14BlockDig.status == 5) {
+ this.playerEntity.stopUsingItem();
+ } else {
+ boolean var3 = false;
+
+ if (par1Packet14BlockDig.status == 0) {
+ var3 = true;
+ }
+
+ if (par1Packet14BlockDig.status == 1) {
+ var3 = true;
+ }
+
+ if (par1Packet14BlockDig.status == 2) {
+ var3 = true;
+ }
+
+ int var4 = par1Packet14BlockDig.xPosition;
+ int var5 = par1Packet14BlockDig.yPosition;
+ int var6 = par1Packet14BlockDig.zPosition;
+
+ if (var3) {
+ double var7 = this.playerEntity.posX - ((double) var4 + 0.5D);
+ double var9 = this.playerEntity.posY - ((double) var5 + 0.5D) + 1.5D;
+ double var11 = this.playerEntity.posZ - ((double) var6 + 0.5D);
+ double var13 = var7 * var7 + var9 * var9 + var11 * var11;
+
+ if (var13 > 36.0D) {
+ return;
+ }
+
+ if (var5 >= this.mcServer.getBuildLimit()) {
+ return;
+ }
+ }
+
+ if (par1Packet14BlockDig.status == 0) {
+ if (!this.mcServer.func_96290_a(var2, var4, var5, var6, this.playerEntity)) {
+ this.playerEntity.theItemInWorldManager.onBlockClicked(var4, var5, var6, par1Packet14BlockDig.face);
+ } else {
+ this.playerEntity.playerNetServerHandler
+ .sendPacket(new Packet53BlockChange(var4, var5, var6, var2));
+ }
+ } else if (par1Packet14BlockDig.status == 2) {
+ this.playerEntity.theItemInWorldManager.blockRemoving(var4, var5, var6);
+
+ if (var2.getBlockId(var4, var5, var6) != 0) {
+ this.playerEntity.playerNetServerHandler
+ .sendPacket(new Packet53BlockChange(var4, var5, var6, var2));
+ }
+ } else if (par1Packet14BlockDig.status == 1) {
+ this.playerEntity.theItemInWorldManager.cancelDestroyingBlock(var4, var5, var6);
+
+ if (var2.getBlockId(var4, var5, var6) != 0) {
+ this.playerEntity.playerNetServerHandler
+ .sendPacket(new Packet53BlockChange(var4, var5, var6, var2));
+ }
+ }
+ }
+ }
+
+ public void handlePlace(Packet15Place par1Packet15Place) {
+ WorldServer var2 = this.mcServer.worldServerForDimension(this.playerEntity.dimension);
+ ItemStack var3 = this.playerEntity.inventory.getCurrentItem();
+ boolean var4 = false;
+ int var5 = par1Packet15Place.getXPosition();
+ int var6 = par1Packet15Place.getYPosition();
+ int var7 = par1Packet15Place.getZPosition();
+ int var8 = par1Packet15Place.getDirection();
+
+ if (par1Packet15Place.getDirection() == 255) {
+ if (var3 == null) {
+ return;
+ }
+
+ this.playerEntity.theItemInWorldManager.tryUseItem(this.playerEntity, var2, var3);
+ } else if (par1Packet15Place.getYPosition() >= this.mcServer.getBuildLimit() - 1
+ && (par1Packet15Place.getDirection() == 1
+ || par1Packet15Place.getYPosition() >= this.mcServer.getBuildLimit())) {
+ this.playerEntity.playerNetServerHandler.sendPacket(new Packet3Chat(
+ "" + EnumChatFormatting.GRAY + "Height limit for building is " + this.mcServer.getBuildLimit()));
+ var4 = true;
+ } else {
+ if (this.hasMoved
+ && this.playerEntity.getDistanceSq((double) var5 + 0.5D, (double) var6 + 0.5D,
+ (double) var7 + 0.5D) < 64.0D
+ && !this.mcServer.func_96290_a(var2, var5, var6, var7, this.playerEntity)) {
+ this.playerEntity.theItemInWorldManager.activateBlockOrUseItem(this.playerEntity, var2, var3, var5,
+ var6, var7, var8, par1Packet15Place.getXOffset(), par1Packet15Place.getYOffset(),
+ par1Packet15Place.getZOffset());
+ }
+
+ var4 = true;
+ }
+
+ if (var4) {
+ this.playerEntity.playerNetServerHandler.sendPacket(new Packet53BlockChange(var5, var6, var7, var2));
+
+ if (var8 == 0) {
+ --var6;
+ }
+
+ if (var8 == 1) {
+ ++var6;
+ }
+
+ if (var8 == 2) {
+ --var7;
+ }
+
+ if (var8 == 3) {
+ ++var7;
+ }
+
+ if (var8 == 4) {
+ --var5;
+ }
+
+ if (var8 == 5) {
+ ++var5;
+ }
+
+ this.playerEntity.playerNetServerHandler.sendPacket(new Packet53BlockChange(var5, var6, var7, var2));
+ }
+
+ var3 = this.playerEntity.inventory.getCurrentItem();
+
+ if (var3 != null && var3.stackSize == 0) {
+ this.playerEntity.inventory.mainInventory[this.playerEntity.inventory.currentItem] = null;
+ var3 = null;
+ }
+
+ if (var3 == null || var3.getMaxItemUseDuration() == 0) {
+ this.playerEntity.isChangingQuantityOnly = true;
+ this.playerEntity.inventory.mainInventory[this.playerEntity.inventory.currentItem] = ItemStack
+ .copyItemStack(this.playerEntity.inventory.mainInventory[this.playerEntity.inventory.currentItem]);
+ Slot var9 = this.playerEntity.openContainer.getSlotFromInventory(this.playerEntity.inventory,
+ this.playerEntity.inventory.currentItem);
+ this.playerEntity.openContainer.detectAndSendChanges();
+ this.playerEntity.isChangingQuantityOnly = false;
+
+ if (!ItemStack.areItemStacksEqual(this.playerEntity.inventory.getCurrentItem(),
+ par1Packet15Place.getItemStack())) {
+ this.sendPacket(new Packet103SetSlot(this.playerEntity.openContainer.windowId, var9.slotNumber,
+ this.playerEntity.inventory.getCurrentItem()));
+ }
+ }
+ }
+
+ public void handleErrorMessage(String par1Str, Object[] par2ArrayOfObj) {
+ this.mcServer.getLogAgent().func_98233_a(this.playerEntity.username + " lost connection: " + par1Str);
+ this.mcServer.getConfigurationManager().sendPacketToAllPlayers(new Packet3Chat(
+ EnumChatFormatting.YELLOW + this.playerEntity.getTranslatedEntityName() + " left the game."));
+ this.mcServer.getConfigurationManager().playerLoggedOut(this.playerEntity);
+ this.connectionClosed = true;
+
+ if (this.mcServer.isSinglePlayer() && this.playerEntity.username.equals(this.mcServer.getServerOwner())) {
+ this.mcServer.getLogAgent().func_98233_a("Stopping singleplayer server as player logged out");
+ this.mcServer.initiateShutdown();
+ }
+ }
+
+ /**
+ * Default handler called for packets that don't have their own handlers in
+ * NetServerHandler; kicks player from the server.
+ */
+ public void unexpectedPacket(Packet par1Packet) {
+ this.mcServer.getLogAgent()
+ .func_98236_b(this.getClass() + " wasn\'t prepared to deal with a " + par1Packet.getClass());
+ this.kickPlayer("Protocol error, unexpected packet");
+ }
+
+ /**
+ * Adds the packet to the underlying network manager's send queue.
+ */
+ public void sendPacket(Packet par1Packet) {
+ if (par1Packet instanceof Packet3Chat) {
+ Packet3Chat var2 = (Packet3Chat) par1Packet;
+ int var3 = this.playerEntity.getChatVisibility();
+
+ if (var3 == 2) {
+ return;
+ }
+
+ if (var3 == 1 && !var2.getIsServer()) {
+ return;
+ }
+ }
+
+ this.netManager.addToSendQueue(par1Packet);
+ }
+
+ public void handleBlockItemSwitch(Packet16BlockItemSwitch par1Packet16BlockItemSwitch) {
+ if (par1Packet16BlockItemSwitch.id >= 0 && par1Packet16BlockItemSwitch.id < InventoryPlayer.getHotbarSize()) {
+ this.playerEntity.inventory.currentItem = par1Packet16BlockItemSwitch.id;
+ } else {
+ this.mcServer.getLogAgent()
+ .func_98236_b(this.playerEntity.username + " tried to set an invalid carried item");
+ }
+ }
+
+ public void handleChat(Packet3Chat par1Packet3Chat) {
+ if (this.playerEntity.getChatVisibility() == 2) {
+ this.sendPacket(new Packet3Chat("Cannot send chat message."));
+ } else {
+ String var2 = par1Packet3Chat.message;
+
+ if (var2.length() > 100) {
+ this.kickPlayer("Chat message too long");
+ } else {
+ var2 = var2.trim();
+
+ for (int var3 = 0; var3 < var2.length(); ++var3) {
+ if (!ChatAllowedCharacters.isAllowedCharacter(var2.charAt(var3))) {
+ this.kickPlayer("Illegal characters in chat");
+ return;
+ }
+ }
+
+ if (var2.startsWith("/")) {
+ this.handleSlashCommand(var2);
+ } else {
+ if (this.playerEntity.getChatVisibility() == 1) {
+ this.sendPacket(new Packet3Chat("Cannot send chat message."));
+ return;
+ }
+
+ var2 = "<" + this.playerEntity.getTranslatedEntityName() + "> " + var2;
+ this.mcServer.getLogAgent().func_98233_a(var2);
+ this.mcServer.getConfigurationManager().sendPacketToAllPlayers(new Packet3Chat(var2, false));
+ }
+
+ this.chatSpamThresholdCount += 20;
+
+ if (this.chatSpamThresholdCount > 200
+ && !this.mcServer.getConfigurationManager().areCommandsAllowed(this.playerEntity.username)) {
+ this.kickPlayer("disconnect.spam");
+ }
+ }
+ }
+ }
+
+ /**
+ * Processes a / command
+ */
+ private void handleSlashCommand(String par1Str) {
+ this.mcServer.getCommandManager().executeCommand(this.playerEntity, par1Str);
+ }
+
+ public void handleAnimation(Packet18Animation par1Packet18Animation) {
+ if (par1Packet18Animation.animate == 1) {
+ this.playerEntity.swingItem();
+ }
+ }
+
+ /**
+ * runs registerPacket on the given Packet19EntityAction
+ */
+ public void handleEntityAction(Packet19EntityAction par1Packet19EntityAction) {
+ if (par1Packet19EntityAction.state == 1) {
+ this.playerEntity.setSneaking(true);
+ } else if (par1Packet19EntityAction.state == 2) {
+ this.playerEntity.setSneaking(false);
+ } else if (par1Packet19EntityAction.state == 4) {
+ this.playerEntity.setSprinting(true);
+ } else if (par1Packet19EntityAction.state == 5) {
+ this.playerEntity.setSprinting(false);
+ } else if (par1Packet19EntityAction.state == 3) {
+ this.playerEntity.wakeUpPlayer(false, true, true);
+ this.hasMoved = false;
+ }
+ }
+
+ public void handleKickDisconnect(Packet255KickDisconnect par1Packet255KickDisconnect) {
+ this.netManager.networkShutdown("disconnect.quitting", new Object[0]);
+ }
+
+ /**
+ * return the number of chuckDataPackets from the netManager
+ */
+ public int getNumChunkDataPackets() {
+ return this.netManager.getNumChunkDataPackets();
+ }
+
+ public void handleUseEntity(Packet7UseEntity par1Packet7UseEntity) {
+ WorldServer var2 = this.mcServer.worldServerForDimension(this.playerEntity.dimension);
+ Entity var3 = var2.getEntityByID(par1Packet7UseEntity.targetEntity);
+
+ if (var3 != null) {
+ boolean var4 = this.playerEntity.canEntityBeSeen(var3);
+ double var5 = 36.0D;
+
+ if (!var4) {
+ var5 = 9.0D;
+ }
+
+ if (this.playerEntity.getDistanceSqToEntity(var3) < var5) {
+ if (par1Packet7UseEntity.isLeftClick == 0) {
+ this.playerEntity.interactWith(var3);
+ } else if (par1Packet7UseEntity.isLeftClick == 1) {
+ this.playerEntity.attackTargetEntityWithCurrentItem(var3);
+ }
+ }
+ }
+ }
+
+ public void handleClientCommand(Packet205ClientCommand par1Packet205ClientCommand) {
+ if (par1Packet205ClientCommand.forceRespawn == 1) {
+ if (this.playerEntity.playerConqueredTheEnd) {
+ this.playerEntity = this.mcServer.getConfigurationManager().recreatePlayerEntity(this.playerEntity, 0, true);
+ } else if (this.playerEntity.getServerForPlayer().getWorldInfo().isHardcoreModeEnabled()) {
+ if (this.mcServer.isSinglePlayer()
+ && this.playerEntity.username.equals(this.mcServer.getServerOwner())) {
+ this.playerEntity.playerNetServerHandler
+ .kickPlayer("You have died. Game over, man, it\'s game over!");
+ this.mcServer.deleteWorldAndStopServer();
+ }
+ } else {
+ if (this.playerEntity.getHealth() > 0) {
+ return;
+ }
+
+ this.playerEntity = this.mcServer.getConfigurationManager().recreatePlayerEntity(this.playerEntity, 0, false);
+ }
+ }
+ }
+
+ /**
+ * If this returns false, all packets will be queued for the main thread to
+ * handle, even if they would otherwise be processed asynchronously. Used to
+ * avoid processing packets on the client before the world has been downloaded
+ * (which happens on the main thread)
+ */
+ public boolean canProcessPacketsAsync() {
+ return true;
+ }
+
+ /**
+ * respawns the player
+ */
+ public void handleRespawn(Packet9Respawn par1Packet9Respawn) {
+ }
+
+ public void handleCloseWindow(Packet101CloseWindow par1Packet101CloseWindow) {
+ this.playerEntity.closeCraftingGui();
+ }
+
+ public void handleWindowClick(Packet102WindowClick par1Packet102WindowClick) {
+ if (this.playerEntity.openContainer.windowId == par1Packet102WindowClick.window_Id
+ && this.playerEntity.openContainer.getCanCraft(this.playerEntity)) {
+ ItemStack var2 = this.playerEntity.openContainer.slotClick(par1Packet102WindowClick.inventorySlot,
+ par1Packet102WindowClick.mouseClick, par1Packet102WindowClick.holdingShift, this.playerEntity);
+
+ if (ItemStack.areItemStacksEqual(par1Packet102WindowClick.itemStack, var2)) {
+ this.playerEntity.playerNetServerHandler.sendPacket(new Packet106Transaction(
+ par1Packet102WindowClick.window_Id, par1Packet102WindowClick.action, true));
+ this.playerEntity.isChangingQuantityOnly = true;
+ this.playerEntity.openContainer.detectAndSendChanges();
+ this.playerEntity.updateHeldItem();
+ this.playerEntity.isChangingQuantityOnly = false;
+ } else {
+ this.field_72586_s.addKey(this.playerEntity.openContainer.windowId,
+ Short.valueOf(par1Packet102WindowClick.action));
+ this.playerEntity.playerNetServerHandler.sendPacket(new Packet106Transaction(
+ par1Packet102WindowClick.window_Id, par1Packet102WindowClick.action, false));
+ this.playerEntity.openContainer.setCanCraft(this.playerEntity, false);
+ ArrayList var3 = new ArrayList();
+
+ for (int var4 = 0; var4 < this.playerEntity.openContainer.inventorySlots.size(); ++var4) {
+ var3.add(((Slot) this.playerEntity.openContainer.inventorySlots.get(var4)).getStack());
+ }
+
+ this.playerEntity.updateCraftingInventory(this.playerEntity.openContainer, var3);
+ }
+ }
+ }
+
+ public void handleEnchantItem(Packet108EnchantItem par1Packet108EnchantItem) {
+ if (this.playerEntity.openContainer.windowId == par1Packet108EnchantItem.windowId
+ && this.playerEntity.openContainer.getCanCraft(this.playerEntity)) {
+ this.playerEntity.openContainer.enchantItem(this.playerEntity, par1Packet108EnchantItem.enchantment);
+ this.playerEntity.openContainer.detectAndSendChanges();
+ }
+ }
+
+ /**
+ * Handle a creative slot packet.
+ */
+ public void handleCreativeSetSlot(Packet107CreativeSetSlot par1Packet107CreativeSetSlot) {
+ if (this.playerEntity.theItemInWorldManager.isCreative()) {
+ boolean var2 = par1Packet107CreativeSetSlot.slot < 0;
+ ItemStack var3 = par1Packet107CreativeSetSlot.itemStack;
+ boolean var4 = par1Packet107CreativeSetSlot.slot >= 1
+ && par1Packet107CreativeSetSlot.slot < 36 + InventoryPlayer.getHotbarSize();
+ boolean var5 = var3 == null
+ || var3.itemID < Item.itemsList.length && var3.itemID >= 0 && Item.itemsList[var3.itemID] != null;
+ boolean var6 = var3 == null || var3.getItemDamage() >= 0 && var3.getItemDamage() >= 0
+ && var3.stackSize <= 64 && var3.stackSize > 0;
+
+ if (var4 && var5 && var6) {
+ if (var3 == null) {
+ this.playerEntity.inventoryContainer.putStackInSlot(par1Packet107CreativeSetSlot.slot,
+ (ItemStack) null);
+ } else {
+ this.playerEntity.inventoryContainer.putStackInSlot(par1Packet107CreativeSetSlot.slot, var3);
+ }
+
+ this.playerEntity.inventoryContainer.setCanCraft(this.playerEntity, true);
+ } else if (var2 && var5 && var6 && this.creativeItemCreationSpamThresholdTally < 200) {
+ this.creativeItemCreationSpamThresholdTally += 20;
+ EntityItem var7 = this.playerEntity.dropPlayerItem(var3);
+
+ if (var7 != null) {
+ var7.setAgeToCreativeDespawnTime();
+ }
+ }
+ }
+ }
+
+ public void handleTransaction(Packet106Transaction par1Packet106Transaction) {
+ Short var2 = (Short) this.field_72586_s.lookup(this.playerEntity.openContainer.windowId);
+
+ if (var2 != null && par1Packet106Transaction.shortWindowId == var2.shortValue()
+ && this.playerEntity.openContainer.windowId == par1Packet106Transaction.windowId
+ && !this.playerEntity.openContainer.getCanCraft(this.playerEntity)) {
+ this.playerEntity.openContainer.setCanCraft(this.playerEntity, true);
+ }
+ }
+
+ /**
+ * Updates Client side signs
+ */
+ public void handleUpdateSign(Packet130UpdateSign par1Packet130UpdateSign) {
+ WorldServer var2 = this.mcServer.worldServerForDimension(this.playerEntity.dimension);
+
+ if (var2.blockExists(par1Packet130UpdateSign.xPosition, par1Packet130UpdateSign.yPosition,
+ par1Packet130UpdateSign.zPosition)) {
+ TileEntity var3 = var2.getBlockTileEntity(par1Packet130UpdateSign.xPosition,
+ par1Packet130UpdateSign.yPosition, par1Packet130UpdateSign.zPosition);
+
+ if (var3 instanceof TileEntitySign) {
+ TileEntitySign var4 = (TileEntitySign) var3;
+
+ if (!var4.isEditable()) {
+ this.mcServer.logWarning(
+ "Player " + this.playerEntity.username + " just tried to change non-editable sign");
+ return;
+ }
+ }
+
+ int var6;
+ int var8;
+
+ for (var8 = 0; var8 < 4; ++var8) {
+ boolean var5 = true;
+
+ if (par1Packet130UpdateSign.signLines[var8].length() > 15) {
+ var5 = false;
+ } else {
+ for (var6 = 0; var6 < par1Packet130UpdateSign.signLines[var8].length(); ++var6) {
+ if (ChatAllowedCharacters.allowedCharacters
+ .indexOf(par1Packet130UpdateSign.signLines[var8].charAt(var6)) < 0) {
+ var5 = false;
+ }
+ }
+ }
+
+ if (!var5) {
+ par1Packet130UpdateSign.signLines[var8] = "!?";
+ }
+ }
+
+ if (var3 instanceof TileEntitySign) {
+ var8 = par1Packet130UpdateSign.xPosition;
+ int var9 = par1Packet130UpdateSign.yPosition;
+ var6 = par1Packet130UpdateSign.zPosition;
+ TileEntitySign var7 = (TileEntitySign) var3;
+ System.arraycopy(par1Packet130UpdateSign.signLines, 0, var7.signText, 0, 4);
+ var7.onInventoryChanged();
+ var2.markBlockForUpdate(var8, var9, var6);
+ }
+ }
+ }
+
+ /**
+ * Handle a keep alive packet.
+ */
+ public void handleKeepAlive(Packet0KeepAlive par1Packet0KeepAlive) {
+ if (par1Packet0KeepAlive.randomId == this.keepAliveRandomID) {
+ int var2 = (int) (System.nanoTime() / 1000000L - this.keepAliveTimeSent);
+ this.playerEntity.ping = (this.playerEntity.ping * 3 + var2) / 4;
+ }
+ }
+
+ /**
+ * determine if it is a server handler
+ */
+ public boolean isServerHandler() {
+ return true;
+ }
+
+ /**
+ * Handle a player abilities packet.
+ */
+ public void handlePlayerAbilities(Packet202PlayerAbilities par1Packet202PlayerAbilities) {
+ this.playerEntity.capabilities.isFlying = par1Packet202PlayerAbilities.getFlying()
+ && this.playerEntity.capabilities.allowFlying;
+ }
+
+ public void handleAutoComplete(Packet203AutoComplete par1Packet203AutoComplete) {
+ StringBuilder var2 = new StringBuilder();
+ String var4;
+
+ for (Iterator var3 = this.mcServer
+ .getPossibleCompletions(this.playerEntity, par1Packet203AutoComplete.getText()).iterator(); var3
+ .hasNext(); var2.append(var4)) {
+ var4 = (String) var3.next();
+
+ if (var2.length() > 0) {
+ var2.append("\u0000");
+ }
+ }
+
+ this.playerEntity.playerNetServerHandler.sendPacket(new Packet203AutoComplete(var2.toString()));
+ }
+
+ public void handleClientInfo(Packet204ClientInfo par1Packet204ClientInfo) {
+ this.playerEntity.updateClientInfo(par1Packet204ClientInfo);
+ }
+
+ public void handleCustomPayload(Packet250CustomPayload par1Packet250CustomPayload) {
+ DataInputStream var2;
+ ItemStack var3;
+ ItemStack var4;
+
+ if ("MC|BEdit".equals(par1Packet250CustomPayload.channel)) {
+ try {
+ var2 = new DataInputStream(new ByteArrayInputStream(par1Packet250CustomPayload.data));
+ var3 = Packet.readItemStack(var2);
+
+ if (!ItemWritableBook.validBookTagPages(var3.getTagCompound())) {
+ throw new IOException("Invalid book tag!");
+ }
+
+ var4 = this.playerEntity.inventory.getCurrentItem();
+
+ if (var3 != null && var3.itemID == Item.writableBook.itemID && var3.itemID == var4.itemID) {
+ var4.setTagInfo("pages", var3.getTagCompound().getTagList("pages"));
+ }
+ } catch (Exception var12) {
+ var12.printStackTrace();
+ }
+ } else if ("MC|BSign".equals(par1Packet250CustomPayload.channel)) {
+ try {
+ var2 = new DataInputStream(new ByteArrayInputStream(par1Packet250CustomPayload.data));
+ var3 = Packet.readItemStack(var2);
+
+ if (!ItemEditableBook.validBookTagContents(var3.getTagCompound())) {
+ throw new IOException("Invalid book tag!");
+ }
+
+ var4 = this.playerEntity.inventory.getCurrentItem();
+
+ if (var3 != null && var3.itemID == Item.writtenBook.itemID && var4.itemID == Item.writableBook.itemID) {
+ var4.setTagInfo("author", new NBTTagString("author", this.playerEntity.username));
+ var4.setTagInfo("title", new NBTTagString("title", var3.getTagCompound().getString("title")));
+ var4.setTagInfo("pages", var3.getTagCompound().getTagList("pages"));
+ var4.itemID = Item.writtenBook.itemID;
+ }
+ } catch (Exception var11) {
+ var11.printStackTrace();
+ }
+ } else {
+ int var13;
+
+ if ("MC|TrSel".equals(par1Packet250CustomPayload.channel)) {
+ try {
+ var2 = new DataInputStream(new ByteArrayInputStream(par1Packet250CustomPayload.data));
+ var13 = var2.readInt();
+ Container var15 = this.playerEntity.openContainer;
+
+ if (var15 instanceof ContainerMerchant) {
+ ((ContainerMerchant) var15).setCurrentRecipeIndex(var13);
+ }
+ } catch (Exception var10) {
+ var10.printStackTrace();
+ }
+ } else {
+ int var17;
+
+ if ("MC|AdvCdm".equals(par1Packet250CustomPayload.channel)) {
+ if (!this.mcServer.isCommandBlockEnabled()) {
+ this.playerEntity.sendChatToPlayer(
+ this.playerEntity.translateString("advMode.notEnabled", new Object[0]));
+ } else if (this.playerEntity.canCommandSenderUseCommand(2, "")
+ && this.playerEntity.capabilities.isCreativeMode) {
+ try {
+ var2 = new DataInputStream(new ByteArrayInputStream(par1Packet250CustomPayload.data));
+ var13 = var2.readInt();
+ var17 = var2.readInt();
+ int var5 = var2.readInt();
+ String var6 = Packet.readString(var2, 256);
+ TileEntity var7 = this.playerEntity.worldObj.getBlockTileEntity(var13, var17, var5);
+
+ if (var7 != null && var7 instanceof TileEntityCommandBlock) {
+ ((TileEntityCommandBlock) var7).setCommand(var6);
+ this.playerEntity.worldObj.markBlockForUpdate(var13, var17, var5);
+ this.playerEntity.sendChatToPlayer("Command set: " + var6);
+ }
+ } catch (Exception var9) {
+ var9.printStackTrace();
+ }
+ } else {
+ this.playerEntity.sendChatToPlayer(
+ this.playerEntity.translateString("advMode.notAllowed", new Object[0]));
+ }
+ } else if ("MC|Beacon".equals(par1Packet250CustomPayload.channel)) {
+ if (this.playerEntity.openContainer instanceof ContainerBeacon) {
+ try {
+ var2 = new DataInputStream(new ByteArrayInputStream(par1Packet250CustomPayload.data));
+ var13 = var2.readInt();
+ var17 = var2.readInt();
+ ContainerBeacon var18 = (ContainerBeacon) this.playerEntity.openContainer;
+ Slot var19 = var18.getSlot(0);
+
+ if (var19.getHasStack()) {
+ var19.decrStackSize(1);
+ TileEntityBeacon var20 = var18.getBeacon();
+ var20.setPrimaryEffect(var13);
+ var20.setSecondaryEffect(var17);
+ var20.onInventoryChanged();
+ }
+ } catch (Exception var8) {
+ var8.printStackTrace();
+ }
+ }
+ } else if ("MC|ItemName".equals(par1Packet250CustomPayload.channel)
+ && this.playerEntity.openContainer instanceof ContainerRepair) {
+ ContainerRepair var14 = (ContainerRepair) this.playerEntity.openContainer;
+
+ if (par1Packet250CustomPayload.data != null && par1Packet250CustomPayload.data.length >= 1) {
+ String var16 = ChatAllowedCharacters
+ .filerAllowedCharacters(new String(par1Packet250CustomPayload.data));
+
+ if (var16.length() <= 30) {
+ var14.updateItemName(var16);
+ }
+ } else {
+ var14.updateItemName("");
+ }
+ } else {
+ if(!SkinsPlugin.handleMessage(playerEntity, par1Packet250CustomPayload)) {
+ if(!VoiceChatPlugin.handleMessage(playerEntity, par1Packet250CustomPayload)) {
+ System.err.println("Unexpected Packet250CustomPayload: '" + par1Packet250CustomPayload.channel + "'");
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/NextTickListEntry.java b/sp-server/src/main/java/net/minecraft/src/NextTickListEntry.java
new file mode 100644
index 0000000..d528040
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/NextTickListEntry.java
@@ -0,0 +1,84 @@
+package net.minecraft.src;
+
+public class NextTickListEntry implements Comparable {
+ /** The id number for the next tick entry */
+ private static long nextTickEntryID = 0L;
+
+ /** X position this tick is occuring at */
+ public int xCoord;
+
+ /** Y position this tick is occuring at */
+ public int yCoord;
+
+ /** Z position this tick is occuring at */
+ public int zCoord;
+
+ /**
+ * blockID of the scheduled tick (ensures when the tick occurs its still for
+ * this block)
+ */
+ public int blockID;
+
+ /** Time this tick is scheduled to occur at */
+ public long scheduledTime;
+ public int field_82754_f;
+
+ /** The id of the tick entry */
+ private long tickEntryID;
+
+ public NextTickListEntry(int par1, int par2, int par3, int par4) {
+ this.tickEntryID = (long) (nextTickEntryID++);
+ this.xCoord = par1;
+ this.yCoord = par2;
+ this.zCoord = par3;
+ this.blockID = par4;
+ }
+
+ public boolean equals(Object par1Obj) {
+ if (!(par1Obj instanceof NextTickListEntry)) {
+ return false;
+ } else {
+ NextTickListEntry var2 = (NextTickListEntry) par1Obj;
+ return this.xCoord == var2.xCoord && this.yCoord == var2.yCoord && this.zCoord == var2.zCoord
+ && Block.isAssociatedBlockID(this.blockID, var2.blockID);
+ }
+ }
+
+ public int hashCode() {
+ return (this.xCoord * 1024 * 1024 + this.zCoord * 1024 + this.yCoord) * 256;
+ }
+
+ /**
+ * Sets the scheduled time for this tick entry
+ */
+ public NextTickListEntry setScheduledTime(long par1) {
+ this.scheduledTime = par1;
+ return this;
+ }
+
+ public void func_82753_a(int par1) {
+ this.field_82754_f = par1;
+ }
+
+ /**
+ * Compares this tick entry to another tick entry for sorting purposes. Compared
+ * first based on the scheduled time and second based on tickEntryID.
+ */
+ public int comparer(NextTickListEntry par1NextTickListEntry) {
+ return this.scheduledTime < par1NextTickListEntry.scheduledTime ? -1
+ : (this.scheduledTime > par1NextTickListEntry.scheduledTime ? 1
+ : (this.field_82754_f != par1NextTickListEntry.field_82754_f
+ ? this.field_82754_f - par1NextTickListEntry.field_82754_f
+ : (this.tickEntryID < par1NextTickListEntry.tickEntryID ? -1
+ : (this.tickEntryID > par1NextTickListEntry.tickEntryID ? 1 : 0))));
+ }
+
+ public String toString() {
+ return this.blockID + ": (" + this.xCoord + ", " + this.yCoord + ", " + this.zCoord + "), " + this.scheduledTime
+ + ", " + this.field_82754_f + ", " + this.tickEntryID;
+ }
+
+ public int compareTo(Object par1Obj) {
+ return this.comparer((NextTickListEntry) par1Obj);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/NibbleArray.java b/sp-server/src/main/java/net/minecraft/src/NibbleArray.java
new file mode 100644
index 0000000..a5a27e1
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/NibbleArray.java
@@ -0,0 +1,59 @@
+package net.minecraft.src;
+
+public class NibbleArray {
+ /**
+ * Byte array of data stored in this holder. Possibly a light map or some chunk
+ * data. Data is accessed in 4-bit pieces.
+ */
+ public final byte[] data;
+
+ /**
+ * Log base 2 of the chunk height (128); applied as a shift on Z coordinate
+ */
+ private final int depthBits;
+
+ /**
+ * Log base 2 of the chunk height (128) * width (16); applied as a shift on X
+ * coordinate
+ */
+ private final int depthBitsPlusFour;
+
+ public NibbleArray(int par1, int par2) {
+ this.data = new byte[par1 >> 1];
+ this.depthBits = par2;
+ this.depthBitsPlusFour = par2 + 4;
+ }
+
+ public NibbleArray(byte[] par1ArrayOfByte, int par2) {
+ this.data = par1ArrayOfByte;
+ this.depthBits = par2;
+ this.depthBitsPlusFour = par2 + 4;
+ }
+
+ /**
+ * Returns the nibble of data corresponding to the passed in x, y, z. y is at
+ * most 6 bits, z is at most 4.
+ */
+ public int get(int par1, int par2, int par3) {
+ int var4 = par2 << this.depthBitsPlusFour | par3 << this.depthBits | par1;
+ int var5 = var4 >> 1;
+ int var6 = var4 & 1;
+ return var6 == 0 ? this.data[var5] & 15 : this.data[var5] >> 4 & 15;
+ }
+
+ /**
+ * Arguments are x, y, z, val. Sets the nibble of data at x << 11 | z << 7 | y
+ * to val.
+ */
+ public void set(int par1, int par2, int par3, int par4) {
+ int var5 = par2 << this.depthBitsPlusFour | par3 << this.depthBits | par1;
+ int var6 = var5 >> 1;
+ int var7 = var5 & 1;
+
+ if (var7 == 0) {
+ this.data[var6] = (byte) (this.data[var6] & 240 | par4 & 15);
+ } else {
+ this.data[var6] = (byte) (this.data[var6] & 15 | (par4 & 15) << 4);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/NibbleArrayReader.java b/sp-server/src/main/java/net/minecraft/src/NibbleArrayReader.java
new file mode 100644
index 0000000..1d045f2
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/NibbleArrayReader.java
@@ -0,0 +1,20 @@
+package net.minecraft.src;
+
+public class NibbleArrayReader {
+ public final byte[] data;
+ private final int depthBits;
+ private final int depthBitsPlusFour;
+
+ public NibbleArrayReader(byte[] par1ArrayOfByte, int par2) {
+ this.data = par1ArrayOfByte;
+ this.depthBits = par2;
+ this.depthBitsPlusFour = par2 + 4;
+ }
+
+ public int get(int par1, int par2, int par3) {
+ int var4 = par1 << this.depthBitsPlusFour | par3 << this.depthBits | par2;
+ int var5 = var4 >> 1;
+ int var6 = var4 & 1;
+ return var6 == 0 ? this.data[var5] & 15 : this.data[var5] >> 4 & 15;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/NoiseGenerator.java b/sp-server/src/main/java/net/minecraft/src/NoiseGenerator.java
new file mode 100644
index 0000000..53e6d05
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/NoiseGenerator.java
@@ -0,0 +1,4 @@
+package net.minecraft.src;
+
+public abstract class NoiseGenerator {
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/NoiseGeneratorOctaves.java b/sp-server/src/main/java/net/minecraft/src/NoiseGeneratorOctaves.java
new file mode 100644
index 0000000..ec203e0
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/NoiseGeneratorOctaves.java
@@ -0,0 +1,65 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class NoiseGeneratorOctaves extends NoiseGenerator {
+ /**
+ * Collection of noise generation functions. Output is combined to produce
+ * different octaves of noise.
+ */
+ private NoiseGeneratorPerlin[] generatorCollection;
+ private int octaves;
+
+ public NoiseGeneratorOctaves(EaglercraftRandom par1Random, int par2) {
+ this.octaves = par2;
+ this.generatorCollection = new NoiseGeneratorPerlin[par2];
+
+ for (int var3 = 0; var3 < par2; ++var3) {
+ this.generatorCollection[var3] = new NoiseGeneratorPerlin(par1Random);
+ }
+ }
+
+ /**
+ * pars:(par2,3,4=noiseOffset ; so that adjacent noise segments connect)
+ * (pars5,6,7=x,y,zArraySize),(pars8,10,12 = x,y,z noiseScale)
+ */
+ public double[] generateNoiseOctaves(double[] par1ArrayOfDouble, int par2, int par3, int par4, int par5, int par6,
+ int par7, double par8, double par10, double par12) {
+ if (par1ArrayOfDouble == null) {
+ par1ArrayOfDouble = new double[par5 * par6 * par7];
+ } else {
+ for (int var14 = 0; var14 < par1ArrayOfDouble.length; ++var14) {
+ par1ArrayOfDouble[var14] = 0.0D;
+ }
+ }
+
+ double var27 = 1.0D;
+
+ for (int var16 = 0; var16 < this.octaves; ++var16) {
+ double var17 = (double) par2 * var27 * par8;
+ double var19 = (double) par3 * var27 * par10;
+ double var21 = (double) par4 * var27 * par12;
+ long var23 = MathHelper.floor_double_long(var17);
+ long var25 = MathHelper.floor_double_long(var21);
+ var17 -= (double) var23;
+ var21 -= (double) var25;
+ var23 %= 16777216L;
+ var25 %= 16777216L;
+ var17 += (double) var23;
+ var21 += (double) var25;
+ this.generatorCollection[var16].populateNoiseArray(par1ArrayOfDouble, var17, var19, var21, par5, par6, par7,
+ par8 * var27, par10 * var27, par12 * var27, var27);
+ var27 /= 2.0D;
+ }
+
+ return par1ArrayOfDouble;
+ }
+
+ /**
+ * Bouncer function to the main one with some default arguments.
+ */
+ public double[] generateNoiseOctaves(double[] par1ArrayOfDouble, int par2, int par3, int par4, int par5,
+ double par6, double par8, double par10) {
+ return this.generateNoiseOctaves(par1ArrayOfDouble, par2, 10, par3, par4, 1, par5, par6, 1.0D, par8);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/NoiseGeneratorPerlin.java b/sp-server/src/main/java/net/minecraft/src/NoiseGeneratorPerlin.java
new file mode 100644
index 0000000..1b4c3e2
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/NoiseGeneratorPerlin.java
@@ -0,0 +1,199 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class NoiseGeneratorPerlin extends NoiseGenerator {
+ private int[] permutations;
+ public double xCoord;
+ public double yCoord;
+ public double zCoord;
+
+ public NoiseGeneratorPerlin() {
+ this(new EaglercraftRandom());
+ }
+
+ public NoiseGeneratorPerlin(EaglercraftRandom par1Random) {
+ this.permutations = new int[512];
+ this.xCoord = par1Random.nextDouble() * 256.0D;
+ this.yCoord = par1Random.nextDouble() * 256.0D;
+ this.zCoord = par1Random.nextDouble() * 256.0D;
+ int var2;
+
+ for (var2 = 0; var2 < 256; this.permutations[var2] = var2++) {
+ ;
+ }
+
+ for (var2 = 0; var2 < 256; ++var2) {
+ int var3 = par1Random.nextInt(256 - var2) + var2;
+ int var4 = this.permutations[var2];
+ this.permutations[var2] = this.permutations[var3];
+ this.permutations[var3] = var4;
+ this.permutations[var2 + 256] = this.permutations[var2];
+ }
+ }
+
+ public final double lerp(double par1, double par3, double par5) {
+ return par3 + par1 * (par5 - par3);
+ }
+
+ public final double func_76309_a(int par1, double par2, double par4) {
+ int var6 = par1 & 15;
+ double var7 = (double) (1 - ((var6 & 8) >> 3)) * par2;
+ double var9 = var6 < 4 ? 0.0D : (var6 != 12 && var6 != 14 ? par4 : par2);
+ return ((var6 & 1) == 0 ? var7 : -var7) + ((var6 & 2) == 0 ? var9 : -var9);
+ }
+
+ public final double grad(int par1, double par2, double par4, double par6) {
+ int var8 = par1 & 15;
+ double var9 = var8 < 8 ? par2 : par4;
+ double var11 = var8 < 4 ? par4 : (var8 != 12 && var8 != 14 ? par6 : par2);
+ return ((var8 & 1) == 0 ? var9 : -var9) + ((var8 & 2) == 0 ? var11 : -var11);
+ }
+
+ /**
+ * pars: noiseArray , xOffset , yOffset , zOffset , xSize , ySize , zSize ,
+ * xScale, yScale , zScale , noiseScale. noiseArray should be xSize*ySize*zSize
+ * in size
+ */
+ public void populateNoiseArray(double[] par1ArrayOfDouble, double par2, double par4, double par6, int par8,
+ int par9, int par10, double par11, double par13, double par15, double par17) {
+ int var10001;
+ int var19;
+ int var22;
+ double var31;
+ double var35;
+ int var37;
+ double var38;
+ int var40;
+ int var41;
+ double var42;
+ int var75;
+
+ if (par9 == 1) {
+ boolean var64 = false;
+ boolean var65 = false;
+ boolean var21 = false;
+ boolean var68 = false;
+ double var70 = 0.0D;
+ double var73 = 0.0D;
+ var75 = 0;
+ double var77 = 1.0D / par17;
+
+ for (int var30 = 0; var30 < par8; ++var30) {
+ var31 = par2 + (double) var30 * par11 + this.xCoord;
+ int var78 = (int) var31;
+
+ if (var31 < (double) var78) {
+ --var78;
+ }
+
+ int var34 = var78 & 255;
+ var31 -= (double) var78;
+ var35 = var31 * var31 * var31 * (var31 * (var31 * 6.0D - 15.0D) + 10.0D);
+
+ for (var37 = 0; var37 < par10; ++var37) {
+ var38 = par6 + (double) var37 * par15 + this.zCoord;
+ var40 = (int) var38;
+
+ if (var38 < (double) var40) {
+ --var40;
+ }
+
+ var41 = var40 & 255;
+ var38 -= (double) var40;
+ var42 = var38 * var38 * var38 * (var38 * (var38 * 6.0D - 15.0D) + 10.0D);
+ var19 = this.permutations[var34] + 0;
+ int var66 = this.permutations[var19] + var41;
+ int var67 = this.permutations[var34 + 1] + 0;
+ var22 = this.permutations[var67] + var41;
+ var70 = this.lerp(var35, this.func_76309_a(this.permutations[var66], var31, var38),
+ this.grad(this.permutations[var22], var31 - 1.0D, 0.0D, var38));
+ var73 = this.lerp(var35, this.grad(this.permutations[var66 + 1], var31, 0.0D, var38 - 1.0D),
+ this.grad(this.permutations[var22 + 1], var31 - 1.0D, 0.0D, var38 - 1.0D));
+ double var79 = this.lerp(var42, var70, var73);
+ var10001 = var75++;
+ par1ArrayOfDouble[var10001] += var79 * var77;
+ }
+ }
+ } else {
+ var19 = 0;
+ double var20 = 1.0D / par17;
+ var22 = -1;
+ boolean var23 = false;
+ boolean var24 = false;
+ boolean var25 = false;
+ boolean var26 = false;
+ boolean var27 = false;
+ boolean var28 = false;
+ double var29 = 0.0D;
+ var31 = 0.0D;
+ double var33 = 0.0D;
+ var35 = 0.0D;
+
+ for (var37 = 0; var37 < par8; ++var37) {
+ var38 = par2 + (double) var37 * par11 + this.xCoord;
+ var40 = (int) var38;
+
+ if (var38 < (double) var40) {
+ --var40;
+ }
+
+ var41 = var40 & 255;
+ var38 -= (double) var40;
+ var42 = var38 * var38 * var38 * (var38 * (var38 * 6.0D - 15.0D) + 10.0D);
+
+ for (int var44 = 0; var44 < par10; ++var44) {
+ double var45 = par6 + (double) var44 * par15 + this.zCoord;
+ int var47 = (int) var45;
+
+ if (var45 < (double) var47) {
+ --var47;
+ }
+
+ int var48 = var47 & 255;
+ var45 -= (double) var47;
+ double var49 = var45 * var45 * var45 * (var45 * (var45 * 6.0D - 15.0D) + 10.0D);
+
+ for (int var51 = 0; var51 < par9; ++var51) {
+ double var52 = par4 + (double) var51 * par13 + this.yCoord;
+ int var54 = (int) var52;
+
+ if (var52 < (double) var54) {
+ --var54;
+ }
+
+ int var55 = var54 & 255;
+ var52 -= (double) var54;
+ double var56 = var52 * var52 * var52 * (var52 * (var52 * 6.0D - 15.0D) + 10.0D);
+
+ if (var51 == 0 || var55 != var22) {
+ var22 = var55;
+ int var69 = this.permutations[var41] + var55;
+ int var71 = this.permutations[var69] + var48;
+ int var72 = this.permutations[var69 + 1] + var48;
+ int var74 = this.permutations[var41 + 1] + var55;
+ var75 = this.permutations[var74] + var48;
+ int var76 = this.permutations[var74 + 1] + var48;
+ var29 = this.lerp(var42, this.grad(this.permutations[var71], var38, var52, var45),
+ this.grad(this.permutations[var75], var38 - 1.0D, var52, var45));
+ var31 = this.lerp(var42, this.grad(this.permutations[var72], var38, var52 - 1.0D, var45),
+ this.grad(this.permutations[var76], var38 - 1.0D, var52 - 1.0D, var45));
+ var33 = this.lerp(var42,
+ this.grad(this.permutations[var71 + 1], var38, var52, var45 - 1.0D),
+ this.grad(this.permutations[var75 + 1], var38 - 1.0D, var52, var45 - 1.0D));
+ var35 = this.lerp(var42,
+ this.grad(this.permutations[var72 + 1], var38, var52 - 1.0D, var45 - 1.0D),
+ this.grad(this.permutations[var76 + 1], var38 - 1.0D, var52 - 1.0D, var45 - 1.0D));
+ }
+
+ double var58 = this.lerp(var56, var29, var31);
+ double var60 = this.lerp(var56, var33, var35);
+ double var62 = this.lerp(var49, var58, var60);
+ var10001 = var19++;
+ par1ArrayOfDouble[var10001] += var62 * var20;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/NumberInvalidException.java b/sp-server/src/main/java/net/minecraft/src/NumberInvalidException.java
new file mode 100644
index 0000000..9112275
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/NumberInvalidException.java
@@ -0,0 +1,11 @@
+package net.minecraft.src;
+
+public class NumberInvalidException extends CommandException {
+ public NumberInvalidException() {
+ this("commands.generic.num.invalid", new Object[0]);
+ }
+
+ public NumberInvalidException(String par1Str, Object... par2ArrayOfObj) {
+ super(par1Str, par2ArrayOfObj);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet.java b/sp-server/src/main/java/net/minecraft/src/Packet.java
new file mode 100644
index 0000000..5acefce
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet.java
@@ -0,0 +1,397 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.net.Socket;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import net.lax1dude.eaglercraft.sp.SysUtil;
+
+public abstract class Packet {
+ /** Maps packet id to packet class */
+ public static IntHashMap packetIdToClassMap = new IntHashMap();
+
+ /** Maps packet class to packet id */
+ private static Map packetClassToIdMap = new HashMap();
+
+ /** List of the client's packet IDs. */
+ private static Set clientPacketIdList = new HashSet();
+
+ /** List of the server's packet IDs. */
+ private static Set serverPacketIdList = new HashSet();
+ public ILogAgent field_98193_m;
+
+ /** the system time in milliseconds when this packet was created. */
+ public final long creationTimeMillis = SysUtil.steadyTimeMillis();
+ public static long receivedID;
+ public static long receivedSize;
+
+ /** Assumed to be sequential by the profiler. */
+ public static long sentID;
+ public static long sentSize;
+
+ /**
+ * Only true for Packet51MapChunk, Packet52MultiBlockChange, Packet53BlockChange
+ * and Packet59ComplexEntity. Used to separate them into a different send queue.
+ */
+ public boolean isChunkDataPacket = false;
+
+ /**
+ * Adds a two way mapping between the packet ID and packet class.
+ */
+ static void addIdClassMapping(int par0, boolean par1, boolean par2, Class par3Class) {
+ if (packetIdToClassMap.containsItem(par0)) {
+ throw new IllegalArgumentException("Duplicate packet id:" + par0);
+ } else if (packetClassToIdMap.containsKey(par3Class)) {
+ throw new IllegalArgumentException("Duplicate packet class:" + par3Class);
+ } else {
+ packetIdToClassMap.addKey(par0, par3Class);
+ packetClassToIdMap.put(par3Class, Integer.valueOf(par0));
+
+ if (par1) {
+ clientPacketIdList.add(Integer.valueOf(par0));
+ }
+
+ if (par2) {
+ serverPacketIdList.add(Integer.valueOf(par0));
+ }
+ }
+ }
+
+ /**
+ * Returns a new instance of the specified Packet class.
+ */
+ public static Packet getNewPacket(ILogAgent par0ILogAgent, int par1) {
+ try {
+ Class var2 = (Class) packetIdToClassMap.lookup(par1);
+ return var2 == null ? null : (Packet) var2.newInstance();
+ } catch (Exception var3) {
+ var3.printStackTrace();
+ par0ILogAgent.logSevere("Skipping packet with id " + par1);
+ return null;
+ }
+ }
+
+ /**
+ * Writes a byte array to the DataOutputStream
+ */
+ public static void writeByteArray(DataOutputStream par0DataOutputStream, byte[] par1ArrayOfByte)
+ throws IOException {
+ par0DataOutputStream.writeShort(par1ArrayOfByte.length);
+ par0DataOutputStream.write(par1ArrayOfByte);
+ }
+
+ /**
+ * the first short in the stream indicates the number of bytes to read
+ */
+ public static byte[] readBytesFromStream(DataInputStream par0DataInputStream) throws IOException {
+ short var1 = par0DataInputStream.readShort();
+
+ if (var1 < 0) {
+ throw new IOException("Key was smaller than nothing! Weird key!");
+ } else {
+ byte[] var2 = new byte[var1];
+ par0DataInputStream.readFully(var2);
+ return var2;
+ }
+ }
+
+ /**
+ * Returns the ID of this packet.
+ */
+ public final int getPacketId() {
+ return ((Integer) packetClassToIdMap.get(this.getClass())).intValue();
+ }
+
+ /**
+ * Read a packet, prefixed by its ID, from the data stream.
+ */
+ public static Packet readPacket(ILogAgent par0ILogAgent, DataInputStream par1DataInputStream, boolean par2,
+ Socket par3Socket) throws IOException {
+ boolean var4 = false;
+ Packet var5 = null;
+ int var6 = par3Socket.getSoTimeout();
+ int var9;
+
+ try {
+ var9 = par1DataInputStream.read();
+
+ if (var9 == -1) {
+ return null;
+ }
+
+ if (par2 && !serverPacketIdList.contains(Integer.valueOf(var9))
+ || !par2 && !clientPacketIdList.contains(Integer.valueOf(var9))) {
+ throw new IOException("Bad packet id " + var9);
+ }
+
+ var5 = getNewPacket(par0ILogAgent, var9);
+
+ if (var5 == null) {
+ throw new IOException("Bad packet id " + var9);
+ }
+
+ var5.field_98193_m = par0ILogAgent;
+
+ if (var5 instanceof Packet254ServerPing) {
+ par3Socket.setSoTimeout(1500);
+ }
+
+ var5.readPacketData(par1DataInputStream);
+ ++receivedID;
+ receivedSize += (long) var5.getPacketSize();
+ } catch (EOFException var8) {
+ par0ILogAgent.logSevere("Reached end of stream");
+ return null;
+ }
+
+ PacketCount.countPacket(var9, (long) var5.getPacketSize());
+ ++receivedID;
+ receivedSize += (long) var5.getPacketSize();
+ par3Socket.setSoTimeout(var6);
+ return var5;
+ }
+
+ /**
+ * Writes a packet, prefixed by its ID, to the data stream.
+ */
+ public static void writePacket(Packet par0Packet, DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.write(par0Packet.getPacketId());
+ par0Packet.writePacketData(par1DataOutputStream);
+ ++sentID;
+ sentSize += (long) par0Packet.getPacketSize();
+ }
+
+ /**
+ * Writes a String to the DataOutputStream
+ */
+ public static void writeString(String par0Str, DataOutputStream par1DataOutputStream) throws IOException {
+ if (par0Str.length() > 32767) {
+ throw new IOException("String too big");
+ } else {
+ par1DataOutputStream.writeShort(par0Str.length());
+ par1DataOutputStream.writeChars(par0Str);
+ }
+ }
+
+ /**
+ * Reads a string from a packet
+ */
+ public static String readString(DataInputStream par0DataInputStream, int par1) throws IOException {
+ short var2 = par0DataInputStream.readShort();
+
+ if (var2 > par1) {
+ throw new IOException("Received string length longer than maximum allowed (" + var2 + " > " + par1 + ")");
+ } else if (var2 < 0) {
+ throw new IOException("Received string length is less than zero! Weird string!");
+ } else {
+ StringBuilder var3 = new StringBuilder();
+
+ for (int var4 = 0; var4 < var2; ++var4) {
+ var3.append(par0DataInputStream.readChar());
+ }
+
+ return var3.toString();
+ }
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public abstract void readPacketData(DataInputStream var1) throws IOException;
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public abstract void writePacketData(DataOutputStream var1) throws IOException;
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public abstract void processPacket(NetHandler var1);
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public abstract int getPacketSize();
+
+ /**
+ * only false for the abstract Packet class, all real packets return true
+ */
+ public boolean isRealPacket() {
+ return false;
+ }
+
+ /**
+ * eg return packet30entity.entityId == entityId; WARNING : will throw if you
+ * compare a packet to a different packet class
+ */
+ public boolean containsSameEntityIDAs(Packet par1Packet) {
+ return false;
+ }
+
+ /**
+ * If this returns true, the packet may be processed on any thread; otherwise it
+ * is queued for the main thread to handle.
+ */
+ public boolean canProcessAsync() {
+ return false;
+ }
+
+ public String toString() {
+ String var1 = this.getClass().getSimpleName();
+ return var1;
+ }
+
+ /**
+ * Reads a ItemStack from the InputStream
+ */
+ public static ItemStack readItemStack(DataInputStream par0DataInputStream) throws IOException {
+ ItemStack var1 = null;
+ short var2 = par0DataInputStream.readShort();
+
+ if (var2 >= 0) {
+ byte var3 = par0DataInputStream.readByte();
+ short var4 = par0DataInputStream.readShort();
+ var1 = new ItemStack(var2, var3, var4);
+ var1.stackTagCompound = readNBTTagCompound(par0DataInputStream);
+ }
+
+ return var1;
+ }
+
+ /**
+ * Writes the ItemStack's ID (short), then size (byte), then damage. (short)
+ */
+ public static void writeItemStack(ItemStack par0ItemStack, DataOutputStream par1DataOutputStream)
+ throws IOException {
+ if (par0ItemStack == null) {
+ par1DataOutputStream.writeShort(-1);
+ } else {
+ par1DataOutputStream.writeShort(par0ItemStack.itemID);
+ par1DataOutputStream.writeByte(par0ItemStack.stackSize);
+ par1DataOutputStream.writeShort(par0ItemStack.getItemDamage());
+ NBTTagCompound var2 = null;
+
+ if (par0ItemStack.getItem().isDamageable() || par0ItemStack.getItem().getShareTag()) {
+ var2 = par0ItemStack.stackTagCompound;
+ }
+
+ writeNBTTagCompound(var2, par1DataOutputStream);
+ }
+ }
+
+ /**
+ * Reads a compressed NBTTagCompound from the InputStream
+ */
+ public static NBTTagCompound readNBTTagCompound(DataInputStream par0DataInputStream) throws IOException {
+ short var1 = par0DataInputStream.readShort();
+
+ if (var1 < 0) {
+ return null;
+ } else {
+ byte[] var2 = new byte[var1];
+ par0DataInputStream.readFully(var2);
+ return CompressedStreamTools.decompress(var2);
+ }
+ }
+
+ /**
+ * Writes a compressed NBTTagCompound to the OutputStream
+ */
+ protected static void writeNBTTagCompound(NBTTagCompound par0NBTTagCompound, DataOutputStream par1DataOutputStream)
+ throws IOException {
+ if (par0NBTTagCompound == null) {
+ par1DataOutputStream.writeShort(-1);
+ } else {
+ byte[] var2 = CompressedStreamTools.compress(par0NBTTagCompound);
+ par1DataOutputStream.writeShort((short) var2.length);
+ par1DataOutputStream.write(var2);
+ }
+ }
+
+ static {
+ addIdClassMapping(0, true, true, Packet0KeepAlive.class);
+ addIdClassMapping(1, true, true, Packet1Login.class);
+ addIdClassMapping(2, false, true, Packet2ClientProtocol.class);
+ addIdClassMapping(3, true, true, Packet3Chat.class);
+ addIdClassMapping(4, true, false, Packet4UpdateTime.class);
+ addIdClassMapping(5, true, false, Packet5PlayerInventory.class);
+ addIdClassMapping(6, true, false, Packet6SpawnPosition.class);
+ addIdClassMapping(7, false, true, Packet7UseEntity.class);
+ addIdClassMapping(8, true, false, Packet8UpdateHealth.class);
+ addIdClassMapping(9, true, true, Packet9Respawn.class);
+ addIdClassMapping(10, true, true, Packet10Flying.class);
+ addIdClassMapping(11, true, true, Packet11PlayerPosition.class);
+ addIdClassMapping(12, true, true, Packet12PlayerLook.class);
+ addIdClassMapping(13, true, true, Packet13PlayerLookMove.class);
+ addIdClassMapping(14, false, true, Packet14BlockDig.class);
+ addIdClassMapping(15, false, true, Packet15Place.class);
+ addIdClassMapping(16, true, true, Packet16BlockItemSwitch.class);
+ addIdClassMapping(17, true, false, Packet17Sleep.class);
+ addIdClassMapping(18, true, true, Packet18Animation.class);
+ addIdClassMapping(19, false, true, Packet19EntityAction.class);
+ addIdClassMapping(20, true, false, Packet20NamedEntitySpawn.class);
+ addIdClassMapping(22, true, false, Packet22Collect.class);
+ addIdClassMapping(23, true, false, Packet23VehicleSpawn.class);
+ addIdClassMapping(24, true, false, Packet24MobSpawn.class);
+ addIdClassMapping(25, true, false, Packet25EntityPainting.class);
+ addIdClassMapping(26, true, false, Packet26EntityExpOrb.class);
+ addIdClassMapping(28, true, false, Packet28EntityVelocity.class);
+ addIdClassMapping(29, true, false, Packet29DestroyEntity.class);
+ addIdClassMapping(30, true, false, Packet30Entity.class);
+ addIdClassMapping(31, true, false, Packet31RelEntityMove.class);
+ addIdClassMapping(32, true, false, Packet32EntityLook.class);
+ addIdClassMapping(33, true, false, Packet33RelEntityMoveLook.class);
+ addIdClassMapping(34, true, false, Packet34EntityTeleport.class);
+ addIdClassMapping(35, true, false, Packet35EntityHeadRotation.class);
+ addIdClassMapping(38, true, false, Packet38EntityStatus.class);
+ addIdClassMapping(39, true, false, Packet39AttachEntity.class);
+ addIdClassMapping(40, true, false, Packet40EntityMetadata.class);
+ addIdClassMapping(41, true, false, Packet41EntityEffect.class);
+ addIdClassMapping(42, true, false, Packet42RemoveEntityEffect.class);
+ addIdClassMapping(43, true, false, Packet43Experience.class);
+ addIdClassMapping(51, true, false, Packet51MapChunk.class);
+ addIdClassMapping(52, true, false, Packet52MultiBlockChange.class);
+ addIdClassMapping(53, true, false, Packet53BlockChange.class);
+ addIdClassMapping(54, true, false, Packet54PlayNoteBlock.class);
+ addIdClassMapping(55, true, false, Packet55BlockDestroy.class);
+ addIdClassMapping(56, true, false, Packet56MapChunks.class);
+ addIdClassMapping(60, true, false, Packet60Explosion.class);
+ addIdClassMapping(61, true, false, Packet61DoorChange.class);
+ addIdClassMapping(62, true, false, Packet62LevelSound.class);
+ addIdClassMapping(63, true, false, Packet63WorldParticles.class);
+ addIdClassMapping(70, true, false, Packet70GameEvent.class);
+ addIdClassMapping(71, true, false, Packet71Weather.class);
+ addIdClassMapping(100, true, false, Packet100OpenWindow.class);
+ addIdClassMapping(101, true, true, Packet101CloseWindow.class);
+ addIdClassMapping(102, false, true, Packet102WindowClick.class);
+ addIdClassMapping(103, true, false, Packet103SetSlot.class);
+ addIdClassMapping(104, true, false, Packet104WindowItems.class);
+ addIdClassMapping(105, true, false, Packet105UpdateProgressbar.class);
+ addIdClassMapping(106, true, true, Packet106Transaction.class);
+ addIdClassMapping(107, true, true, Packet107CreativeSetSlot.class);
+ addIdClassMapping(108, false, true, Packet108EnchantItem.class);
+ addIdClassMapping(130, true, true, Packet130UpdateSign.class);
+ addIdClassMapping(131, true, false, Packet131MapData.class);
+ addIdClassMapping(132, true, false, Packet132TileEntityData.class);
+ addIdClassMapping(200, true, false, Packet200Statistic.class);
+ addIdClassMapping(201, true, false, Packet201PlayerInfo.class);
+ addIdClassMapping(202, true, true, Packet202PlayerAbilities.class);
+ addIdClassMapping(203, true, true, Packet203AutoComplete.class);
+ addIdClassMapping(204, false, true, Packet204ClientInfo.class);
+ addIdClassMapping(205, false, true, Packet205ClientCommand.class);
+ addIdClassMapping(206, true, false, Packet206SetObjective.class);
+ addIdClassMapping(207, true, false, Packet207SetScore.class);
+ addIdClassMapping(208, true, false, Packet208SetDisplayObjective.class);
+ addIdClassMapping(209, true, false, Packet209SetPlayerTeam.class);
+ addIdClassMapping(250, true, true, Packet250CustomPayload.class);
+ addIdClassMapping(254, false, true, Packet254ServerPing.class);
+ addIdClassMapping(255, true, true, Packet255KickDisconnect.class);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet0KeepAlive.java b/sp-server/src/main/java/net/minecraft/src/Packet0KeepAlive.java
new file mode 100644
index 0000000..d92837d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet0KeepAlive.java
@@ -0,0 +1,67 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet0KeepAlive extends Packet {
+ public int randomId;
+
+ public Packet0KeepAlive() {
+ }
+
+ public Packet0KeepAlive(int par1) {
+ this.randomId = par1;
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleKeepAlive(this);
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.randomId = par1DataInputStream.readInt();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeInt(this.randomId);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 4;
+ }
+
+ /**
+ * only false for the abstract Packet class, all real packets return true
+ */
+ public boolean isRealPacket() {
+ return true;
+ }
+
+ /**
+ * eg return packet30entity.entityId == entityId; WARNING : will throw if you
+ * compare a packet to a different packet class
+ */
+ public boolean containsSameEntityIDAs(Packet par1Packet) {
+ return true;
+ }
+
+ /**
+ * If this returns true, the packet may be processed on any thread; otherwise it
+ * is queued for the main thread to handle.
+ */
+ public boolean canProcessAsync() {
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet100OpenWindow.java b/sp-server/src/main/java/net/minecraft/src/Packet100OpenWindow.java
new file mode 100644
index 0000000..2a5ce81
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet100OpenWindow.java
@@ -0,0 +1,65 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet100OpenWindow extends Packet {
+ public int windowId;
+ public int inventoryType;
+ public String windowTitle;
+ public int slotsCount;
+
+ /**
+ * If false, the client will look up a string like "window.minecart". If true,
+ * the client uses what the server provides.
+ */
+ public boolean useProvidedWindowTitle;
+
+ public Packet100OpenWindow() {
+ }
+
+ public Packet100OpenWindow(int par1, int par2, String par3Str, int par4, boolean par5) {
+ this.windowId = par1;
+ this.inventoryType = par2;
+ this.windowTitle = par3Str;
+ this.slotsCount = par4;
+ this.useProvidedWindowTitle = par5;
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleOpenWindow(this);
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.windowId = par1DataInputStream.readByte() & 255;
+ this.inventoryType = par1DataInputStream.readByte() & 255;
+ this.windowTitle = readString(par1DataInputStream, 32);
+ this.slotsCount = par1DataInputStream.readByte() & 255;
+ this.useProvidedWindowTitle = par1DataInputStream.readBoolean();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeByte(this.windowId & 255);
+ par1DataOutputStream.writeByte(this.inventoryType & 255);
+ writeString(this.windowTitle, par1DataOutputStream);
+ par1DataOutputStream.writeByte(this.slotsCount & 255);
+ par1DataOutputStream.writeBoolean(this.useProvidedWindowTitle);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 4 + this.windowTitle.length();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet101CloseWindow.java b/sp-server/src/main/java/net/minecraft/src/Packet101CloseWindow.java
new file mode 100644
index 0000000..da55399
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet101CloseWindow.java
@@ -0,0 +1,44 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet101CloseWindow extends Packet {
+ public int windowId;
+
+ public Packet101CloseWindow() {
+ }
+
+ public Packet101CloseWindow(int par1) {
+ this.windowId = par1;
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleCloseWindow(this);
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.windowId = par1DataInputStream.readByte();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeByte(this.windowId);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 1;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet102WindowClick.java b/sp-server/src/main/java/net/minecraft/src/Packet102WindowClick.java
new file mode 100644
index 0000000..49c5cb1
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet102WindowClick.java
@@ -0,0 +1,61 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet102WindowClick extends Packet {
+ /** The id of the window which was clicked. 0 for player inventory. */
+ public int window_Id;
+
+ /** The clicked slot (-999 is outside of inventory) */
+ public int inventorySlot;
+
+ /** 1 when right-clicking and otherwise 0 */
+ public int mouseClick;
+
+ /** A unique number for the action, used for transaction handling */
+ public short action;
+
+ /** Item stack for inventory */
+ public ItemStack itemStack;
+ public int holdingShift;
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleWindowClick(this);
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.window_Id = par1DataInputStream.readByte();
+ this.inventorySlot = par1DataInputStream.readShort();
+ this.mouseClick = par1DataInputStream.readByte();
+ this.action = par1DataInputStream.readShort();
+ this.holdingShift = par1DataInputStream.readByte();
+ this.itemStack = readItemStack(par1DataInputStream);
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeByte(this.window_Id);
+ par1DataOutputStream.writeShort(this.inventorySlot);
+ par1DataOutputStream.writeByte(this.mouseClick);
+ par1DataOutputStream.writeShort(this.action);
+ par1DataOutputStream.writeByte(this.holdingShift);
+ writeItemStack(this.itemStack, par1DataOutputStream);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 11;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet103SetSlot.java b/sp-server/src/main/java/net/minecraft/src/Packet103SetSlot.java
new file mode 100644
index 0000000..466fd66
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet103SetSlot.java
@@ -0,0 +1,57 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet103SetSlot extends Packet {
+ /** The window which is being updated. 0 for player inventory */
+ public int windowId;
+
+ /** Slot that should be updated */
+ public int itemSlot;
+
+ /** Item stack */
+ public ItemStack myItemStack;
+
+ public Packet103SetSlot() {
+ }
+
+ public Packet103SetSlot(int par1, int par2, ItemStack par3ItemStack) {
+ this.windowId = par1;
+ this.itemSlot = par2;
+ this.myItemStack = par3ItemStack == null ? par3ItemStack : par3ItemStack.copy();
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleSetSlot(this);
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.windowId = par1DataInputStream.readByte();
+ this.itemSlot = par1DataInputStream.readShort();
+ this.myItemStack = readItemStack(par1DataInputStream);
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeByte(this.windowId);
+ par1DataOutputStream.writeShort(this.itemSlot);
+ writeItemStack(this.myItemStack, par1DataOutputStream);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 8;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet104WindowItems.java b/sp-server/src/main/java/net/minecraft/src/Packet104WindowItems.java
new file mode 100644
index 0000000..cfb3163
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet104WindowItems.java
@@ -0,0 +1,68 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.List;
+
+public class Packet104WindowItems extends Packet {
+ /**
+ * The id of window which items are being sent for. 0 for player inventory.
+ */
+ public int windowId;
+
+ /** Stack of items */
+ public ItemStack[] itemStack;
+
+ public Packet104WindowItems() {
+ }
+
+ public Packet104WindowItems(int par1, List par2List) {
+ this.windowId = par1;
+ this.itemStack = new ItemStack[par2List.size()];
+
+ for (int var3 = 0; var3 < this.itemStack.length; ++var3) {
+ ItemStack var4 = (ItemStack) par2List.get(var3);
+ this.itemStack[var3] = var4 == null ? null : var4.copy();
+ }
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.windowId = par1DataInputStream.readByte();
+ short var2 = par1DataInputStream.readShort();
+ this.itemStack = new ItemStack[var2];
+
+ for (int var3 = 0; var3 < var2; ++var3) {
+ this.itemStack[var3] = readItemStack(par1DataInputStream);
+ }
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeByte(this.windowId);
+ par1DataOutputStream.writeShort(this.itemStack.length);
+
+ for (int var2 = 0; var2 < this.itemStack.length; ++var2) {
+ writeItemStack(this.itemStack[var2], par1DataOutputStream);
+ }
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleWindowItems(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 3 + this.itemStack.length * 5;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet105UpdateProgressbar.java b/sp-server/src/main/java/net/minecraft/src/Packet105UpdateProgressbar.java
new file mode 100644
index 0000000..dc199c3
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet105UpdateProgressbar.java
@@ -0,0 +1,65 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet105UpdateProgressbar extends Packet {
+ /** The id of the window that the progress bar is in. */
+ public int windowId;
+
+ /**
+ * Which of the progress bars that should be updated. (For furnaces, 0 =
+ * progress arrow, 1 = fire icon)
+ */
+ public int progressBar;
+
+ /**
+ * The value of the progress bar. The maximum values vary depending on the
+ * progress bar. Presumably the values are specified as in-game ticks. Some
+ * progress bar values increase, while others decrease. For furnaces, 0 is
+ * empty, full progress arrow = about 180, full fire icon = about 250)
+ */
+ public int progressBarValue;
+
+ public Packet105UpdateProgressbar() {
+ }
+
+ public Packet105UpdateProgressbar(int par1, int par2, int par3) {
+ this.windowId = par1;
+ this.progressBar = par2;
+ this.progressBarValue = par3;
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleUpdateProgressbar(this);
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.windowId = par1DataInputStream.readByte();
+ this.progressBar = par1DataInputStream.readShort();
+ this.progressBarValue = par1DataInputStream.readShort();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeByte(this.windowId);
+ par1DataOutputStream.writeShort(this.progressBar);
+ par1DataOutputStream.writeShort(this.progressBarValue);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 5;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet106Transaction.java b/sp-server/src/main/java/net/minecraft/src/Packet106Transaction.java
new file mode 100644
index 0000000..1c4a177
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet106Transaction.java
@@ -0,0 +1,53 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet106Transaction extends Packet {
+ /** The id of the window that the action occurred in. */
+ public int windowId;
+ public short shortWindowId;
+ public boolean accepted;
+
+ public Packet106Transaction() {
+ }
+
+ public Packet106Transaction(int par1, short par2, boolean par3) {
+ this.windowId = par1;
+ this.shortWindowId = par2;
+ this.accepted = par3;
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleTransaction(this);
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.windowId = par1DataInputStream.readByte();
+ this.shortWindowId = par1DataInputStream.readShort();
+ this.accepted = par1DataInputStream.readByte() != 0;
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeByte(this.windowId);
+ par1DataOutputStream.writeShort(this.shortWindowId);
+ par1DataOutputStream.writeByte(this.accepted ? 1 : 0);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 4;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet107CreativeSetSlot.java b/sp-server/src/main/java/net/minecraft/src/Packet107CreativeSetSlot.java
new file mode 100644
index 0000000..15f72bb
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet107CreativeSetSlot.java
@@ -0,0 +1,40 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet107CreativeSetSlot extends Packet {
+ public int slot;
+ public ItemStack itemStack;
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleCreativeSetSlot(this);
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.slot = par1DataInputStream.readShort();
+ this.itemStack = readItemStack(par1DataInputStream);
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeShort(this.slot);
+ writeItemStack(this.itemStack, par1DataOutputStream);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 8;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet108EnchantItem.java b/sp-server/src/main/java/net/minecraft/src/Packet108EnchantItem.java
new file mode 100644
index 0000000..dda205a
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet108EnchantItem.java
@@ -0,0 +1,45 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet108EnchantItem extends Packet {
+ public int windowId;
+
+ /**
+ * The position of the enchantment on the enchantment table window, starting
+ * with 0 as the topmost one.
+ */
+ public int enchantment;
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleEnchantItem(this);
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.windowId = par1DataInputStream.readByte();
+ this.enchantment = par1DataInputStream.readByte();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeByte(this.windowId);
+ par1DataOutputStream.writeByte(this.enchantment);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 2;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet10Flying.java b/sp-server/src/main/java/net/minecraft/src/Packet10Flying.java
new file mode 100644
index 0000000..2686114
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet10Flying.java
@@ -0,0 +1,77 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet10Flying extends Packet {
+ /** The player's X position. */
+ public double xPosition;
+
+ /** The player's Y position. */
+ public double yPosition;
+
+ /** The player's Z position. */
+ public double zPosition;
+
+ /** The player's stance. (boundingBox.minY) */
+ public double stance;
+
+ /** The player's yaw rotation. */
+ public float yaw;
+
+ /** The player's pitch rotation. */
+ public float pitch;
+
+ /** True if the client is on the ground. */
+ public boolean onGround;
+
+ /** Boolean set to true if the player is moving. */
+ public boolean moving;
+
+ /** Boolean set to true if the player is rotating. */
+ public boolean rotating;
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleFlying(this);
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.onGround = par1DataInputStream.read() != 0;
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.write(this.onGround ? 1 : 0);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 1;
+ }
+
+ /**
+ * only false for the abstract Packet class, all real packets return true
+ */
+ public boolean isRealPacket() {
+ return true;
+ }
+
+ /**
+ * eg return packet30entity.entityId == entityId; WARNING : will throw if you
+ * compare a packet to a different packet class
+ */
+ public boolean containsSameEntityIDAs(Packet par1Packet) {
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet11PlayerPosition.java b/sp-server/src/main/java/net/minecraft/src/Packet11PlayerPosition.java
new file mode 100644
index 0000000..85fca69
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet11PlayerPosition.java
@@ -0,0 +1,40 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet11PlayerPosition extends Packet10Flying {
+ public Packet11PlayerPosition() {
+ this.moving = true;
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.xPosition = par1DataInputStream.readDouble();
+ this.yPosition = par1DataInputStream.readDouble();
+ this.stance = par1DataInputStream.readDouble();
+ this.zPosition = par1DataInputStream.readDouble();
+ super.readPacketData(par1DataInputStream);
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeDouble(this.xPosition);
+ par1DataOutputStream.writeDouble(this.yPosition);
+ par1DataOutputStream.writeDouble(this.stance);
+ par1DataOutputStream.writeDouble(this.zPosition);
+ super.writePacketData(par1DataOutputStream);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 33;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet12PlayerLook.java b/sp-server/src/main/java/net/minecraft/src/Packet12PlayerLook.java
new file mode 100644
index 0000000..1bb4a78
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet12PlayerLook.java
@@ -0,0 +1,36 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet12PlayerLook extends Packet10Flying {
+ public Packet12PlayerLook() {
+ this.rotating = true;
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.yaw = par1DataInputStream.readFloat();
+ this.pitch = par1DataInputStream.readFloat();
+ super.readPacketData(par1DataInputStream);
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeFloat(this.yaw);
+ par1DataOutputStream.writeFloat(this.pitch);
+ super.writePacketData(par1DataOutputStream);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 9;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet130UpdateSign.java b/sp-server/src/main/java/net/minecraft/src/Packet130UpdateSign.java
new file mode 100644
index 0000000..0386b38
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet130UpdateSign.java
@@ -0,0 +1,71 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet130UpdateSign extends Packet {
+ public int xPosition;
+ public int yPosition;
+ public int zPosition;
+ public String[] signLines;
+
+ public Packet130UpdateSign() {
+ this.isChunkDataPacket = true;
+ }
+
+ public Packet130UpdateSign(int par1, int par2, int par3, String[] par4ArrayOfStr) {
+ this.isChunkDataPacket = true;
+ this.xPosition = par1;
+ this.yPosition = par2;
+ this.zPosition = par3;
+ this.signLines = new String[] { par4ArrayOfStr[0], par4ArrayOfStr[1], par4ArrayOfStr[2], par4ArrayOfStr[3] };
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.xPosition = par1DataInputStream.readInt();
+ this.yPosition = par1DataInputStream.readShort();
+ this.zPosition = par1DataInputStream.readInt();
+ this.signLines = new String[4];
+
+ for (int var2 = 0; var2 < 4; ++var2) {
+ this.signLines[var2] = readString(par1DataInputStream, 15);
+ }
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeInt(this.xPosition);
+ par1DataOutputStream.writeShort(this.yPosition);
+ par1DataOutputStream.writeInt(this.zPosition);
+
+ for (int var2 = 0; var2 < 4; ++var2) {
+ writeString(this.signLines[var2], par1DataOutputStream);
+ }
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleUpdateSign(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ int var1 = 0;
+
+ for (int var2 = 0; var2 < 4; ++var2) {
+ var1 += this.signLines[var2].length();
+ }
+
+ return var1;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet131MapData.java b/sp-server/src/main/java/net/minecraft/src/Packet131MapData.java
new file mode 100644
index 0000000..d246801
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet131MapData.java
@@ -0,0 +1,65 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet131MapData extends Packet {
+ public short itemID;
+
+ /**
+ * Contains a unique ID for the item that this packet will be populating.
+ */
+ public short uniqueID;
+
+ /**
+ * Contains a buffer of arbitrary data with which to populate an individual item
+ * in the world.
+ */
+ public byte[] itemData;
+
+ public Packet131MapData() {
+ this.isChunkDataPacket = true;
+ }
+
+ public Packet131MapData(short par1, short par2, byte[] par3ArrayOfByte) {
+ this.isChunkDataPacket = true;
+ this.itemID = par1;
+ this.uniqueID = par2;
+ this.itemData = par3ArrayOfByte;
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.itemID = par1DataInputStream.readShort();
+ this.uniqueID = par1DataInputStream.readShort();
+ this.itemData = new byte[par1DataInputStream.readUnsignedShort()];
+ par1DataInputStream.readFully(this.itemData);
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeShort(this.itemID);
+ par1DataOutputStream.writeShort(this.uniqueID);
+ par1DataOutputStream.writeShort(this.itemData.length);
+ par1DataOutputStream.write(this.itemData);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleMapData(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 4 + this.itemData.length;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet132TileEntityData.java b/sp-server/src/main/java/net/minecraft/src/Packet132TileEntityData.java
new file mode 100644
index 0000000..6cc9726
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet132TileEntityData.java
@@ -0,0 +1,71 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet132TileEntityData extends Packet {
+ /** The X position of the tile entity to update. */
+ public int xPosition;
+
+ /** The Y position of the tile entity to update. */
+ public int yPosition;
+
+ /** The Z position of the tile entity to update. */
+ public int zPosition;
+
+ /** The type of update to perform on the tile entity. */
+ public int actionType;
+
+ /** Custom parameter 1 passed to the tile entity on update. */
+ public NBTTagCompound customParam1;
+
+ public Packet132TileEntityData() {
+ this.isChunkDataPacket = true;
+ }
+
+ public Packet132TileEntityData(int par1, int par2, int par3, int par4, NBTTagCompound par5NBTTagCompound) {
+ this.isChunkDataPacket = true;
+ this.xPosition = par1;
+ this.yPosition = par2;
+ this.zPosition = par3;
+ this.actionType = par4;
+ this.customParam1 = par5NBTTagCompound;
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.xPosition = par1DataInputStream.readInt();
+ this.yPosition = par1DataInputStream.readShort();
+ this.zPosition = par1DataInputStream.readInt();
+ this.actionType = par1DataInputStream.readByte();
+ this.customParam1 = readNBTTagCompound(par1DataInputStream);
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeInt(this.xPosition);
+ par1DataOutputStream.writeShort(this.yPosition);
+ par1DataOutputStream.writeInt(this.zPosition);
+ par1DataOutputStream.writeByte((byte) this.actionType);
+ writeNBTTagCompound(this.customParam1, par1DataOutputStream);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleTileEntityData(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 25;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet13PlayerLookMove.java b/sp-server/src/main/java/net/minecraft/src/Packet13PlayerLookMove.java
new file mode 100644
index 0000000..edff4d2
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet13PlayerLookMove.java
@@ -0,0 +1,58 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet13PlayerLookMove extends Packet10Flying {
+ public Packet13PlayerLookMove() {
+ this.rotating = true;
+ this.moving = true;
+ }
+
+ public Packet13PlayerLookMove(double par1, double par3, double par5, double par7, float par9, float par10,
+ boolean par11) {
+ this.xPosition = par1;
+ this.yPosition = par3;
+ this.stance = par5;
+ this.zPosition = par7;
+ this.yaw = par9;
+ this.pitch = par10;
+ this.onGround = par11;
+ this.rotating = true;
+ this.moving = true;
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.xPosition = par1DataInputStream.readDouble();
+ this.yPosition = par1DataInputStream.readDouble();
+ this.stance = par1DataInputStream.readDouble();
+ this.zPosition = par1DataInputStream.readDouble();
+ this.yaw = par1DataInputStream.readFloat();
+ this.pitch = par1DataInputStream.readFloat();
+ super.readPacketData(par1DataInputStream);
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeDouble(this.xPosition);
+ par1DataOutputStream.writeDouble(this.yPosition);
+ par1DataOutputStream.writeDouble(this.stance);
+ par1DataOutputStream.writeDouble(this.zPosition);
+ par1DataOutputStream.writeFloat(this.yaw);
+ par1DataOutputStream.writeFloat(this.pitch);
+ super.writePacketData(par1DataOutputStream);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 41;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet14BlockDig.java b/sp-server/src/main/java/net/minecraft/src/Packet14BlockDig.java
new file mode 100644
index 0000000..16b4548
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet14BlockDig.java
@@ -0,0 +1,58 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet14BlockDig extends Packet {
+ /** Block X position. */
+ public int xPosition;
+
+ /** Block Y position. */
+ public int yPosition;
+
+ /** Block Z position. */
+ public int zPosition;
+
+ /** Punched face of the block. */
+ public int face;
+
+ /** Status of the digging (started, ongoing, broken). */
+ public int status;
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.status = par1DataInputStream.read();
+ this.xPosition = par1DataInputStream.readInt();
+ this.yPosition = par1DataInputStream.read();
+ this.zPosition = par1DataInputStream.readInt();
+ this.face = par1DataInputStream.read();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.write(this.status);
+ par1DataOutputStream.writeInt(this.xPosition);
+ par1DataOutputStream.write(this.yPosition);
+ par1DataOutputStream.writeInt(this.zPosition);
+ par1DataOutputStream.write(this.face);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleBlockDig(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 11;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet15Place.java b/sp-server/src/main/java/net/minecraft/src/Packet15Place.java
new file mode 100644
index 0000000..507bad0
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet15Place.java
@@ -0,0 +1,107 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet15Place extends Packet {
+ private int xPosition;
+ private int yPosition;
+ private int zPosition;
+
+ /** The offset to use for block/item placement. */
+ private int direction;
+ private ItemStack itemStack;
+
+ /** The offset from xPosition where the actual click took place */
+ private float xOffset;
+
+ /** The offset from yPosition where the actual click took place */
+ private float yOffset;
+
+ /** The offset from zPosition where the actual click took place */
+ private float zOffset;
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.xPosition = par1DataInputStream.readInt();
+ this.yPosition = par1DataInputStream.read();
+ this.zPosition = par1DataInputStream.readInt();
+ this.direction = par1DataInputStream.read();
+ this.itemStack = readItemStack(par1DataInputStream);
+ this.xOffset = (float) par1DataInputStream.read() / 16.0F;
+ this.yOffset = (float) par1DataInputStream.read() / 16.0F;
+ this.zOffset = (float) par1DataInputStream.read() / 16.0F;
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeInt(this.xPosition);
+ par1DataOutputStream.write(this.yPosition);
+ par1DataOutputStream.writeInt(this.zPosition);
+ par1DataOutputStream.write(this.direction);
+ writeItemStack(this.itemStack, par1DataOutputStream);
+ par1DataOutputStream.write((int) (this.xOffset * 16.0F));
+ par1DataOutputStream.write((int) (this.yOffset * 16.0F));
+ par1DataOutputStream.write((int) (this.zOffset * 16.0F));
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handlePlace(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 19;
+ }
+
+ public int getXPosition() {
+ return this.xPosition;
+ }
+
+ public int getYPosition() {
+ return this.yPosition;
+ }
+
+ public int getZPosition() {
+ return this.zPosition;
+ }
+
+ public int getDirection() {
+ return this.direction;
+ }
+
+ public ItemStack getItemStack() {
+ return this.itemStack;
+ }
+
+ /**
+ * Returns the offset from xPosition where the actual click took place
+ */
+ public float getXOffset() {
+ return this.xOffset;
+ }
+
+ /**
+ * Returns the offset from yPosition where the actual click took place
+ */
+ public float getYOffset() {
+ return this.yOffset;
+ }
+
+ /**
+ * Returns the offset from zPosition where the actual click took place
+ */
+ public float getZOffset() {
+ return this.zOffset;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet16BlockItemSwitch.java b/sp-server/src/main/java/net/minecraft/src/Packet16BlockItemSwitch.java
new file mode 100644
index 0000000..39d1aa6
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet16BlockItemSwitch.java
@@ -0,0 +1,60 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet16BlockItemSwitch extends Packet {
+ /** The block/item id to be equipped. */
+ public int id;
+
+ public Packet16BlockItemSwitch() {
+ }
+
+ public Packet16BlockItemSwitch(int par1) {
+ this.id = par1;
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.id = par1DataInputStream.readShort();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeShort(this.id);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleBlockItemSwitch(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 2;
+ }
+
+ /**
+ * only false for the abstract Packet class, all real packets return true
+ */
+ public boolean isRealPacket() {
+ return true;
+ }
+
+ /**
+ * eg return packet30entity.entityId == entityId; WARNING : will throw if you
+ * compare a packet to a different packet class
+ */
+ public boolean containsSameEntityIDAs(Packet par1Packet) {
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet17Sleep.java b/sp-server/src/main/java/net/minecraft/src/Packet17Sleep.java
new file mode 100644
index 0000000..c619fa3
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet17Sleep.java
@@ -0,0 +1,60 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet17Sleep extends Packet {
+ public int entityID;
+ public int bedX;
+ public int bedY;
+ public int bedZ;
+ public int field_73622_e;
+
+ public Packet17Sleep() {
+ }
+
+ public Packet17Sleep(Entity par1Entity, int par2, int par3, int par4, int par5) {
+ this.field_73622_e = par2;
+ this.bedX = par3;
+ this.bedY = par4;
+ this.bedZ = par5;
+ this.entityID = par1Entity.entityId;
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.entityID = par1DataInputStream.readInt();
+ this.field_73622_e = par1DataInputStream.readByte();
+ this.bedX = par1DataInputStream.readInt();
+ this.bedY = par1DataInputStream.readByte();
+ this.bedZ = par1DataInputStream.readInt();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeInt(this.entityID);
+ par1DataOutputStream.writeByte(this.field_73622_e);
+ par1DataOutputStream.writeInt(this.bedX);
+ par1DataOutputStream.writeByte(this.bedY);
+ par1DataOutputStream.writeInt(this.bedZ);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleSleep(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 14;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet18Animation.java b/sp-server/src/main/java/net/minecraft/src/Packet18Animation.java
new file mode 100644
index 0000000..4221a4d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet18Animation.java
@@ -0,0 +1,49 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet18Animation extends Packet {
+ /** The entity ID, in this case it's the player ID. */
+ public int entityId;
+ public int animate;
+
+ public Packet18Animation() {
+ }
+
+ public Packet18Animation(Entity par1Entity, int par2) {
+ this.entityId = par1Entity.entityId;
+ this.animate = par2;
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.entityId = par1DataInputStream.readInt();
+ this.animate = par1DataInputStream.readByte();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeInt(this.entityId);
+ par1DataOutputStream.writeByte(this.animate);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleAnimation(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 5;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet19EntityAction.java b/sp-server/src/main/java/net/minecraft/src/Packet19EntityAction.java
new file mode 100644
index 0000000..66ecfaa
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet19EntityAction.java
@@ -0,0 +1,43 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet19EntityAction extends Packet {
+ /** Player ID. */
+ public int entityId;
+
+ /** 1=sneak, 2=normal */
+ public int state;
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.entityId = par1DataInputStream.readInt();
+ this.state = par1DataInputStream.readByte();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeInt(this.entityId);
+ par1DataOutputStream.writeByte(this.state);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleEntityAction(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 5;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet1Login.java b/sp-server/src/main/java/net/minecraft/src/Packet1Login.java
new file mode 100644
index 0000000..2b8f4ae
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet1Login.java
@@ -0,0 +1,101 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet1Login extends Packet {
+ /** The player's entity ID */
+ public int clientEntityId = 0;
+ public WorldType terrainType;
+ public boolean hardcoreMode;
+ public EnumGameType gameType;
+
+ /** -1: The Nether, 0: The Overworld, 1: The End */
+ public int dimension;
+
+ /** The difficulty setting byte. */
+ public byte difficultySetting;
+
+ /** Defaults to 128 */
+ public byte worldHeight;
+
+ /** The maximum players. */
+ public byte maxPlayers;
+
+ public Packet1Login() {
+ }
+
+ public Packet1Login(int par1, WorldType par2WorldType, EnumGameType par3EnumGameType, boolean par4, int par5,
+ int par6, int par7, int par8) {
+ this.clientEntityId = par1;
+ this.terrainType = par2WorldType;
+ this.dimension = par5;
+ this.difficultySetting = (byte) par6;
+ this.gameType = par3EnumGameType;
+ this.worldHeight = (byte) par7;
+ this.maxPlayers = (byte) par8;
+ this.hardcoreMode = par4;
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.clientEntityId = par1DataInputStream.readInt();
+ String var2 = readString(par1DataInputStream, 16);
+ this.terrainType = WorldType.parseWorldType(var2);
+
+ if (this.terrainType == null) {
+ this.terrainType = WorldType.DEFAULT;
+ }
+
+ byte var3 = par1DataInputStream.readByte();
+ this.hardcoreMode = (var3 & 8) == 8;
+ int var4 = var3 & -9;
+ this.gameType = EnumGameType.getByID(var4);
+ this.dimension = par1DataInputStream.readByte();
+ this.difficultySetting = par1DataInputStream.readByte();
+ this.worldHeight = par1DataInputStream.readByte();
+ this.maxPlayers = par1DataInputStream.readByte();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeInt(this.clientEntityId);
+ writeString(this.terrainType == null ? "" : this.terrainType.getWorldTypeName(), par1DataOutputStream);
+ int var2 = this.gameType.getID();
+
+ if (this.hardcoreMode) {
+ var2 |= 8;
+ }
+
+ par1DataOutputStream.writeByte(var2);
+ par1DataOutputStream.writeByte(this.dimension);
+ par1DataOutputStream.writeByte(this.difficultySetting);
+ par1DataOutputStream.writeByte(this.worldHeight);
+ par1DataOutputStream.writeByte(this.maxPlayers);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleLogin(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ int var1 = 0;
+
+ if (this.terrainType != null) {
+ var1 = this.terrainType.getWorldTypeName().length();
+ }
+
+ return 6 + 2 * var1 + 4 + 4 + 1 + 1 + 1;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet200Statistic.java b/sp-server/src/main/java/net/minecraft/src/Packet200Statistic.java
new file mode 100644
index 0000000..a8294b8
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet200Statistic.java
@@ -0,0 +1,56 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet200Statistic extends Packet {
+ public int statisticId;
+ public int amount;
+
+ public Packet200Statistic() {
+ }
+
+ public Packet200Statistic(int par1, int par2) {
+ this.statisticId = par1;
+ this.amount = par2;
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleStatistic(this);
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.statisticId = par1DataInputStream.readInt();
+ this.amount = par1DataInputStream.readByte();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeInt(this.statisticId);
+ par1DataOutputStream.writeByte(this.amount);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 6;
+ }
+
+ /**
+ * If this returns true, the packet may be processed on any thread; otherwise it
+ * is queued for the main thread to handle.
+ */
+ public boolean canProcessAsync() {
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet201PlayerInfo.java b/sp-server/src/main/java/net/minecraft/src/Packet201PlayerInfo.java
new file mode 100644
index 0000000..052614f
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet201PlayerInfo.java
@@ -0,0 +1,55 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet201PlayerInfo extends Packet {
+ /** The player's name. */
+ public String playerName;
+
+ /** Byte that tells whether the player is connected. */
+ public boolean isConnected;
+ public int ping;
+
+ public Packet201PlayerInfo() {
+ }
+
+ public Packet201PlayerInfo(String par1Str, boolean par2, int par3) {
+ this.playerName = par1Str;
+ this.isConnected = par2;
+ this.ping = par3;
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.playerName = readString(par1DataInputStream, 16);
+ this.isConnected = par1DataInputStream.readByte() != 0;
+ this.ping = par1DataInputStream.readShort();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ writeString(this.playerName, par1DataOutputStream);
+ par1DataOutputStream.writeByte(this.isConnected ? 1 : 0);
+ par1DataOutputStream.writeShort(this.ping);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handlePlayerInfo(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return this.playerName.length() + 2 + 1 + 2;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet202PlayerAbilities.java b/sp-server/src/main/java/net/minecraft/src/Packet202PlayerAbilities.java
new file mode 100644
index 0000000..b604bcb
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet202PlayerAbilities.java
@@ -0,0 +1,157 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet202PlayerAbilities extends Packet {
+ /** Disables player damage. */
+ private boolean disableDamage = false;
+
+ /** Indicates whether the player is flying or not. */
+ private boolean isFlying = false;
+
+ /** Whether or not to allow the player to fly when they double jump. */
+ private boolean allowFlying = false;
+
+ /**
+ * Used to determine if creative mode is enabled, and therefore if items should
+ * be depleted on usage
+ */
+ private boolean isCreativeMode = false;
+ private float flySpeed;
+ private float walkSpeed;
+
+ public Packet202PlayerAbilities() {
+ }
+
+ public Packet202PlayerAbilities(PlayerCapabilities par1PlayerCapabilities) {
+ this.setDisableDamage(par1PlayerCapabilities.disableDamage);
+ this.setFlying(par1PlayerCapabilities.isFlying);
+ this.setAllowFlying(par1PlayerCapabilities.allowFlying);
+ this.setCreativeMode(par1PlayerCapabilities.isCreativeMode);
+ this.setFlySpeed(par1PlayerCapabilities.getFlySpeed());
+ this.setWalkSpeed(par1PlayerCapabilities.getWalkSpeed());
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ byte var2 = par1DataInputStream.readByte();
+ this.setDisableDamage((var2 & 1) > 0);
+ this.setFlying((var2 & 2) > 0);
+ this.setAllowFlying((var2 & 4) > 0);
+ this.setCreativeMode((var2 & 8) > 0);
+ this.setFlySpeed((float) par1DataInputStream.readByte() / 255.0F);
+ this.setWalkSpeed((float) par1DataInputStream.readByte() / 255.0F);
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ byte var2 = 0;
+
+ if (this.getDisableDamage()) {
+ var2 = (byte) (var2 | 1);
+ }
+
+ if (this.getFlying()) {
+ var2 = (byte) (var2 | 2);
+ }
+
+ if (this.getAllowFlying()) {
+ var2 = (byte) (var2 | 4);
+ }
+
+ if (this.isCreativeMode()) {
+ var2 = (byte) (var2 | 8);
+ }
+
+ par1DataOutputStream.writeByte(var2);
+ par1DataOutputStream.writeByte((int) (this.flySpeed * 255.0F));
+ par1DataOutputStream.writeByte((int) (this.walkSpeed * 255.0F));
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handlePlayerAbilities(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 2;
+ }
+
+ public boolean getDisableDamage() {
+ return this.disableDamage;
+ }
+
+ /**
+ * Sets whether damage is disabled or not.
+ */
+ public void setDisableDamage(boolean par1) {
+ this.disableDamage = par1;
+ }
+
+ public boolean getFlying() {
+ return this.isFlying;
+ }
+
+ /**
+ * Sets whether we're currently flying or not.
+ */
+ public void setFlying(boolean par1) {
+ this.isFlying = par1;
+ }
+
+ public boolean getAllowFlying() {
+ return this.allowFlying;
+ }
+
+ public void setAllowFlying(boolean par1) {
+ this.allowFlying = par1;
+ }
+
+ public boolean isCreativeMode() {
+ return this.isCreativeMode;
+ }
+
+ public void setCreativeMode(boolean par1) {
+ this.isCreativeMode = par1;
+ }
+
+ /**
+ * Sets the flying speed.
+ */
+ public void setFlySpeed(float par1) {
+ this.flySpeed = par1;
+ }
+
+ /**
+ * Sets the walking speed.
+ */
+ public void setWalkSpeed(float par1) {
+ this.walkSpeed = par1;
+ }
+
+ /**
+ * only false for the abstract Packet class, all real packets return true
+ */
+ public boolean isRealPacket() {
+ return true;
+ }
+
+ /**
+ * eg return packet30entity.entityId == entityId; WARNING : will throw if you
+ * compare a packet to a different packet class
+ */
+ public boolean containsSameEntityIDAs(Packet par1Packet) {
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet203AutoComplete.java b/sp-server/src/main/java/net/minecraft/src/Packet203AutoComplete.java
new file mode 100644
index 0000000..24a3b11
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet203AutoComplete.java
@@ -0,0 +1,67 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet203AutoComplete extends Packet {
+ /**
+ * Sent by the client containing the text to be autocompleted. Sent by the
+ * server with possible completions separated by null (two bytes in UTF-16)
+ */
+ private String text;
+
+ public Packet203AutoComplete() {
+ }
+
+ public Packet203AutoComplete(String par1Str) {
+ this.text = par1Str;
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.text = readString(par1DataInputStream, Packet3Chat.maxChatLength);
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ writeString(this.text, par1DataOutputStream);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleAutoComplete(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 2 + this.text.length() * 2;
+ }
+
+ public String getText() {
+ return this.text;
+ }
+
+ /**
+ * only false for the abstract Packet class, all real packets return true
+ */
+ public boolean isRealPacket() {
+ return true;
+ }
+
+ /**
+ * eg return packet30entity.entityId == entityId; WARNING : will throw if you
+ * compare a packet to a different packet class
+ */
+ public boolean containsSameEntityIDAs(Packet par1Packet) {
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet204ClientInfo.java b/sp-server/src/main/java/net/minecraft/src/Packet204ClientInfo.java
new file mode 100644
index 0000000..ecdbb85
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet204ClientInfo.java
@@ -0,0 +1,91 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet204ClientInfo extends Packet {
+ private String language;
+ private int renderDistance;
+ private int chatVisisble;
+ private boolean chatColours;
+ private int gameDifficulty;
+ private boolean showCape;
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.language = readString(par1DataInputStream, 7);
+ this.renderDistance = par1DataInputStream.readByte();
+ byte var2 = par1DataInputStream.readByte();
+ this.chatVisisble = var2 & 7;
+ this.chatColours = (var2 & 8) == 8;
+ this.gameDifficulty = par1DataInputStream.readByte();
+ this.showCape = par1DataInputStream.readBoolean();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ writeString(this.language, par1DataOutputStream);
+ par1DataOutputStream.writeByte(this.renderDistance);
+ par1DataOutputStream.writeByte(this.chatVisisble | (this.chatColours ? 1 : 0) << 3);
+ par1DataOutputStream.writeByte(this.gameDifficulty);
+ par1DataOutputStream.writeBoolean(this.showCape);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleClientInfo(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 7;
+ }
+
+ public String getLanguage() {
+ return this.language;
+ }
+
+ public int getRenderDistance() {
+ return this.renderDistance;
+ }
+
+ public int getChatVisibility() {
+ return this.chatVisisble;
+ }
+
+ public boolean getChatColours() {
+ return this.chatColours;
+ }
+
+ public int getDifficulty() {
+ return this.gameDifficulty;
+ }
+
+ public boolean getShowCape() {
+ return this.showCape;
+ }
+
+ /**
+ * only false for the abstract Packet class, all real packets return true
+ */
+ public boolean isRealPacket() {
+ return true;
+ }
+
+ /**
+ * eg return packet30entity.entityId == entityId; WARNING : will throw if you
+ * compare a packet to a different packet class
+ */
+ public boolean containsSameEntityIDAs(Packet par1Packet) {
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet205ClientCommand.java b/sp-server/src/main/java/net/minecraft/src/Packet205ClientCommand.java
new file mode 100644
index 0000000..1b2fd7e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet205ClientCommand.java
@@ -0,0 +1,41 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet205ClientCommand extends Packet {
+ /**
+ * 0 sent to a netLoginHandler starts the server, 1 sent to NetServerHandler
+ * forces a respawn
+ */
+ public int forceRespawn;
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.forceRespawn = par1DataInputStream.readByte();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeByte(this.forceRespawn & 255);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleClientCommand(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 1;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet206SetObjective.java b/sp-server/src/main/java/net/minecraft/src/Packet206SetObjective.java
new file mode 100644
index 0000000..33c9b0d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet206SetObjective.java
@@ -0,0 +1,56 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet206SetObjective extends Packet {
+ public String objectiveName;
+ public String objectiveDisplayName;
+
+ /**
+ * 0 to create scoreboard, 1 to remove scoreboard, 2 to update display text.
+ */
+ public int change;
+
+ public Packet206SetObjective() {
+ }
+
+ public Packet206SetObjective(ScoreObjective par1, int par2) {
+ this.objectiveName = par1.getName();
+ this.objectiveDisplayName = par1.getDisplayName();
+ this.change = par2;
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.objectiveName = readString(par1DataInputStream, 16);
+ this.objectiveDisplayName = readString(par1DataInputStream, 32);
+ this.change = par1DataInputStream.readByte();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ writeString(this.objectiveName, par1DataOutputStream);
+ writeString(this.objectiveDisplayName, par1DataOutputStream);
+ par1DataOutputStream.writeByte(this.change);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleSetObjective(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 2 + this.objectiveName.length() + 2 + this.objectiveDisplayName.length() + 1;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet207SetScore.java b/sp-server/src/main/java/net/minecraft/src/Packet207SetScore.java
new file mode 100644
index 0000000..455ec4c
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet207SetScore.java
@@ -0,0 +1,82 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet207SetScore extends Packet {
+ /** An unique name to be displayed in the list. */
+ public String itemName = "";
+
+ /**
+ * The unique name for the scoreboard to be updated. Only sent when
+ * updateOrRemove does not equal 1.
+ */
+ public String scoreName = "";
+
+ /**
+ * The score to be displayed next to the entry. Only sent when Update/Remove
+ * does not equal 1.
+ */
+ public int value = 0;
+
+ /** 0 to create/update an item. 1 to remove an item. */
+ public int updateOrRemove = 0;
+
+ public Packet207SetScore() {
+ }
+
+ public Packet207SetScore(Score par1, int par2) {
+ this.itemName = par1.func_96653_e();
+ this.scoreName = par1.func_96645_d().getName();
+ this.value = par1.func_96652_c();
+ this.updateOrRemove = par2;
+ }
+
+ public Packet207SetScore(String par1) {
+ this.itemName = par1;
+ this.scoreName = "";
+ this.value = 0;
+ this.updateOrRemove = 1;
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.itemName = readString(par1DataInputStream, 16);
+ this.updateOrRemove = par1DataInputStream.readByte();
+
+ if (this.updateOrRemove != 1) {
+ this.scoreName = readString(par1DataInputStream, 16);
+ this.value = par1DataInputStream.readInt();
+ }
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ writeString(this.itemName, par1DataOutputStream);
+ par1DataOutputStream.writeByte(this.updateOrRemove);
+
+ if (this.updateOrRemove != 1) {
+ writeString(this.scoreName, par1DataOutputStream);
+ par1DataOutputStream.writeInt(this.value);
+ }
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleSetScore(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 2 + this.itemName.length() + 2 + this.scoreName.length() + 4 + 1;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet208SetDisplayObjective.java b/sp-server/src/main/java/net/minecraft/src/Packet208SetDisplayObjective.java
new file mode 100644
index 0000000..fec57a1
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet208SetDisplayObjective.java
@@ -0,0 +1,56 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet208SetDisplayObjective extends Packet {
+ /** The position of the scoreboard. 0 = list, 1 = sidebar, 2 = belowName. */
+ public int scoreboardPosition;
+
+ /** The unique name for the scoreboard to be displayed. */
+ public String scoreName;
+
+ public Packet208SetDisplayObjective() {
+ }
+
+ public Packet208SetDisplayObjective(int par1, ScoreObjective par2ScoreObjective) {
+ this.scoreboardPosition = par1;
+
+ if (par2ScoreObjective == null) {
+ this.scoreName = "";
+ } else {
+ this.scoreName = par2ScoreObjective.getName();
+ }
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.scoreboardPosition = par1DataInputStream.readByte();
+ this.scoreName = readString(par1DataInputStream, 16);
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeByte(this.scoreboardPosition);
+ writeString(this.scoreName, par1DataOutputStream);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleSetDisplayObjective(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 3 + this.scoreName.length();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet209SetPlayerTeam.java b/sp-server/src/main/java/net/minecraft/src/Packet209SetPlayerTeam.java
new file mode 100644
index 0000000..f8bdb3a
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet209SetPlayerTeam.java
@@ -0,0 +1,134 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+
+public class Packet209SetPlayerTeam extends Packet {
+ /** A unique name for the team. */
+ public String teamName = "";
+
+ /** Only if mode = 0 or 2. */
+ public String teamDisplayName = "";
+
+ /**
+ * Only if mode = 0 or 2. Displayed before the players' name that are part of
+ * this team.
+ */
+ public String teamPrefix = "";
+
+ /**
+ * Only if mode = 0 or 2. Displayed after the players' name that are part of
+ * this team.
+ */
+ public String teamSuffix = "";
+
+ /** Only if mode = 0 or 3 or 4. Players to be added/remove from the team. */
+ public Collection playerNames = new ArrayList();
+
+ /**
+ * If 0 then the team is created. If 1 then the team is removed. If 2 the team
+ * team information is updated. If 3 then new players are added to the team. If
+ * 4 then players are removed from the team.
+ */
+ public int mode = 0;
+
+ /** Only if mode = 0 or 2. */
+ public int friendlyFire;
+
+ public Packet209SetPlayerTeam() {
+ }
+
+ public Packet209SetPlayerTeam(ScorePlayerTeam par1, int par2) {
+ this.teamName = par1.func_96661_b();
+ this.mode = par2;
+
+ if (par2 == 0 || par2 == 2) {
+ this.teamDisplayName = par1.func_96669_c();
+ this.teamPrefix = par1.func_96668_e();
+ this.teamSuffix = par1.func_96663_f();
+ this.friendlyFire = par1.func_98299_i();
+ }
+
+ if (par2 == 0) {
+ this.playerNames.addAll(par1.getMembershipCollection());
+ }
+ }
+
+ public Packet209SetPlayerTeam(ScorePlayerTeam par1ScorePlayerTeam, Collection par2Collection, int par3) {
+ if (par3 != 3 && par3 != 4) {
+ throw new IllegalArgumentException("Method must be join or leave for player constructor");
+ } else if (par2Collection != null && !par2Collection.isEmpty()) {
+ this.mode = par3;
+ this.teamName = par1ScorePlayerTeam.func_96661_b();
+ this.playerNames.addAll(par2Collection);
+ } else {
+ throw new IllegalArgumentException("Players cannot be null/empty");
+ }
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.teamName = readString(par1DataInputStream, 16);
+ this.mode = par1DataInputStream.readByte();
+
+ if (this.mode == 0 || this.mode == 2) {
+ this.teamDisplayName = readString(par1DataInputStream, 32);
+ this.teamPrefix = readString(par1DataInputStream, 16);
+ this.teamSuffix = readString(par1DataInputStream, 16);
+ this.friendlyFire = par1DataInputStream.readByte();
+ }
+
+ if (this.mode == 0 || this.mode == 3 || this.mode == 4) {
+ short var2 = par1DataInputStream.readShort();
+
+ for (int var3 = 0; var3 < var2; ++var3) {
+ this.playerNames.add(readString(par1DataInputStream, 16));
+ }
+ }
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ writeString(this.teamName, par1DataOutputStream);
+ par1DataOutputStream.writeByte(this.mode);
+
+ if (this.mode == 0 || this.mode == 2) {
+ writeString(this.teamDisplayName, par1DataOutputStream);
+ writeString(this.teamPrefix, par1DataOutputStream);
+ writeString(this.teamSuffix, par1DataOutputStream);
+ par1DataOutputStream.writeByte(this.friendlyFire);
+ }
+
+ if (this.mode == 0 || this.mode == 3 || this.mode == 4) {
+ par1DataOutputStream.writeShort(this.playerNames.size());
+ Iterator var2 = this.playerNames.iterator();
+
+ while (var2.hasNext()) {
+ String var3 = (String) var2.next();
+ writeString(var3, par1DataOutputStream);
+ }
+ }
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleSetPlayerTeam(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 3 + this.teamName.length();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet20NamedEntitySpawn.java b/sp-server/src/main/java/net/minecraft/src/Packet20NamedEntitySpawn.java
new file mode 100644
index 0000000..d2dc7f1
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet20NamedEntitySpawn.java
@@ -0,0 +1,94 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.List;
+
+public class Packet20NamedEntitySpawn extends Packet {
+ /** The entity ID, in this case it's the player ID. */
+ public int entityId;
+
+ /** The player's name. */
+ public String name;
+
+ /** The player's X position. */
+ public int xPosition;
+
+ /** The player's Y position. */
+ public int yPosition;
+
+ /** The player's Z position. */
+ public int zPosition;
+
+ /** The player's rotation. */
+ public byte rotation;
+
+ /** The player's pitch. */
+ public byte pitch;
+
+ /** The current item the player is holding. */
+ public int currentItem;
+ private DataWatcher metadata;
+ private List metadataWatchableObjects;
+
+ public Packet20NamedEntitySpawn() {
+ }
+
+ public Packet20NamedEntitySpawn(EntityPlayer par1EntityPlayer) {
+ this.entityId = par1EntityPlayer.entityId;
+ this.name = par1EntityPlayer.username;
+ this.xPosition = MathHelper.floor_double(par1EntityPlayer.posX * 32.0D);
+ this.yPosition = MathHelper.floor_double(par1EntityPlayer.posY * 32.0D);
+ this.zPosition = MathHelper.floor_double(par1EntityPlayer.posZ * 32.0D);
+ this.rotation = (byte) ((int) (par1EntityPlayer.rotationYaw * 256.0F / 360.0F));
+ this.pitch = (byte) ((int) (par1EntityPlayer.rotationPitch * 256.0F / 360.0F));
+ ItemStack var2 = par1EntityPlayer.inventory.getCurrentItem();
+ this.currentItem = var2 == null ? 0 : var2.itemID;
+ this.metadata = par1EntityPlayer.getDataWatcher();
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.entityId = par1DataInputStream.readInt();
+ this.name = readString(par1DataInputStream, 16);
+ this.xPosition = par1DataInputStream.readInt();
+ this.yPosition = par1DataInputStream.readInt();
+ this.zPosition = par1DataInputStream.readInt();
+ this.rotation = par1DataInputStream.readByte();
+ this.pitch = par1DataInputStream.readByte();
+ this.currentItem = par1DataInputStream.readShort();
+ this.metadataWatchableObjects = DataWatcher.readWatchableObjects(par1DataInputStream);
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeInt(this.entityId);
+ writeString(this.name, par1DataOutputStream);
+ par1DataOutputStream.writeInt(this.xPosition);
+ par1DataOutputStream.writeInt(this.yPosition);
+ par1DataOutputStream.writeInt(this.zPosition);
+ par1DataOutputStream.writeByte(this.rotation);
+ par1DataOutputStream.writeByte(this.pitch);
+ par1DataOutputStream.writeShort(this.currentItem);
+ this.metadata.writeWatchableObjects(par1DataOutputStream);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleNamedEntitySpawn(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 28;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet22Collect.java b/sp-server/src/main/java/net/minecraft/src/Packet22Collect.java
new file mode 100644
index 0000000..850711b
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet22Collect.java
@@ -0,0 +1,51 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet22Collect extends Packet {
+ /** The entity on the ground that was picked up. */
+ public int collectedEntityId;
+
+ /** The entity that picked up the one from the ground. */
+ public int collectorEntityId;
+
+ public Packet22Collect() {
+ }
+
+ public Packet22Collect(int par1, int par2) {
+ this.collectedEntityId = par1;
+ this.collectorEntityId = par2;
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.collectedEntityId = par1DataInputStream.readInt();
+ this.collectorEntityId = par1DataInputStream.readInt();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeInt(this.collectedEntityId);
+ par1DataOutputStream.writeInt(this.collectorEntityId);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleCollect(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 8;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet23VehicleSpawn.java b/sp-server/src/main/java/net/minecraft/src/Packet23VehicleSpawn.java
new file mode 100644
index 0000000..22946ae
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet23VehicleSpawn.java
@@ -0,0 +1,156 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet23VehicleSpawn extends Packet {
+ /** Entity ID of the object. */
+ public int entityId;
+
+ /** The X position of the object. */
+ public int xPosition;
+
+ /** The Y position of the object. */
+ public int yPosition;
+
+ /** The Z position of the object. */
+ public int zPosition;
+
+ /**
+ * Not sent if the thrower entity ID is 0. The speed of this fireball along the
+ * X axis.
+ */
+ public int speedX;
+
+ /**
+ * Not sent if the thrower entity ID is 0. The speed of this fireball along the
+ * Y axis.
+ */
+ public int speedY;
+
+ /**
+ * Not sent if the thrower entity ID is 0. The speed of this fireball along the
+ * Z axis.
+ */
+ public int speedZ;
+
+ /** The pitch in steps of 2p/256 */
+ public int pitch;
+
+ /** The yaw in steps of 2p/256 */
+ public int yaw;
+
+ /** The type of object. */
+ public int type;
+
+ /** 0 if not a fireball. Otherwise, this is the Entity ID of the thrower. */
+ public int throwerEntityId;
+
+ public Packet23VehicleSpawn() {
+ }
+
+ public Packet23VehicleSpawn(Entity par1Entity, int par2) {
+ this(par1Entity, par2, 0);
+ }
+
+ public Packet23VehicleSpawn(Entity par1Entity, int par2, int par3) {
+ this.entityId = par1Entity.entityId;
+ this.xPosition = MathHelper.floor_double(par1Entity.posX * 32.0D);
+ this.yPosition = MathHelper.floor_double(par1Entity.posY * 32.0D);
+ this.zPosition = MathHelper.floor_double(par1Entity.posZ * 32.0D);
+ this.pitch = MathHelper.floor_float(par1Entity.rotationPitch * 256.0F / 360.0F);
+ this.yaw = MathHelper.floor_float(par1Entity.rotationYaw * 256.0F / 360.0F);
+ this.type = par2;
+ this.throwerEntityId = par3;
+
+ if (par3 > 0) {
+ double var4 = par1Entity.motionX;
+ double var6 = par1Entity.motionY;
+ double var8 = par1Entity.motionZ;
+ double var10 = 3.9D;
+
+ if (var4 < -var10) {
+ var4 = -var10;
+ }
+
+ if (var6 < -var10) {
+ var6 = -var10;
+ }
+
+ if (var8 < -var10) {
+ var8 = -var10;
+ }
+
+ if (var4 > var10) {
+ var4 = var10;
+ }
+
+ if (var6 > var10) {
+ var6 = var10;
+ }
+
+ if (var8 > var10) {
+ var8 = var10;
+ }
+
+ this.speedX = (int) (var4 * 8000.0D);
+ this.speedY = (int) (var6 * 8000.0D);
+ this.speedZ = (int) (var8 * 8000.0D);
+ }
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.entityId = par1DataInputStream.readInt();
+ this.type = par1DataInputStream.readByte();
+ this.xPosition = par1DataInputStream.readInt();
+ this.yPosition = par1DataInputStream.readInt();
+ this.zPosition = par1DataInputStream.readInt();
+ this.pitch = par1DataInputStream.readByte();
+ this.yaw = par1DataInputStream.readByte();
+ this.throwerEntityId = par1DataInputStream.readInt();
+
+ if (this.throwerEntityId > 0) {
+ this.speedX = par1DataInputStream.readShort();
+ this.speedY = par1DataInputStream.readShort();
+ this.speedZ = par1DataInputStream.readShort();
+ }
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeInt(this.entityId);
+ par1DataOutputStream.writeByte(this.type);
+ par1DataOutputStream.writeInt(this.xPosition);
+ par1DataOutputStream.writeInt(this.yPosition);
+ par1DataOutputStream.writeInt(this.zPosition);
+ par1DataOutputStream.writeByte(this.pitch);
+ par1DataOutputStream.writeByte(this.yaw);
+ par1DataOutputStream.writeInt(this.throwerEntityId);
+
+ if (this.throwerEntityId > 0) {
+ par1DataOutputStream.writeShort(this.speedX);
+ par1DataOutputStream.writeShort(this.speedY);
+ par1DataOutputStream.writeShort(this.speedZ);
+ }
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleVehicleSpawn(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 21 + this.throwerEntityId > 0 ? 6 : 0;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet24MobSpawn.java b/sp-server/src/main/java/net/minecraft/src/Packet24MobSpawn.java
new file mode 100644
index 0000000..35e430e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet24MobSpawn.java
@@ -0,0 +1,136 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.List;
+
+public class Packet24MobSpawn extends Packet {
+ /** The entity ID. */
+ public int entityId;
+
+ /** The type of mob. */
+ public int type;
+
+ /** The X position of the entity. */
+ public int xPosition;
+
+ /** The Y position of the entity. */
+ public int yPosition;
+
+ /** The Z position of the entity. */
+ public int zPosition;
+ public int velocityX;
+ public int velocityY;
+ public int velocityZ;
+
+ /** The yaw of the entity. */
+ public byte yaw;
+
+ /** The pitch of the entity. */
+ public byte pitch;
+
+ /** The yaw of the entity's head. */
+ public byte headYaw;
+
+ /** Indexed metadata for Mob, terminated by 0x7F */
+ private DataWatcher metaData;
+ private List metadata;
+
+ public Packet24MobSpawn() {
+ }
+
+ public Packet24MobSpawn(EntityLiving par1EntityLiving) {
+ this.entityId = par1EntityLiving.entityId;
+ this.type = (byte) EntityList.getEntityID(par1EntityLiving);
+ this.xPosition = par1EntityLiving.myEntitySize.multiplyBy32AndRound(par1EntityLiving.posX);
+ this.yPosition = MathHelper.floor_double(par1EntityLiving.posY * 32.0D);
+ this.zPosition = par1EntityLiving.myEntitySize.multiplyBy32AndRound(par1EntityLiving.posZ);
+ this.yaw = (byte) ((int) (par1EntityLiving.rotationYaw * 256.0F / 360.0F));
+ this.pitch = (byte) ((int) (par1EntityLiving.rotationPitch * 256.0F / 360.0F));
+ this.headYaw = (byte) ((int) (par1EntityLiving.rotationYawHead * 256.0F / 360.0F));
+ double var2 = 3.9D;
+ double var4 = par1EntityLiving.motionX;
+ double var6 = par1EntityLiving.motionY;
+ double var8 = par1EntityLiving.motionZ;
+
+ if (var4 < -var2) {
+ var4 = -var2;
+ }
+
+ if (var6 < -var2) {
+ var6 = -var2;
+ }
+
+ if (var8 < -var2) {
+ var8 = -var2;
+ }
+
+ if (var4 > var2) {
+ var4 = var2;
+ }
+
+ if (var6 > var2) {
+ var6 = var2;
+ }
+
+ if (var8 > var2) {
+ var8 = var2;
+ }
+
+ this.velocityX = (int) (var4 * 8000.0D);
+ this.velocityY = (int) (var6 * 8000.0D);
+ this.velocityZ = (int) (var8 * 8000.0D);
+ this.metaData = par1EntityLiving.getDataWatcher();
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.entityId = par1DataInputStream.readInt();
+ this.type = par1DataInputStream.readByte() & 255;
+ this.xPosition = par1DataInputStream.readInt();
+ this.yPosition = par1DataInputStream.readInt();
+ this.zPosition = par1DataInputStream.readInt();
+ this.yaw = par1DataInputStream.readByte();
+ this.pitch = par1DataInputStream.readByte();
+ this.headYaw = par1DataInputStream.readByte();
+ this.velocityX = par1DataInputStream.readShort();
+ this.velocityY = par1DataInputStream.readShort();
+ this.velocityZ = par1DataInputStream.readShort();
+ this.metadata = DataWatcher.readWatchableObjects(par1DataInputStream);
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeInt(this.entityId);
+ par1DataOutputStream.writeByte(this.type & 255);
+ par1DataOutputStream.writeInt(this.xPosition);
+ par1DataOutputStream.writeInt(this.yPosition);
+ par1DataOutputStream.writeInt(this.zPosition);
+ par1DataOutputStream.writeByte(this.yaw);
+ par1DataOutputStream.writeByte(this.pitch);
+ par1DataOutputStream.writeByte(this.headYaw);
+ par1DataOutputStream.writeShort(this.velocityX);
+ par1DataOutputStream.writeShort(this.velocityY);
+ par1DataOutputStream.writeShort(this.velocityZ);
+ this.metaData.writeWatchableObjects(par1DataOutputStream);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleMobSpawn(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 26;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet250CustomPayload.java b/sp-server/src/main/java/net/minecraft/src/Packet250CustomPayload.java
new file mode 100644
index 0000000..4be3a8f
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet250CustomPayload.java
@@ -0,0 +1,71 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet250CustomPayload extends Packet {
+ /** Name of the 'channel' used to send data */
+ public String channel;
+
+ /** Length of the data to be read */
+ public int length;
+
+ /** Any data */
+ public byte[] data;
+
+ public Packet250CustomPayload() {
+ }
+
+ public Packet250CustomPayload(String par1Str, byte[] par2ArrayOfByte) {
+ this.channel = par1Str;
+ this.data = par2ArrayOfByte;
+
+ if (par2ArrayOfByte != null) {
+ this.length = par2ArrayOfByte.length;
+
+ if (this.length > 32767) {
+ throw new IllegalArgumentException("Payload may not be larger than 32k");
+ }
+ }
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.channel = readString(par1DataInputStream, 20);
+ this.length = par1DataInputStream.readShort();
+
+ if (this.length > 0 && this.length < 32767) {
+ this.data = new byte[this.length];
+ par1DataInputStream.readFully(this.data);
+ }
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ writeString(this.channel, par1DataOutputStream);
+ par1DataOutputStream.writeShort((short) this.length);
+
+ if (this.data != null) {
+ par1DataOutputStream.write(this.data);
+ }
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleCustomPayload(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 2 + this.channel.length() * 2 + 2 + this.length;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet254ServerPing.java b/sp-server/src/main/java/net/minecraft/src/Packet254ServerPing.java
new file mode 100644
index 0000000..ec9268a
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet254ServerPing.java
@@ -0,0 +1,41 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet254ServerPing extends Packet {
+ /** Always 1, unless readByte threw an exception. */
+ public int readSuccessfully = 0;
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ try {
+ this.readSuccessfully = par1DataInputStream.readByte();
+ } catch (Throwable var3) {
+ this.readSuccessfully = 0;
+ }
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleServerPing(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 0;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet255KickDisconnect.java b/sp-server/src/main/java/net/minecraft/src/Packet255KickDisconnect.java
new file mode 100644
index 0000000..829e01d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet255KickDisconnect.java
@@ -0,0 +1,60 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet255KickDisconnect extends Packet {
+ /** Displayed to the client when the connection terminates. */
+ public String reason;
+
+ public Packet255KickDisconnect() {
+ }
+
+ public Packet255KickDisconnect(String par1Str) {
+ this.reason = par1Str;
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.reason = readString(par1DataInputStream, 256);
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ writeString(this.reason, par1DataOutputStream);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleKickDisconnect(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return this.reason.length();
+ }
+
+ /**
+ * only false for the abstract Packet class, all real packets return true
+ */
+ public boolean isRealPacket() {
+ return true;
+ }
+
+ /**
+ * eg return packet30entity.entityId == entityId; WARNING : will throw if you
+ * compare a packet to a different packet class
+ */
+ public boolean containsSameEntityIDAs(Packet par1Packet) {
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet25EntityPainting.java b/sp-server/src/main/java/net/minecraft/src/Packet25EntityPainting.java
new file mode 100644
index 0000000..d2e779d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet25EntityPainting.java
@@ -0,0 +1,64 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet25EntityPainting extends Packet {
+ public int entityId;
+ public int xPosition;
+ public int yPosition;
+ public int zPosition;
+ public int direction;
+ public String title;
+
+ public Packet25EntityPainting() {
+ }
+
+ public Packet25EntityPainting(EntityPainting par1EntityPainting) {
+ this.entityId = par1EntityPainting.entityId;
+ this.xPosition = par1EntityPainting.xPosition;
+ this.yPosition = par1EntityPainting.yPosition;
+ this.zPosition = par1EntityPainting.zPosition;
+ this.direction = par1EntityPainting.hangingDirection;
+ this.title = par1EntityPainting.art.title;
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.entityId = par1DataInputStream.readInt();
+ this.title = readString(par1DataInputStream, EnumArt.maxArtTitleLength);
+ this.xPosition = par1DataInputStream.readInt();
+ this.yPosition = par1DataInputStream.readInt();
+ this.zPosition = par1DataInputStream.readInt();
+ this.direction = par1DataInputStream.readInt();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeInt(this.entityId);
+ writeString(this.title, par1DataOutputStream);
+ par1DataOutputStream.writeInt(this.xPosition);
+ par1DataOutputStream.writeInt(this.yPosition);
+ par1DataOutputStream.writeInt(this.zPosition);
+ par1DataOutputStream.writeInt(this.direction);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleEntityPainting(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 24;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet26EntityExpOrb.java b/sp-server/src/main/java/net/minecraft/src/Packet26EntityExpOrb.java
new file mode 100644
index 0000000..4686f7b
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet26EntityExpOrb.java
@@ -0,0 +1,63 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet26EntityExpOrb extends Packet {
+ /** Entity ID for the XP Orb */
+ public int entityId;
+ public int posX;
+ public int posY;
+ public int posZ;
+
+ /** The Orbs Experience points value. */
+ public int xpValue;
+
+ public Packet26EntityExpOrb() {
+ }
+
+ public Packet26EntityExpOrb(EntityXPOrb par1EntityXPOrb) {
+ this.entityId = par1EntityXPOrb.entityId;
+ this.posX = MathHelper.floor_double(par1EntityXPOrb.posX * 32.0D);
+ this.posY = MathHelper.floor_double(par1EntityXPOrb.posY * 32.0D);
+ this.posZ = MathHelper.floor_double(par1EntityXPOrb.posZ * 32.0D);
+ this.xpValue = par1EntityXPOrb.getXpValue();
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.entityId = par1DataInputStream.readInt();
+ this.posX = par1DataInputStream.readInt();
+ this.posY = par1DataInputStream.readInt();
+ this.posZ = par1DataInputStream.readInt();
+ this.xpValue = par1DataInputStream.readShort();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeInt(this.entityId);
+ par1DataOutputStream.writeInt(this.posX);
+ par1DataOutputStream.writeInt(this.posY);
+ par1DataOutputStream.writeInt(this.posZ);
+ par1DataOutputStream.writeShort(this.xpValue);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleEntityExpOrb(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 18;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet28EntityVelocity.java b/sp-server/src/main/java/net/minecraft/src/Packet28EntityVelocity.java
new file mode 100644
index 0000000..24a7153
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet28EntityVelocity.java
@@ -0,0 +1,102 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet28EntityVelocity extends Packet {
+ public int entityId;
+ public int motionX;
+ public int motionY;
+ public int motionZ;
+
+ public Packet28EntityVelocity() {
+ }
+
+ public Packet28EntityVelocity(Entity par1Entity) {
+ this(par1Entity.entityId, par1Entity.motionX, par1Entity.motionY, par1Entity.motionZ);
+ }
+
+ public Packet28EntityVelocity(int par1, double par2, double par4, double par6) {
+ this.entityId = par1;
+ double var8 = 3.9D;
+
+ if (par2 < -var8) {
+ par2 = -var8;
+ }
+
+ if (par4 < -var8) {
+ par4 = -var8;
+ }
+
+ if (par6 < -var8) {
+ par6 = -var8;
+ }
+
+ if (par2 > var8) {
+ par2 = var8;
+ }
+
+ if (par4 > var8) {
+ par4 = var8;
+ }
+
+ if (par6 > var8) {
+ par6 = var8;
+ }
+
+ this.motionX = (int) (par2 * 8000.0D);
+ this.motionY = (int) (par4 * 8000.0D);
+ this.motionZ = (int) (par6 * 8000.0D);
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.entityId = par1DataInputStream.readInt();
+ this.motionX = par1DataInputStream.readShort();
+ this.motionY = par1DataInputStream.readShort();
+ this.motionZ = par1DataInputStream.readShort();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeInt(this.entityId);
+ par1DataOutputStream.writeShort(this.motionX);
+ par1DataOutputStream.writeShort(this.motionY);
+ par1DataOutputStream.writeShort(this.motionZ);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleEntityVelocity(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 10;
+ }
+
+ /**
+ * only false for the abstract Packet class, all real packets return true
+ */
+ public boolean isRealPacket() {
+ return true;
+ }
+
+ /**
+ * eg return packet30entity.entityId == entityId; WARNING : will throw if you
+ * compare a packet to a different packet class
+ */
+ public boolean containsSameEntityIDAs(Packet par1Packet) {
+ Packet28EntityVelocity var2 = (Packet28EntityVelocity) par1Packet;
+ return var2.entityId == this.entityId;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet29DestroyEntity.java b/sp-server/src/main/java/net/minecraft/src/Packet29DestroyEntity.java
new file mode 100644
index 0000000..ed8bea1
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet29DestroyEntity.java
@@ -0,0 +1,53 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet29DestroyEntity extends Packet {
+ /** ID of the entity to be destroyed on the client. */
+ public int[] entityId;
+
+ public Packet29DestroyEntity() {
+ }
+
+ public Packet29DestroyEntity(int... par1ArrayOfInteger) {
+ this.entityId = par1ArrayOfInteger;
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.entityId = new int[par1DataInputStream.readByte()];
+
+ for (int var2 = 0; var2 < this.entityId.length; ++var2) {
+ this.entityId[var2] = par1DataInputStream.readInt();
+ }
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeByte(this.entityId.length);
+
+ for (int var2 = 0; var2 < this.entityId.length; ++var2) {
+ par1DataOutputStream.writeInt(this.entityId[var2]);
+ }
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleDestroyEntity(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 1 + this.entityId.length * 4;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet2ClientProtocol.java b/sp-server/src/main/java/net/minecraft/src/Packet2ClientProtocol.java
new file mode 100644
index 0000000..0802342
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet2ClientProtocol.java
@@ -0,0 +1,65 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet2ClientProtocol extends Packet {
+ private int protocolVersion;
+ private String username;
+ private String serverHost;
+ private int viewDistance;
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.protocolVersion = par1DataInputStream.readByte();
+ this.username = readString(par1DataInputStream, 16);
+ this.serverHost = readString(par1DataInputStream, 255);
+ this.viewDistance = par1DataInputStream.readInt();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeByte(this.protocolVersion);
+ writeString(this.username, par1DataOutputStream);
+ writeString(this.serverHost, par1DataOutputStream);
+ par1DataOutputStream.writeInt(this.viewDistance);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleClientProtocol(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 3 + 2 * this.username.length();
+ }
+
+ /**
+ * Returns the protocol version.
+ */
+ public int getProtocolVersion() {
+ return this.protocolVersion;
+ }
+
+ /**
+ * Returns the username.
+ */
+ public String getUsername() {
+ return this.username;
+ }
+
+ public int getViewDistance() {
+ return this.viewDistance;
+ }
+
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet30Entity.java b/sp-server/src/main/java/net/minecraft/src/Packet30Entity.java
new file mode 100644
index 0000000..ecd074c
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet30Entity.java
@@ -0,0 +1,83 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet30Entity extends Packet {
+ /** The ID of this entity. */
+ public int entityId;
+
+ /** The X axis relative movement. */
+ public byte xPosition;
+
+ /** The Y axis relative movement. */
+ public byte yPosition;
+
+ /** The Z axis relative movement. */
+ public byte zPosition;
+
+ /** The X axis rotation. */
+ public byte yaw;
+
+ /** The Y axis rotation. */
+ public byte pitch;
+
+ /** Boolean set to true if the entity is rotating. */
+ public boolean rotating = false;
+
+ public Packet30Entity() {
+ }
+
+ public Packet30Entity(int par1) {
+ this.entityId = par1;
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.entityId = par1DataInputStream.readInt();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeInt(this.entityId);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleEntity(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 4;
+ }
+
+ public String toString() {
+ return "Entity_" + super.toString();
+ }
+
+ /**
+ * only false for the abstract Packet class, all real packets return true
+ */
+ public boolean isRealPacket() {
+ return true;
+ }
+
+ /**
+ * eg return packet30entity.entityId == entityId; WARNING : will throw if you
+ * compare a packet to a different packet class
+ */
+ public boolean containsSameEntityIDAs(Packet par1Packet) {
+ Packet30Entity var2 = (Packet30Entity) par1Packet;
+ return var2.entityId == this.entityId;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet31RelEntityMove.java b/sp-server/src/main/java/net/minecraft/src/Packet31RelEntityMove.java
new file mode 100644
index 0000000..d0199a6
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet31RelEntityMove.java
@@ -0,0 +1,44 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet31RelEntityMove extends Packet30Entity {
+ public Packet31RelEntityMove() {
+ }
+
+ public Packet31RelEntityMove(int par1, byte par2, byte par3, byte par4) {
+ super(par1);
+ this.xPosition = par2;
+ this.yPosition = par3;
+ this.zPosition = par4;
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ super.readPacketData(par1DataInputStream);
+ this.xPosition = par1DataInputStream.readByte();
+ this.yPosition = par1DataInputStream.readByte();
+ this.zPosition = par1DataInputStream.readByte();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ super.writePacketData(par1DataOutputStream);
+ par1DataOutputStream.writeByte(this.xPosition);
+ par1DataOutputStream.writeByte(this.yPosition);
+ par1DataOutputStream.writeByte(this.zPosition);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 7;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet32EntityLook.java b/sp-server/src/main/java/net/minecraft/src/Packet32EntityLook.java
new file mode 100644
index 0000000..3b4034e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet32EntityLook.java
@@ -0,0 +1,43 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet32EntityLook extends Packet30Entity {
+ public Packet32EntityLook() {
+ this.rotating = true;
+ }
+
+ public Packet32EntityLook(int par1, byte par2, byte par3) {
+ super(par1);
+ this.yaw = par2;
+ this.pitch = par3;
+ this.rotating = true;
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ super.readPacketData(par1DataInputStream);
+ this.yaw = par1DataInputStream.readByte();
+ this.pitch = par1DataInputStream.readByte();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ super.writePacketData(par1DataOutputStream);
+ par1DataOutputStream.writeByte(this.yaw);
+ par1DataOutputStream.writeByte(this.pitch);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 6;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet33RelEntityMoveLook.java b/sp-server/src/main/java/net/minecraft/src/Packet33RelEntityMoveLook.java
new file mode 100644
index 0000000..4af3007
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet33RelEntityMoveLook.java
@@ -0,0 +1,52 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet33RelEntityMoveLook extends Packet30Entity {
+ public Packet33RelEntityMoveLook() {
+ this.rotating = true;
+ }
+
+ public Packet33RelEntityMoveLook(int par1, byte par2, byte par3, byte par4, byte par5, byte par6) {
+ super(par1);
+ this.xPosition = par2;
+ this.yPosition = par3;
+ this.zPosition = par4;
+ this.yaw = par5;
+ this.pitch = par6;
+ this.rotating = true;
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ super.readPacketData(par1DataInputStream);
+ this.xPosition = par1DataInputStream.readByte();
+ this.yPosition = par1DataInputStream.readByte();
+ this.zPosition = par1DataInputStream.readByte();
+ this.yaw = par1DataInputStream.readByte();
+ this.pitch = par1DataInputStream.readByte();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ super.writePacketData(par1DataOutputStream);
+ par1DataOutputStream.writeByte(this.xPosition);
+ par1DataOutputStream.writeByte(this.yPosition);
+ par1DataOutputStream.writeByte(this.zPosition);
+ par1DataOutputStream.writeByte(this.yaw);
+ par1DataOutputStream.writeByte(this.pitch);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 9;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet34EntityTeleport.java b/sp-server/src/main/java/net/minecraft/src/Packet34EntityTeleport.java
new file mode 100644
index 0000000..1b58eaa
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet34EntityTeleport.java
@@ -0,0 +1,100 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet34EntityTeleport extends Packet {
+ /** ID of the entity. */
+ public int entityId;
+
+ /** X position of the entity. */
+ public int xPosition;
+
+ /** Y position of the entity. */
+ public int yPosition;
+
+ /** Z position of the entity. */
+ public int zPosition;
+
+ /** Yaw of the entity. */
+ public byte yaw;
+
+ /** Pitch of the entity. */
+ public byte pitch;
+
+ public Packet34EntityTeleport() {
+ }
+
+ public Packet34EntityTeleport(Entity par1Entity) {
+ this.entityId = par1Entity.entityId;
+ this.xPosition = MathHelper.floor_double(par1Entity.posX * 32.0D);
+ this.yPosition = MathHelper.floor_double(par1Entity.posY * 32.0D);
+ this.zPosition = MathHelper.floor_double(par1Entity.posZ * 32.0D);
+ this.yaw = (byte) ((int) (par1Entity.rotationYaw * 256.0F / 360.0F));
+ this.pitch = (byte) ((int) (par1Entity.rotationPitch * 256.0F / 360.0F));
+ }
+
+ public Packet34EntityTeleport(int par1, int par2, int par3, int par4, byte par5, byte par6) {
+ this.entityId = par1;
+ this.xPosition = par2;
+ this.yPosition = par3;
+ this.zPosition = par4;
+ this.yaw = par5;
+ this.pitch = par6;
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.entityId = par1DataInputStream.readInt();
+ this.xPosition = par1DataInputStream.readInt();
+ this.yPosition = par1DataInputStream.readInt();
+ this.zPosition = par1DataInputStream.readInt();
+ this.yaw = (byte) par1DataInputStream.read();
+ this.pitch = (byte) par1DataInputStream.read();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeInt(this.entityId);
+ par1DataOutputStream.writeInt(this.xPosition);
+ par1DataOutputStream.writeInt(this.yPosition);
+ par1DataOutputStream.writeInt(this.zPosition);
+ par1DataOutputStream.write(this.yaw);
+ par1DataOutputStream.write(this.pitch);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleEntityTeleport(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 34;
+ }
+
+ /**
+ * only false for the abstract Packet class, all real packets return true
+ */
+ public boolean isRealPacket() {
+ return true;
+ }
+
+ /**
+ * eg return packet30entity.entityId == entityId; WARNING : will throw if you
+ * compare a packet to a different packet class
+ */
+ public boolean containsSameEntityIDAs(Packet par1Packet) {
+ Packet34EntityTeleport var2 = (Packet34EntityTeleport) par1Packet;
+ return var2.entityId == this.entityId;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet35EntityHeadRotation.java b/sp-server/src/main/java/net/minecraft/src/Packet35EntityHeadRotation.java
new file mode 100644
index 0000000..62962cc
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet35EntityHeadRotation.java
@@ -0,0 +1,72 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet35EntityHeadRotation extends Packet {
+ public int entityId;
+ public byte headRotationYaw;
+
+ public Packet35EntityHeadRotation() {
+ }
+
+ public Packet35EntityHeadRotation(int par1, byte par2) {
+ this.entityId = par1;
+ this.headRotationYaw = par2;
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.entityId = par1DataInputStream.readInt();
+ this.headRotationYaw = par1DataInputStream.readByte();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeInt(this.entityId);
+ par1DataOutputStream.writeByte(this.headRotationYaw);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleEntityHeadRotation(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 5;
+ }
+
+ /**
+ * only false for the abstract Packet class, all real packets return true
+ */
+ public boolean isRealPacket() {
+ return true;
+ }
+
+ /**
+ * eg return packet30entity.entityId == entityId; WARNING : will throw if you
+ * compare a packet to a different packet class
+ */
+ public boolean containsSameEntityIDAs(Packet par1Packet) {
+ Packet35EntityHeadRotation var2 = (Packet35EntityHeadRotation) par1Packet;
+ return var2.entityId == this.entityId;
+ }
+
+ /**
+ * If this returns true, the packet may be processed on any thread; otherwise it
+ * is queued for the main thread to handle.
+ */
+ public boolean canProcessAsync() {
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet38EntityStatus.java b/sp-server/src/main/java/net/minecraft/src/Packet38EntityStatus.java
new file mode 100644
index 0000000..f675fd7
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet38EntityStatus.java
@@ -0,0 +1,50 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet38EntityStatus extends Packet {
+ public int entityId;
+
+ /** 2 for hurt, 3 for dead */
+ public byte entityStatus;
+
+ public Packet38EntityStatus() {
+ }
+
+ public Packet38EntityStatus(int par1, byte par2) {
+ this.entityId = par1;
+ this.entityStatus = par2;
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.entityId = par1DataInputStream.readInt();
+ this.entityStatus = par1DataInputStream.readByte();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeInt(this.entityId);
+ par1DataOutputStream.writeByte(this.entityStatus);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleEntityStatus(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 5;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet39AttachEntity.java b/sp-server/src/main/java/net/minecraft/src/Packet39AttachEntity.java
new file mode 100644
index 0000000..2b390d3
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet39AttachEntity.java
@@ -0,0 +1,64 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet39AttachEntity extends Packet {
+ public int entityId;
+ public int vehicleEntityId;
+
+ public Packet39AttachEntity() {
+ }
+
+ public Packet39AttachEntity(Entity par1Entity, Entity par2Entity) {
+ this.entityId = par1Entity.entityId;
+ this.vehicleEntityId = par2Entity != null ? par2Entity.entityId : -1;
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 8;
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.entityId = par1DataInputStream.readInt();
+ this.vehicleEntityId = par1DataInputStream.readInt();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeInt(this.entityId);
+ par1DataOutputStream.writeInt(this.vehicleEntityId);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleAttachEntity(this);
+ }
+
+ /**
+ * only false for the abstract Packet class, all real packets return true
+ */
+ public boolean isRealPacket() {
+ return true;
+ }
+
+ /**
+ * eg return packet30entity.entityId == entityId; WARNING : will throw if you
+ * compare a packet to a different packet class
+ */
+ public boolean containsSameEntityIDAs(Packet par1Packet) {
+ Packet39AttachEntity var2 = (Packet39AttachEntity) par1Packet;
+ return var2.entityId == this.entityId;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet3Chat.java b/sp-server/src/main/java/net/minecraft/src/Packet3Chat.java
new file mode 100644
index 0000000..426b9ea
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet3Chat.java
@@ -0,0 +1,76 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet3Chat extends Packet {
+ /** Maximum number of characters allowed in chat string in each packet. */
+ public static int maxChatLength = 119;
+
+ /** The message being sent. */
+ public String message;
+ private boolean isServer;
+
+ public Packet3Chat() {
+ this.isServer = true;
+ }
+
+ public Packet3Chat(String par1Str) {
+ this(par1Str, true);
+ }
+
+ public Packet3Chat(String par1Str, boolean par2) {
+ this.isServer = true;
+
+ if (par1Str.length() > maxChatLength) {
+ par1Str = par1Str.substring(0, maxChatLength);
+ }
+
+ this.message = par1Str;
+ this.isServer = par2;
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.message = readString(par1DataInputStream, maxChatLength);
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ writeString(this.message, par1DataOutputStream);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleChat(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 2 + this.message.length() * 2;
+ }
+
+ /**
+ * Get whether this is a server
+ */
+ public boolean getIsServer() {
+ return this.isServer;
+ }
+
+ /**
+ * If this returns true, the packet may be processed on any thread; otherwise it
+ * is queued for the main thread to handle.
+ */
+ public boolean canProcessAsync() {
+ return !this.message.startsWith("/");
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet40EntityMetadata.java b/sp-server/src/main/java/net/minecraft/src/Packet40EntityMetadata.java
new file mode 100644
index 0000000..73e33d5
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet40EntityMetadata.java
@@ -0,0 +1,54 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.List;
+
+public class Packet40EntityMetadata extends Packet {
+ public int entityId;
+ private List metadata;
+
+ public Packet40EntityMetadata() {
+ }
+
+ public Packet40EntityMetadata(int par1, DataWatcher par2DataWatcher, boolean par3) {
+ this.entityId = par1;
+
+ if (par3) {
+ this.metadata = par2DataWatcher.getAllWatched();
+ } else {
+ this.metadata = par2DataWatcher.unwatchAndReturnAllWatched();
+ }
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.entityId = par1DataInputStream.readInt();
+ this.metadata = DataWatcher.readWatchableObjects(par1DataInputStream);
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeInt(this.entityId);
+ DataWatcher.writeObjectsInListToStream(this.metadata, par1DataOutputStream);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleEntityMetadata(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 5;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet41EntityEffect.java b/sp-server/src/main/java/net/minecraft/src/Packet41EntityEffect.java
new file mode 100644
index 0000000..0da5e0d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet41EntityEffect.java
@@ -0,0 +1,79 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet41EntityEffect extends Packet {
+ public int entityId;
+ public byte effectId;
+
+ /** The effect's amplifier. */
+ public byte effectAmplifier;
+ public short duration;
+
+ public Packet41EntityEffect() {
+ }
+
+ public Packet41EntityEffect(int par1, PotionEffect par2PotionEffect) {
+ this.entityId = par1;
+ this.effectId = (byte) (par2PotionEffect.getPotionID() & 255);
+ this.effectAmplifier = (byte) (par2PotionEffect.getAmplifier() & 255);
+
+ if (par2PotionEffect.getDuration() > 32767) {
+ this.duration = 32767;
+ } else {
+ this.duration = (short) par2PotionEffect.getDuration();
+ }
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.entityId = par1DataInputStream.readInt();
+ this.effectId = par1DataInputStream.readByte();
+ this.effectAmplifier = par1DataInputStream.readByte();
+ this.duration = par1DataInputStream.readShort();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeInt(this.entityId);
+ par1DataOutputStream.writeByte(this.effectId);
+ par1DataOutputStream.writeByte(this.effectAmplifier);
+ par1DataOutputStream.writeShort(this.duration);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleEntityEffect(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 8;
+ }
+
+ /**
+ * only false for the abstract Packet class, all real packets return true
+ */
+ public boolean isRealPacket() {
+ return true;
+ }
+
+ /**
+ * eg return packet30entity.entityId == entityId; WARNING : will throw if you
+ * compare a packet to a different packet class
+ */
+ public boolean containsSameEntityIDAs(Packet par1Packet) {
+ Packet41EntityEffect var2 = (Packet41EntityEffect) par1Packet;
+ return var2.entityId == this.entityId && var2.effectId == this.effectId;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet42RemoveEntityEffect.java b/sp-server/src/main/java/net/minecraft/src/Packet42RemoveEntityEffect.java
new file mode 100644
index 0000000..448f37e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet42RemoveEntityEffect.java
@@ -0,0 +1,51 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet42RemoveEntityEffect extends Packet {
+ /** The ID of the entity which an effect is being removed from. */
+ public int entityId;
+
+ /** The ID of the effect which is being removed from an entity. */
+ public byte effectId;
+
+ public Packet42RemoveEntityEffect() {
+ }
+
+ public Packet42RemoveEntityEffect(int par1, PotionEffect par2PotionEffect) {
+ this.entityId = par1;
+ this.effectId = (byte) (par2PotionEffect.getPotionID() & 255);
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.entityId = par1DataInputStream.readInt();
+ this.effectId = par1DataInputStream.readByte();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeInt(this.entityId);
+ par1DataOutputStream.writeByte(this.effectId);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleRemoveEntityEffect(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 5;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet43Experience.java b/sp-server/src/main/java/net/minecraft/src/Packet43Experience.java
new file mode 100644
index 0000000..8fcc2da
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet43Experience.java
@@ -0,0 +1,72 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet43Experience extends Packet {
+ /** The current experience bar points. */
+ public float experience;
+
+ /** The total experience points. */
+ public int experienceTotal;
+
+ /** The experience level. */
+ public int experienceLevel;
+
+ public Packet43Experience() {
+ }
+
+ public Packet43Experience(float par1, int par2, int par3) {
+ this.experience = par1;
+ this.experienceTotal = par2;
+ this.experienceLevel = par3;
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.experience = par1DataInputStream.readFloat();
+ this.experienceLevel = par1DataInputStream.readShort();
+ this.experienceTotal = par1DataInputStream.readShort();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeFloat(this.experience);
+ par1DataOutputStream.writeShort(this.experienceLevel);
+ par1DataOutputStream.writeShort(this.experienceTotal);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleExperience(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 4;
+ }
+
+ /**
+ * only false for the abstract Packet class, all real packets return true
+ */
+ public boolean isRealPacket() {
+ return true;
+ }
+
+ /**
+ * eg return packet30entity.entityId == entityId; WARNING : will throw if you
+ * compare a packet to a different packet class
+ */
+ public boolean containsSameEntityIDAs(Packet par1Packet) {
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet4UpdateTime.java b/sp-server/src/main/java/net/minecraft/src/Packet4UpdateTime.java
new file mode 100644
index 0000000..58b6ad8
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet4UpdateTime.java
@@ -0,0 +1,74 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet4UpdateTime extends Packet {
+ /** World age in ticks. */
+ public long worldAge;
+
+ /** The world time in minutes. */
+ public long time;
+
+ public Packet4UpdateTime() {
+ }
+
+ public Packet4UpdateTime(long par1, long par3) {
+ this.worldAge = par1;
+ this.time = par3;
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.worldAge = par1DataInputStream.readLong();
+ this.time = par1DataInputStream.readLong();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeLong(this.worldAge);
+ par1DataOutputStream.writeLong(this.time);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleUpdateTime(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 16;
+ }
+
+ /**
+ * only false for the abstract Packet class, all real packets return true
+ */
+ public boolean isRealPacket() {
+ return true;
+ }
+
+ /**
+ * eg return packet30entity.entityId == entityId; WARNING : will throw if you
+ * compare a packet to a different packet class
+ */
+ public boolean containsSameEntityIDAs(Packet par1Packet) {
+ return true;
+ }
+
+ /**
+ * If this returns true, the packet may be processed on any thread; otherwise it
+ * is queued for the main thread to handle.
+ */
+ public boolean canProcessAsync() {
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet51MapChunk.java b/sp-server/src/main/java/net/minecraft/src/Packet51MapChunk.java
new file mode 100644
index 0000000..ed86b65
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet51MapChunk.java
@@ -0,0 +1,222 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet51MapChunk extends Packet {
+ /** The x-position of the transmitted chunk, in chunk coordinates. */
+ public int xCh;
+
+ /** The z-position of the transmitted chunk, in chunk coordinates. */
+ public int zCh;
+
+ /**
+ * The y-position of the lowest chunk Section in the transmitted chunk, in chunk
+ * coordinates.
+ */
+ public int yChMin;
+
+ /**
+ * The y-position of the highest chunk Section in the transmitted chunk, in
+ * chunk coordinates.
+ */
+ public int yChMax;
+
+ /** The transmitted chunk data, decompressed. */
+ private byte[] chunkData;
+
+ /** The compressed chunk data */
+ private byte[] compressedChunkData;
+
+ /**
+ * Whether to initialize the Chunk before applying the effect of the
+ * Packet51MapChunk.
+ */
+ public boolean includeInitialize;
+
+ /** The length of the compressed chunk data byte array. */
+ private int tempLength;
+
+ /** A temporary storage for the compressed chunk data byte array. */
+ private static byte[] temp = new byte[196864];
+
+ public Packet51MapChunk() {
+ this.isChunkDataPacket = true;
+ }
+
+ public Packet51MapChunk(Chunk par1Chunk, boolean par2, int par3) {
+ this.isChunkDataPacket = true;
+ this.xCh = par1Chunk.xPosition;
+ this.zCh = par1Chunk.zPosition;
+ this.includeInitialize = par2;
+ Packet51MapChunkData var4 = getMapChunkData(par1Chunk, par2, par3);
+ //Deflater var5 = new Deflater(-1);
+ this.yChMax = var4.chunkHasAddSectionFlag;
+ this.yChMin = var4.chunkExistFlag;
+
+ //try {
+ //this.compressedChunkData = var4.compressedData;
+ //var5.setInput(var4.compressedData, 0, var4.compressedData.length);
+ //var5.finish();
+ this.chunkData = var4.compressedData;
+ this.tempLength = var4.compressedData.length;
+ //} finally {
+ // var5.end();
+ //}
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.xCh = par1DataInputStream.readInt();
+ this.zCh = par1DataInputStream.readInt();
+ this.includeInitialize = par1DataInputStream.readBoolean();
+ this.yChMin = par1DataInputStream.readShort();
+ this.yChMax = par1DataInputStream.readShort();
+ this.tempLength = par1DataInputStream.readInt();
+ this.compressedChunkData = new byte[this.tempLength];
+ par1DataInputStream.readFully(this.compressedChunkData, 0, this.tempLength);
+/*
+ if (temp.length < this.tempLength) {
+ temp = new byte[this.tempLength];
+ }
+
+ par1DataInputStream.readFully(temp, 0, this.tempLength);
+ int var2 = 0;
+ int var3;
+
+ for (var3 = 0; var3 < 16; ++var3) {
+ var2 += this.yChMin >> var3 & 1;
+ }
+
+ var3 = 12288 * var2;
+
+ if (this.includeInitialize) {
+ var3 += 256;
+ }
+
+ this.compressedChunkData = new byte[var3];
+ Inflater var4 = new Inflater();
+ var4.setInput(temp, 0, this.tempLength);
+
+ try {
+ var4.inflate(this.compressedChunkData);
+ } catch (DataFormatException var9) {
+ throw new IOException("Bad compressed data format");
+ } finally {
+ var4.end();
+ }
+*/
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeInt(this.xCh);
+ par1DataOutputStream.writeInt(this.zCh);
+ par1DataOutputStream.writeBoolean(this.includeInitialize);
+ par1DataOutputStream.writeShort((short) (this.yChMin & 65535));
+ par1DataOutputStream.writeShort((short) (this.yChMax & 65535));
+ par1DataOutputStream.writeInt(this.tempLength | 0x10000000);
+ par1DataOutputStream.write(this.chunkData, 0, this.tempLength);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleMapChunk(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 17 + this.tempLength;
+ }
+
+ public static Packet51MapChunkData getMapChunkData(Chunk par0Chunk, boolean par1, int par2) {
+ int var3 = 0;
+ ExtendedBlockStorage[] var4 = par0Chunk.getBlockStorageArray();
+ int var5 = 0;
+ Packet51MapChunkData var6 = new Packet51MapChunkData();
+ byte[] var7 = temp;
+
+ if (par1) {
+ par0Chunk.sendUpdates = true;
+ }
+
+ int var8;
+
+ for (var8 = 0; var8 < var4.length; ++var8) {
+ if (var4[var8] != null && (!par1 || !var4[var8].isEmpty()) && (par2 & 1 << var8) != 0) {
+ var6.chunkExistFlag |= 1 << var8;
+
+ if (var4[var8].getBlockMSBArray() != null) {
+ var6.chunkHasAddSectionFlag |= 1 << var8;
+ ++var5;
+ }
+ }
+ }
+
+ for (var8 = 0; var8 < var4.length; ++var8) {
+ if (var4[var8] != null && (!par1 || !var4[var8].isEmpty()) && (par2 & 1 << var8) != 0) {
+ byte[] var9 = var4[var8].getBlockLSBArray();
+ System.arraycopy(var9, 0, var7, var3, var9.length);
+ var3 += var9.length;
+ }
+ }
+
+ NibbleArray var10;
+
+ for (var8 = 0; var8 < var4.length; ++var8) {
+ if (var4[var8] != null && (!par1 || !var4[var8].isEmpty()) && (par2 & 1 << var8) != 0) {
+ var10 = var4[var8].getMetadataArray();
+ System.arraycopy(var10.data, 0, var7, var3, var10.data.length);
+ var3 += var10.data.length;
+ }
+ }
+
+ for (var8 = 0; var8 < var4.length; ++var8) {
+ if (var4[var8] != null && (!par1 || !var4[var8].isEmpty()) && (par2 & 1 << var8) != 0) {
+ var10 = var4[var8].getBlocklightArray();
+ System.arraycopy(var10.data, 0, var7, var3, var10.data.length);
+ var3 += var10.data.length;
+ }
+ }
+
+ if (!par0Chunk.worldObj.provider.hasNoSky) {
+ for (var8 = 0; var8 < var4.length; ++var8) {
+ if (var4[var8] != null && (!par1 || !var4[var8].isEmpty()) && (par2 & 1 << var8) != 0) {
+ var10 = var4[var8].getSkylightArray();
+ System.arraycopy(var10.data, 0, var7, var3, var10.data.length);
+ var3 += var10.data.length;
+ }
+ }
+ }
+
+ if (var5 > 0) {
+ for (var8 = 0; var8 < var4.length; ++var8) {
+ if (var4[var8] != null && (!par1 || !var4[var8].isEmpty()) && var4[var8].getBlockMSBArray() != null
+ && (par2 & 1 << var8) != 0) {
+ var10 = var4[var8].getBlockMSBArray();
+ System.arraycopy(var10.data, 0, var7, var3, var10.data.length);
+ var3 += var10.data.length;
+ }
+ }
+ }
+
+ if (par1) {
+ byte[] var11 = par0Chunk.getBiomeArray();
+ System.arraycopy(var11, 0, var7, var3, var11.length);
+ var3 += var11.length;
+ }
+
+ var6.compressedData = new byte[var3];
+ System.arraycopy(var7, 0, var6.compressedData, 0, var3);
+ return var6;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet51MapChunkData.java b/sp-server/src/main/java/net/minecraft/src/Packet51MapChunkData.java
new file mode 100644
index 0000000..b15a3e3
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet51MapChunkData.java
@@ -0,0 +1,7 @@
+package net.minecraft.src;
+
+public class Packet51MapChunkData {
+ public byte[] compressedData;
+ public int chunkExistFlag;
+ public int chunkHasAddSectionFlag;
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet52MultiBlockChange.java b/sp-server/src/main/java/net/minecraft/src/Packet52MultiBlockChange.java
new file mode 100644
index 0000000..b10bf27
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet52MultiBlockChange.java
@@ -0,0 +1,111 @@
+package net.minecraft.src;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet52MultiBlockChange extends Packet {
+ /** Chunk X position. */
+ public int xPosition;
+
+ /** Chunk Z position. */
+ public int zPosition;
+
+ /** The metadata for each block changed. */
+ public byte[] metadataArray;
+
+ /** The size of the arrays. */
+ public int size;
+ private static byte[] field_73449_e = new byte[0];
+
+ public Packet52MultiBlockChange() {
+ this.isChunkDataPacket = true;
+ }
+
+ public Packet52MultiBlockChange(int par1, int par2, short[] par3ArrayOfShort, int par4, World par5World) {
+ this.isChunkDataPacket = true;
+ this.xPosition = par1;
+ this.zPosition = par2;
+ this.size = par4;
+ int var6 = 4 * par4;
+ Chunk var7 = par5World.getChunkFromChunkCoords(par1, par2);
+
+ try {
+ if (par4 >= 64) {
+ this.field_98193_m.func_98233_a("ChunkTilesUpdatePacket compress " + par4);
+
+ if (field_73449_e.length < var6) {
+ field_73449_e = new byte[var6];
+ }
+ } else {
+ ByteArrayOutputStream var8 = new ByteArrayOutputStream(var6);
+ DataOutputStream var9 = new DataOutputStream(var8);
+
+ for (int var10 = 0; var10 < par4; ++var10) {
+ int var11 = par3ArrayOfShort[var10] >> 12 & 15;
+ int var12 = par3ArrayOfShort[var10] >> 8 & 15;
+ int var13 = par3ArrayOfShort[var10] & 255;
+ var9.writeShort(par3ArrayOfShort[var10]);
+ var9.writeShort((short) ((var7.getBlockID(var11, var13, var12) & 4095) << 4
+ | var7.getBlockMetadata(var11, var13, var12) & 15));
+ }
+
+ this.metadataArray = var8.toByteArray();
+
+ if (this.metadataArray.length != var6) {
+ throw new RuntimeException(
+ "Expected length " + var6 + " doesn\'t match received length " + this.metadataArray.length);
+ }
+ }
+ } catch (IOException var14) {
+ this.field_98193_m.logSevereException("Couldn\'t create chunk packet", var14);
+ this.metadataArray = null;
+ }
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.xPosition = par1DataInputStream.readInt();
+ this.zPosition = par1DataInputStream.readInt();
+ this.size = par1DataInputStream.readShort() & 65535;
+ int var2 = par1DataInputStream.readInt();
+
+ if (var2 > 0) {
+ this.metadataArray = new byte[var2];
+ par1DataInputStream.readFully(this.metadataArray);
+ }
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeInt(this.xPosition);
+ par1DataOutputStream.writeInt(this.zPosition);
+ par1DataOutputStream.writeShort((short) this.size);
+
+ if (this.metadataArray != null) {
+ par1DataOutputStream.writeInt(this.metadataArray.length);
+ par1DataOutputStream.write(this.metadataArray);
+ } else {
+ par1DataOutputStream.writeInt(0);
+ }
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleMultiBlockChange(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 10 + this.size * 4;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet53BlockChange.java b/sp-server/src/main/java/net/minecraft/src/Packet53BlockChange.java
new file mode 100644
index 0000000..cbc4a83
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet53BlockChange.java
@@ -0,0 +1,71 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet53BlockChange extends Packet {
+ /** Block X position. */
+ public int xPosition;
+
+ /** Block Y position. */
+ public int yPosition;
+
+ /** Block Z position. */
+ public int zPosition;
+
+ /** The new block type for the block. */
+ public int type;
+
+ /** Metadata of the block. */
+ public int metadata;
+
+ public Packet53BlockChange() {
+ this.isChunkDataPacket = true;
+ }
+
+ public Packet53BlockChange(int par1, int par2, int par3, World par4World) {
+ this.isChunkDataPacket = true;
+ this.xPosition = par1;
+ this.yPosition = par2;
+ this.zPosition = par3;
+ this.type = par4World.getBlockId(par1, par2, par3);
+ this.metadata = par4World.getBlockMetadata(par1, par2, par3);
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.xPosition = par1DataInputStream.readInt();
+ this.yPosition = par1DataInputStream.read();
+ this.zPosition = par1DataInputStream.readInt();
+ this.type = par1DataInputStream.readShort();
+ this.metadata = par1DataInputStream.read();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeInt(this.xPosition);
+ par1DataOutputStream.write(this.yPosition);
+ par1DataOutputStream.writeInt(this.zPosition);
+ par1DataOutputStream.writeShort(this.type);
+ par1DataOutputStream.write(this.metadata);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleBlockChange(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 11;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet54PlayNoteBlock.java b/sp-server/src/main/java/net/minecraft/src/Packet54PlayNoteBlock.java
new file mode 100644
index 0000000..7a9a9b7
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet54PlayNoteBlock.java
@@ -0,0 +1,73 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet54PlayNoteBlock extends Packet {
+ public int xLocation;
+ public int yLocation;
+ public int zLocation;
+
+ /** 1=Double Bass, 2=Snare Drum, 3=Clicks / Sticks, 4=Bass Drum, 5=Harp */
+ public int instrumentType;
+
+ /**
+ * The pitch of the note (between 0-24 inclusive where 0 is the lowest and 24 is
+ * the highest).
+ */
+ public int pitch;
+
+ /** The block ID this action is set for. */
+ public int blockId;
+
+ public Packet54PlayNoteBlock() {
+ }
+
+ public Packet54PlayNoteBlock(int par1, int par2, int par3, int par4, int par5, int par6) {
+ this.xLocation = par1;
+ this.yLocation = par2;
+ this.zLocation = par3;
+ this.instrumentType = par5;
+ this.pitch = par6;
+ this.blockId = par4;
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.xLocation = par1DataInputStream.readInt();
+ this.yLocation = par1DataInputStream.readShort();
+ this.zLocation = par1DataInputStream.readInt();
+ this.instrumentType = par1DataInputStream.read();
+ this.pitch = par1DataInputStream.read();
+ this.blockId = par1DataInputStream.readShort() & 4095;
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeInt(this.xLocation);
+ par1DataOutputStream.writeShort(this.yLocation);
+ par1DataOutputStream.writeInt(this.zLocation);
+ par1DataOutputStream.write(this.instrumentType);
+ par1DataOutputStream.write(this.pitch);
+ par1DataOutputStream.writeShort(this.blockId & 4095);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleBlockEvent(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 14;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet55BlockDestroy.java b/sp-server/src/main/java/net/minecraft/src/Packet55BlockDestroy.java
new file mode 100644
index 0000000..3b83755
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet55BlockDestroy.java
@@ -0,0 +1,85 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet55BlockDestroy extends Packet {
+ /** Entity breaking the block */
+ private int entityId;
+
+ /** X posiiton of the block */
+ private int posX;
+
+ /** Y position of the block */
+ private int posY;
+
+ /** Z position of the block */
+ private int posZ;
+
+ /** How far destroyed this block is */
+ private int destroyedStage;
+
+ public Packet55BlockDestroy() {
+ }
+
+ public Packet55BlockDestroy(int par1, int par2, int par3, int par4, int par5) {
+ this.entityId = par1;
+ this.posX = par2;
+ this.posY = par3;
+ this.posZ = par4;
+ this.destroyedStage = par5;
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.entityId = par1DataInputStream.readInt();
+ this.posX = par1DataInputStream.readInt();
+ this.posY = par1DataInputStream.readInt();
+ this.posZ = par1DataInputStream.readInt();
+ this.destroyedStage = par1DataInputStream.read();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeInt(this.entityId);
+ par1DataOutputStream.writeInt(this.posX);
+ par1DataOutputStream.writeInt(this.posY);
+ par1DataOutputStream.writeInt(this.posZ);
+ par1DataOutputStream.write(this.destroyedStage);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleBlockDestroy(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 13;
+ }
+
+ /**
+ * only false for the abstract Packet class, all real packets return true
+ */
+ public boolean isRealPacket() {
+ return true;
+ }
+
+ /**
+ * eg return packet30entity.entityId == entityId; WARNING : will throw if you
+ * compare a packet to a different packet class
+ */
+ public boolean containsSameEntityIDAs(Packet par1Packet) {
+ Packet55BlockDestroy var2 = (Packet55BlockDestroy) par1Packet;
+ return var2.entityId == this.entityId;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet56MapChunks.java b/sp-server/src/main/java/net/minecraft/src/Packet56MapChunks.java
new file mode 100644
index 0000000..c64a75f
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet56MapChunks.java
@@ -0,0 +1,107 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.List;
+
+public class Packet56MapChunks extends Packet {
+ private int[] chunkPostX;
+ private int[] chunkPosZ;
+ public int[] field_73590_a;
+ public int[] field_73588_b;
+
+ /** The compressed chunk data buffer */
+ private byte[] chunkDataBuffer;
+ private byte[][] field_73584_f;
+
+ /** total size of the compressed data */
+ private int dataLength;
+
+ /**
+ * Whether or not the chunk data contains a light nibble array. This is true in
+ * the main world, false in the end + nether.
+ */
+ private boolean skyLightSent;
+ private static byte[] chunkDataNotCompressed = new byte[0];
+
+ public Packet56MapChunks() {
+ }
+
+ public Packet56MapChunks(List par1List) {
+ int var2 = par1List.size();
+ this.chunkPostX = new int[var2];
+ this.chunkPosZ = new int[var2];
+ this.field_73590_a = new int[var2];
+ this.field_73588_b = new int[var2];
+ this.field_73584_f = new byte[var2][];
+ this.skyLightSent = !par1List.isEmpty() && !((Chunk) par1List.get(0)).worldObj.provider.hasNoSky;
+ int var3 = 0;
+
+ for (int var4 = 0; var4 < var2; ++var4) {
+ Chunk var5 = (Chunk) par1List.get(var4);
+ Packet51MapChunkData var6 = Packet51MapChunk.getMapChunkData(var5, true, 65535);
+
+ if (chunkDataNotCompressed.length < var3 + var6.compressedData.length) {
+ byte[] var7 = new byte[var3 + var6.compressedData.length];
+ System.arraycopy(chunkDataNotCompressed, 0, var7, 0, chunkDataNotCompressed.length);
+ chunkDataNotCompressed = var7;
+ }
+
+ System.arraycopy(var6.compressedData, 0, chunkDataNotCompressed, var3, var6.compressedData.length);
+ var3 += var6.compressedData.length;
+ this.chunkPostX[var4] = var5.xPosition;
+ this.chunkPosZ[var4] = var5.zPosition;
+ this.field_73590_a[var4] = var6.chunkExistFlag;
+ this.field_73588_b[var4] = var6.chunkHasAddSectionFlag;
+ this.field_73584_f[var4] = var6.compressedData;
+ }
+
+ this.chunkDataBuffer = new byte[var3];
+ System.arraycopy(chunkDataNotCompressed, 0, this.chunkDataBuffer, 0, var3);
+ this.dataLength = this.chunkDataBuffer.length;
+
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ // not used in server
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeShort(this.chunkPostX.length);
+ par1DataOutputStream.writeInt(this.dataLength | 0x10000000);
+ par1DataOutputStream.writeBoolean(this.skyLightSent);
+ par1DataOutputStream.write(this.chunkDataBuffer, 0, this.dataLength);
+
+ for (int var2 = 0; var2 < this.chunkPostX.length; ++var2) {
+ par1DataOutputStream.writeInt(this.chunkPostX[var2]);
+ par1DataOutputStream.writeInt(this.chunkPosZ[var2]);
+ par1DataOutputStream.writeShort((short) (this.field_73590_a[var2] & 65535));
+ par1DataOutputStream.writeShort((short) (this.field_73588_b[var2] & 65535));
+ }
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleMapChunks(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 6 + this.dataLength + 12 * this.getNumberOfChunkInPacket();
+ }
+
+ public int getNumberOfChunkInPacket() {
+ return this.chunkPostX.length;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet5PlayerInventory.java b/sp-server/src/main/java/net/minecraft/src/Packet5PlayerInventory.java
new file mode 100644
index 0000000..319325e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet5PlayerInventory.java
@@ -0,0 +1,73 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet5PlayerInventory extends Packet {
+ /** Entity ID of the object. */
+ public int entityID;
+
+ /** Equipment slot: 0=held, 1-4=armor slot */
+ public int slot;
+
+ /** The item in the slot format (an ItemStack) */
+ private ItemStack itemSlot;
+
+ public Packet5PlayerInventory() {
+ }
+
+ public Packet5PlayerInventory(int par1, int par2, ItemStack par3ItemStack) {
+ this.entityID = par1;
+ this.slot = par2;
+ this.itemSlot = par3ItemStack == null ? null : par3ItemStack.copy();
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.entityID = par1DataInputStream.readInt();
+ this.slot = par1DataInputStream.readShort();
+ this.itemSlot = readItemStack(par1DataInputStream);
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeInt(this.entityID);
+ par1DataOutputStream.writeShort(this.slot);
+ writeItemStack(this.itemSlot, par1DataOutputStream);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handlePlayerInventory(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 8;
+ }
+
+ /**
+ * only false for the abstract Packet class, all real packets return true
+ */
+ public boolean isRealPacket() {
+ return true;
+ }
+
+ /**
+ * eg return packet30entity.entityId == entityId; WARNING : will throw if you
+ * compare a packet to a different packet class
+ */
+ public boolean containsSameEntityIDAs(Packet par1Packet) {
+ Packet5PlayerInventory var2 = (Packet5PlayerInventory) par1Packet;
+ return var2.entityID == this.entityID && var2.slot == this.slot;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet60Explosion.java b/sp-server/src/main/java/net/minecraft/src/Packet60Explosion.java
new file mode 100644
index 0000000..95deeeb
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet60Explosion.java
@@ -0,0 +1,111 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+public class Packet60Explosion extends Packet {
+ public double explosionX;
+ public double explosionY;
+ public double explosionZ;
+ public float explosionSize;
+ public List chunkPositionRecords;
+
+ /** X velocity of the player being pushed by the explosion */
+ private float playerVelocityX;
+
+ /** Y velocity of the player being pushed by the explosion */
+ private float playerVelocityY;
+
+ /** Z velocity of the player being pushed by the explosion */
+ private float playerVelocityZ;
+
+ public Packet60Explosion() {
+ }
+
+ public Packet60Explosion(double par1, double par3, double par5, float par7, List par8List, Vec3 par9Vec3) {
+ this.explosionX = par1;
+ this.explosionY = par3;
+ this.explosionZ = par5;
+ this.explosionSize = par7;
+ this.chunkPositionRecords = new ArrayList(par8List);
+
+ if (par9Vec3 != null) {
+ this.playerVelocityX = (float) par9Vec3.xCoord;
+ this.playerVelocityY = (float) par9Vec3.yCoord;
+ this.playerVelocityZ = (float) par9Vec3.zCoord;
+ }
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.explosionX = par1DataInputStream.readDouble();
+ this.explosionY = par1DataInputStream.readDouble();
+ this.explosionZ = par1DataInputStream.readDouble();
+ this.explosionSize = par1DataInputStream.readFloat();
+ int var2 = par1DataInputStream.readInt();
+ this.chunkPositionRecords = new ArrayList(var2);
+ int var3 = (int) this.explosionX;
+ int var4 = (int) this.explosionY;
+ int var5 = (int) this.explosionZ;
+
+ for (int var6 = 0; var6 < var2; ++var6) {
+ int var7 = par1DataInputStream.readByte() + var3;
+ int var8 = par1DataInputStream.readByte() + var4;
+ int var9 = par1DataInputStream.readByte() + var5;
+ this.chunkPositionRecords.add(new ChunkPosition(var7, var8, var9));
+ }
+
+ this.playerVelocityX = par1DataInputStream.readFloat();
+ this.playerVelocityY = par1DataInputStream.readFloat();
+ this.playerVelocityZ = par1DataInputStream.readFloat();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeDouble(this.explosionX);
+ par1DataOutputStream.writeDouble(this.explosionY);
+ par1DataOutputStream.writeDouble(this.explosionZ);
+ par1DataOutputStream.writeFloat(this.explosionSize);
+ par1DataOutputStream.writeInt(this.chunkPositionRecords.size());
+ int var2 = (int) this.explosionX;
+ int var3 = (int) this.explosionY;
+ int var4 = (int) this.explosionZ;
+ Iterator var5 = this.chunkPositionRecords.iterator();
+
+ while (var5.hasNext()) {
+ ChunkPosition var6 = (ChunkPosition) var5.next();
+ int var7 = var6.x - var2;
+ int var8 = var6.y - var3;
+ int var9 = var6.z - var4;
+ par1DataOutputStream.writeByte(var7);
+ par1DataOutputStream.writeByte(var8);
+ par1DataOutputStream.writeByte(var9);
+ }
+
+ par1DataOutputStream.writeFloat(this.playerVelocityX);
+ par1DataOutputStream.writeFloat(this.playerVelocityY);
+ par1DataOutputStream.writeFloat(this.playerVelocityZ);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleExplosion(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 32 + this.chunkPositionRecords.size() * 3 + 3;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet61DoorChange.java b/sp-server/src/main/java/net/minecraft/src/Packet61DoorChange.java
new file mode 100644
index 0000000..3472c38
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet61DoorChange.java
@@ -0,0 +1,64 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet61DoorChange extends Packet {
+ public int sfxID;
+ public int auxData;
+ public int posX;
+ public int posY;
+ public int posZ;
+ private boolean disableRelativeVolume;
+
+ public Packet61DoorChange() {
+ }
+
+ public Packet61DoorChange(int par1, int par2, int par3, int par4, int par5, boolean par6) {
+ this.sfxID = par1;
+ this.posX = par2;
+ this.posY = par3;
+ this.posZ = par4;
+ this.auxData = par5;
+ this.disableRelativeVolume = par6;
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.sfxID = par1DataInputStream.readInt();
+ this.posX = par1DataInputStream.readInt();
+ this.posY = par1DataInputStream.readByte() & 255;
+ this.posZ = par1DataInputStream.readInt();
+ this.auxData = par1DataInputStream.readInt();
+ this.disableRelativeVolume = par1DataInputStream.readBoolean();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeInt(this.sfxID);
+ par1DataOutputStream.writeInt(this.posX);
+ par1DataOutputStream.writeByte(this.posY & 255);
+ par1DataOutputStream.writeInt(this.posZ);
+ par1DataOutputStream.writeInt(this.auxData);
+ par1DataOutputStream.writeBoolean(this.disableRelativeVolume);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleDoorChange(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 21;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet62LevelSound.java b/sp-server/src/main/java/net/minecraft/src/Packet62LevelSound.java
new file mode 100644
index 0000000..8b4a7ea
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet62LevelSound.java
@@ -0,0 +1,83 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet62LevelSound extends Packet {
+ /** e.g. step.grass */
+ private String soundName;
+
+ /** Effect X multiplied by 8 */
+ private int effectX;
+
+ /** Effect Y multiplied by 8 */
+ private int effectY = Integer.MAX_VALUE;
+
+ /** Effect Z multiplied by 8 */
+ private int effectZ;
+
+ /** 1 is 100%. Can be more. */
+ private float volume;
+
+ /** 63 is 100%. Can be more. */
+ private int pitch;
+
+ public Packet62LevelSound() {
+ }
+
+ public Packet62LevelSound(String par1Str, double par2, double par4, double par6, float par8, float par9) {
+ this.soundName = par1Str;
+ this.effectX = (int) (par2 * 8.0D);
+ this.effectY = (int) (par4 * 8.0D);
+ this.effectZ = (int) (par6 * 8.0D);
+ this.volume = par8;
+ this.pitch = (int) (par9 * 63.0F);
+
+ if (this.pitch < 0) {
+ this.pitch = 0;
+ }
+
+ if (this.pitch > 255) {
+ this.pitch = 255;
+ }
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.soundName = readString(par1DataInputStream, 32);
+ this.effectX = par1DataInputStream.readInt();
+ this.effectY = par1DataInputStream.readInt();
+ this.effectZ = par1DataInputStream.readInt();
+ this.volume = par1DataInputStream.readFloat();
+ this.pitch = par1DataInputStream.readUnsignedByte();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ writeString(this.soundName, par1DataOutputStream);
+ par1DataOutputStream.writeInt(this.effectX);
+ par1DataOutputStream.writeInt(this.effectY);
+ par1DataOutputStream.writeInt(this.effectZ);
+ par1DataOutputStream.writeFloat(this.volume);
+ par1DataOutputStream.writeByte(this.pitch);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleLevelSound(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 24;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet63WorldParticles.java b/sp-server/src/main/java/net/minecraft/src/Packet63WorldParticles.java
new file mode 100644
index 0000000..e493bcf
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet63WorldParticles.java
@@ -0,0 +1,90 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet63WorldParticles extends Packet {
+ /**
+ * The name of the particle to create. A list can be found at
+ * https://gist.github.com/thinkofdeath/5110835
+ */
+ private String particleName;
+
+ /** X position of the particle. */
+ private float posX;
+
+ /** Y position of the particle. */
+ private float posY;
+
+ /** Z position of the particle. */
+ private float posZ;
+
+ /**
+ * This is added to the X position after being multiplied by
+ * random.nextGaussian()
+ */
+ private float offsetX;
+
+ /**
+ * This is added to the Y position after being multiplied by
+ * random.nextGaussian()
+ */
+ private float offsetY;
+
+ /**
+ * This is added to the Z position after being multiplied by
+ * random.nextGaussian()
+ */
+ private float offsetZ;
+
+ /** The speed of each particle. */
+ private float speed;
+
+ /** The number of particles to create. */
+ private int quantity;
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.particleName = readString(par1DataInputStream, 64);
+ this.posX = par1DataInputStream.readFloat();
+ this.posY = par1DataInputStream.readFloat();
+ this.posZ = par1DataInputStream.readFloat();
+ this.offsetX = par1DataInputStream.readFloat();
+ this.offsetY = par1DataInputStream.readFloat();
+ this.offsetZ = par1DataInputStream.readFloat();
+ this.speed = par1DataInputStream.readFloat();
+ this.quantity = par1DataInputStream.readInt();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ writeString(this.particleName, par1DataOutputStream);
+ par1DataOutputStream.writeFloat(this.posX);
+ par1DataOutputStream.writeFloat(this.posY);
+ par1DataOutputStream.writeFloat(this.posZ);
+ par1DataOutputStream.writeFloat(this.offsetX);
+ par1DataOutputStream.writeFloat(this.offsetY);
+ par1DataOutputStream.writeFloat(this.offsetZ);
+ par1DataOutputStream.writeFloat(this.speed);
+ par1DataOutputStream.writeInt(this.quantity);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleWorldParticles(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 64;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet6SpawnPosition.java b/sp-server/src/main/java/net/minecraft/src/Packet6SpawnPosition.java
new file mode 100644
index 0000000..896fa06
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet6SpawnPosition.java
@@ -0,0 +1,80 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet6SpawnPosition extends Packet {
+ /** X coordinate of spawn. */
+ public int xPosition;
+
+ /** Y coordinate of spawn. */
+ public int yPosition;
+
+ /** Z coordinate of spawn. */
+ public int zPosition;
+
+ public Packet6SpawnPosition() {
+ }
+
+ public Packet6SpawnPosition(int par1, int par2, int par3) {
+ this.xPosition = par1;
+ this.yPosition = par2;
+ this.zPosition = par3;
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.xPosition = par1DataInputStream.readInt();
+ this.yPosition = par1DataInputStream.readInt();
+ this.zPosition = par1DataInputStream.readInt();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeInt(this.xPosition);
+ par1DataOutputStream.writeInt(this.yPosition);
+ par1DataOutputStream.writeInt(this.zPosition);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleSpawnPosition(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 12;
+ }
+
+ /**
+ * only false for the abstract Packet class, all real packets return true
+ */
+ public boolean isRealPacket() {
+ return true;
+ }
+
+ /**
+ * eg return packet30entity.entityId == entityId; WARNING : will throw if you
+ * compare a packet to a different packet class
+ */
+ public boolean containsSameEntityIDAs(Packet par1Packet) {
+ return true;
+ }
+
+ /**
+ * If this returns true, the packet may be processed on any thread; otherwise it
+ * is queued for the main thread to handle.
+ */
+ public boolean canProcessAsync() {
+ return false;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet70GameEvent.java b/sp-server/src/main/java/net/minecraft/src/Packet70GameEvent.java
new file mode 100644
index 0000000..2d4fa5a
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet70GameEvent.java
@@ -0,0 +1,59 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet70GameEvent extends Packet {
+ /**
+ * The client prints clientMessage[eventType] to chat when this packet is
+ * received.
+ */
+ public static final String[] clientMessage = new String[] { "tile.bed.notValid", null, null, "gameMode.changed" };
+
+ /** 0: Invalid bed, 1: Rain starts, 2: Rain stops, 3: Game mode changed. */
+ public int eventType;
+
+ /**
+ * When reason==3, the game mode to set. See EnumGameType for a list of values.
+ */
+ public int gameMode;
+
+ public Packet70GameEvent() {
+ }
+
+ public Packet70GameEvent(int par1, int par2) {
+ this.eventType = par1;
+ this.gameMode = par2;
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.eventType = par1DataInputStream.readByte();
+ this.gameMode = par1DataInputStream.readByte();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeByte(this.eventType);
+ par1DataOutputStream.writeByte(this.gameMode);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleGameEvent(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 2;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet71Weather.java b/sp-server/src/main/java/net/minecraft/src/Packet71Weather.java
new file mode 100644
index 0000000..225b859
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet71Weather.java
@@ -0,0 +1,63 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet71Weather extends Packet {
+ public int entityID;
+ public int posX;
+ public int posY;
+ public int posZ;
+ public int isLightningBolt;
+
+ public Packet71Weather() {
+ }
+
+ public Packet71Weather(Entity par1Entity) {
+ this.entityID = par1Entity.entityId;
+ this.posX = MathHelper.floor_double(par1Entity.posX * 32.0D);
+ this.posY = MathHelper.floor_double(par1Entity.posY * 32.0D);
+ this.posZ = MathHelper.floor_double(par1Entity.posZ * 32.0D);
+
+ if (par1Entity instanceof EntityLightningBolt) {
+ this.isLightningBolt = 1;
+ }
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.entityID = par1DataInputStream.readInt();
+ this.isLightningBolt = par1DataInputStream.readByte();
+ this.posX = par1DataInputStream.readInt();
+ this.posY = par1DataInputStream.readInt();
+ this.posZ = par1DataInputStream.readInt();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeInt(this.entityID);
+ par1DataOutputStream.writeByte(this.isLightningBolt);
+ par1DataOutputStream.writeInt(this.posX);
+ par1DataOutputStream.writeInt(this.posY);
+ par1DataOutputStream.writeInt(this.posZ);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleWeather(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 17;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet7UseEntity.java b/sp-server/src/main/java/net/minecraft/src/Packet7UseEntity.java
new file mode 100644
index 0000000..dd943db
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet7UseEntity.java
@@ -0,0 +1,51 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet7UseEntity extends Packet {
+ /** The entity of the player (ignored by the server) */
+ public int playerEntityId;
+
+ /** The entity the player is interacting with */
+ public int targetEntity;
+
+ /**
+ * Seems to be true when the player is pointing at an entity and left-clicking
+ * and false when right-clicking.
+ */
+ public int isLeftClick;
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.playerEntityId = par1DataInputStream.readInt();
+ this.targetEntity = par1DataInputStream.readInt();
+ this.isLeftClick = par1DataInputStream.readByte();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeInt(this.playerEntityId);
+ par1DataOutputStream.writeInt(this.targetEntity);
+ par1DataOutputStream.writeByte(this.isLeftClick);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleUseEntity(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 9;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet8UpdateHealth.java b/sp-server/src/main/java/net/minecraft/src/Packet8UpdateHealth.java
new file mode 100644
index 0000000..8e91d67
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet8UpdateHealth.java
@@ -0,0 +1,73 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet8UpdateHealth extends Packet {
+ /** Variable used for incoming health packets */
+ public int healthMP;
+ public int food;
+
+ /**
+ * Players logging on get a saturation of 5.0. Eating food increases the
+ * saturation as well as the food bar.
+ */
+ public float foodSaturation;
+
+ public Packet8UpdateHealth() {
+ }
+
+ public Packet8UpdateHealth(int par1, int par2, float par3) {
+ this.healthMP = par1;
+ this.food = par2;
+ this.foodSaturation = par3;
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.healthMP = par1DataInputStream.readShort();
+ this.food = par1DataInputStream.readShort();
+ this.foodSaturation = par1DataInputStream.readFloat();
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeShort(this.healthMP);
+ par1DataOutputStream.writeShort(this.food);
+ par1DataOutputStream.writeFloat(this.foodSaturation);
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleUpdateHealth(this);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 8;
+ }
+
+ /**
+ * only false for the abstract Packet class, all real packets return true
+ */
+ public boolean isRealPacket() {
+ return true;
+ }
+
+ /**
+ * eg return packet30entity.entityId == entityId; WARNING : will throw if you
+ * compare a packet to a different packet class
+ */
+ public boolean containsSameEntityIDAs(Packet par1Packet) {
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Packet9Respawn.java b/sp-server/src/main/java/net/minecraft/src/Packet9Respawn.java
new file mode 100644
index 0000000..5eb12f4
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Packet9Respawn.java
@@ -0,0 +1,72 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Packet9Respawn extends Packet {
+ public int respawnDimension;
+
+ /**
+ * The difficulty setting. 0 through 3 for peaceful, easy, normal, hard. The
+ * client always sends 1.
+ */
+ public int difficulty;
+
+ /** Defaults to 128 */
+ public int worldHeight;
+ public EnumGameType gameType;
+ public WorldType terrainType;
+
+ public Packet9Respawn() {
+ }
+
+ public Packet9Respawn(int par1, byte par2, WorldType par3WorldType, int par4, EnumGameType par5EnumGameType) {
+ this.respawnDimension = par1;
+ this.difficulty = par2;
+ this.worldHeight = par4;
+ this.gameType = par5EnumGameType;
+ this.terrainType = par3WorldType;
+ }
+
+ /**
+ * Passes this Packet on to the NetHandler for processing.
+ */
+ public void processPacket(NetHandler par1NetHandler) {
+ par1NetHandler.handleRespawn(this);
+ }
+
+ /**
+ * Abstract. Reads the raw packet data from the data stream.
+ */
+ public void readPacketData(DataInputStream par1DataInputStream) throws IOException {
+ this.respawnDimension = par1DataInputStream.readInt();
+ this.difficulty = par1DataInputStream.readByte();
+ this.gameType = EnumGameType.getByID(par1DataInputStream.readByte());
+ this.worldHeight = par1DataInputStream.readShort();
+ String var2 = readString(par1DataInputStream, 16);
+ this.terrainType = WorldType.parseWorldType(var2);
+
+ if (this.terrainType == null) {
+ this.terrainType = WorldType.DEFAULT;
+ }
+ }
+
+ /**
+ * Abstract. Writes the raw packet data to the data stream.
+ */
+ public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException {
+ par1DataOutputStream.writeInt(this.respawnDimension);
+ par1DataOutputStream.writeByte(this.difficulty);
+ par1DataOutputStream.writeByte(this.gameType.getID());
+ par1DataOutputStream.writeShort(this.worldHeight);
+ writeString(this.terrainType.getWorldTypeName(), par1DataOutputStream);
+ }
+
+ /**
+ * Abstract. Return the size of the packet (not counting the header).
+ */
+ public int getPacketSize() {
+ return 8 + (this.terrainType == null ? 0 : this.terrainType.getWorldTypeName().length());
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/PacketCount.java b/sp-server/src/main/java/net/minecraft/src/PacketCount.java
new file mode 100644
index 0000000..39bf67e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/PacketCount.java
@@ -0,0 +1,36 @@
+package net.minecraft.src;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class PacketCount {
+ /** If false, countPacket does nothing */
+ public static boolean allowCounting = true;
+
+ /** A count of the total number of each packet sent grouped by IDs. */
+ private static final Map packetCountForID = new HashMap();
+
+ /** A count of the total size of each packet sent grouped by IDs. */
+ private static final Map sizeCountForID = new HashMap();
+
+ /** Used to make threads queue to add packets */
+ private static final Object lock = new Object();
+
+ public static void countPacket(int par0, long par1) {
+ if (allowCounting) {
+ Object var3 = lock;
+
+ synchronized (lock) {
+ if (packetCountForID.containsKey(Integer.valueOf(par0))) {
+ packetCountForID.put(Integer.valueOf(par0),
+ Long.valueOf(((Long) packetCountForID.get(Integer.valueOf(par0))).longValue() + 1L));
+ sizeCountForID.put(Integer.valueOf(par0),
+ Long.valueOf(((Long) sizeCountForID.get(Integer.valueOf(par0))).longValue() + par1));
+ } else {
+ packetCountForID.put(Integer.valueOf(par0), Long.valueOf(1L));
+ sizeCountForID.put(Integer.valueOf(par0), Long.valueOf(par1));
+ }
+ }
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Path.java b/sp-server/src/main/java/net/minecraft/src/Path.java
new file mode 100644
index 0000000..218178c
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Path.java
@@ -0,0 +1,147 @@
+package net.minecraft.src;
+
+public class Path {
+ /** Contains the points in this path */
+ private PathPoint[] pathPoints = new PathPoint[1024];
+
+ /** The number of points in this path */
+ private int count = 0;
+
+ /**
+ * Adds a point to the path
+ */
+ public PathPoint addPoint(PathPoint par1PathPoint) {
+ if (par1PathPoint.index >= 0) {
+ throw new IllegalStateException("OW KNOWS!");
+ } else {
+ if (this.count == this.pathPoints.length) {
+ PathPoint[] var2 = new PathPoint[this.count << 1];
+ System.arraycopy(this.pathPoints, 0, var2, 0, this.count);
+ this.pathPoints = var2;
+ }
+
+ this.pathPoints[this.count] = par1PathPoint;
+ par1PathPoint.index = this.count;
+ this.sortBack(this.count++);
+ return par1PathPoint;
+ }
+ }
+
+ /**
+ * Clears the path
+ */
+ public void clearPath() {
+ this.count = 0;
+ }
+
+ /**
+ * Returns and removes the first point in the path
+ */
+ public PathPoint dequeue() {
+ PathPoint var1 = this.pathPoints[0];
+ this.pathPoints[0] = this.pathPoints[--this.count];
+ this.pathPoints[this.count] = null;
+
+ if (this.count > 0) {
+ this.sortForward(0);
+ }
+
+ var1.index = -1;
+ return var1;
+ }
+
+ /**
+ * Changes the provided point's distance to target
+ */
+ public void changeDistance(PathPoint par1PathPoint, float par2) {
+ float var3 = par1PathPoint.distanceToTarget;
+ par1PathPoint.distanceToTarget = par2;
+
+ if (par2 < var3) {
+ this.sortBack(par1PathPoint.index);
+ } else {
+ this.sortForward(par1PathPoint.index);
+ }
+ }
+
+ /**
+ * Sorts a point to the left
+ */
+ private void sortBack(int par1) {
+ PathPoint var2 = this.pathPoints[par1];
+ int var4;
+
+ for (float var3 = var2.distanceToTarget; par1 > 0; par1 = var4) {
+ var4 = par1 - 1 >> 1;
+ PathPoint var5 = this.pathPoints[var4];
+
+ if (var3 >= var5.distanceToTarget) {
+ break;
+ }
+
+ this.pathPoints[par1] = var5;
+ var5.index = par1;
+ }
+
+ this.pathPoints[par1] = var2;
+ var2.index = par1;
+ }
+
+ /**
+ * Sorts a point to the right
+ */
+ private void sortForward(int par1) {
+ PathPoint var2 = this.pathPoints[par1];
+ float var3 = var2.distanceToTarget;
+
+ while (true) {
+ int var4 = 1 + (par1 << 1);
+ int var5 = var4 + 1;
+
+ if (var4 >= this.count) {
+ break;
+ }
+
+ PathPoint var6 = this.pathPoints[var4];
+ float var7 = var6.distanceToTarget;
+ PathPoint var8;
+ float var9;
+
+ if (var5 >= this.count) {
+ var8 = null;
+ var9 = Float.POSITIVE_INFINITY;
+ } else {
+ var8 = this.pathPoints[var5];
+ var9 = var8.distanceToTarget;
+ }
+
+ if (var7 < var9) {
+ if (var7 >= var3) {
+ break;
+ }
+
+ this.pathPoints[par1] = var6;
+ var6.index = par1;
+ par1 = var4;
+ } else {
+ if (var9 >= var3) {
+ break;
+ }
+
+ this.pathPoints[par1] = var8;
+ var8.index = par1;
+ par1 = var5;
+ }
+ }
+
+ this.pathPoints[par1] = var2;
+ var2.index = par1;
+ }
+
+ /**
+ * Returns true if this path contains no points
+ */
+ public boolean isPathEmpty() {
+ return this.count == 0;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/PathEntity.java b/sp-server/src/main/java/net/minecraft/src/PathEntity.java
new file mode 100644
index 0000000..db40ddc
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/PathEntity.java
@@ -0,0 +1,109 @@
+package net.minecraft.src;
+
+public class PathEntity {
+ /** The actual points in the path */
+ private final PathPoint[] points;
+
+ /** PathEntity Array Index the Entity is currently targeting */
+ private int currentPathIndex;
+
+ /** The total length of the path */
+ private int pathLength;
+
+ public PathEntity(PathPoint[] par1ArrayOfPathPoint) {
+ this.points = par1ArrayOfPathPoint;
+ this.pathLength = par1ArrayOfPathPoint.length;
+ }
+
+ /**
+ * Directs this path to the next point in its array
+ */
+ public void incrementPathIndex() {
+ ++this.currentPathIndex;
+ }
+
+ /**
+ * Returns true if this path has reached the end
+ */
+ public boolean isFinished() {
+ return this.currentPathIndex >= this.pathLength;
+ }
+
+ /**
+ * returns the last PathPoint of the Array
+ */
+ public PathPoint getFinalPathPoint() {
+ return this.pathLength > 0 ? this.points[this.pathLength - 1] : null;
+ }
+
+ /**
+ * return the PathPoint located at the specified PathIndex, usually the current
+ * one
+ */
+ public PathPoint getPathPointFromIndex(int par1) {
+ return this.points[par1];
+ }
+
+ public int getCurrentPathLength() {
+ return this.pathLength;
+ }
+
+ public void setCurrentPathLength(int par1) {
+ this.pathLength = par1;
+ }
+
+ public int getCurrentPathIndex() {
+ return this.currentPathIndex;
+ }
+
+ public void setCurrentPathIndex(int par1) {
+ this.currentPathIndex = par1;
+ }
+
+ /**
+ * Gets the vector of the PathPoint associated with the given index.
+ */
+ public Vec3 getVectorFromIndex(Entity par1Entity, int par2) {
+ double var3 = (double) this.points[par2].xCoord + (double) ((int) (par1Entity.width + 1.0F)) * 0.5D;
+ double var5 = (double) this.points[par2].yCoord;
+ double var7 = (double) this.points[par2].zCoord + (double) ((int) (par1Entity.width + 1.0F)) * 0.5D;
+ return par1Entity.worldObj.getWorldVec3Pool().getVecFromPool(var3, var5, var7);
+ }
+
+ /**
+ * returns the current PathEntity target node as Vec3D
+ */
+ public Vec3 getPosition(Entity par1Entity) {
+ return this.getVectorFromIndex(par1Entity, this.currentPathIndex);
+ }
+
+ /**
+ * Returns true if the EntityPath are the same. Non instance related equals.
+ */
+ public boolean isSamePath(PathEntity par1PathEntity) {
+ if (par1PathEntity == null) {
+ return false;
+ } else if (par1PathEntity.points.length != this.points.length) {
+ return false;
+ } else {
+ for (int var2 = 0; var2 < this.points.length; ++var2) {
+ if (this.points[var2].xCoord != par1PathEntity.points[var2].xCoord
+ || this.points[var2].yCoord != par1PathEntity.points[var2].yCoord
+ || this.points[var2].zCoord != par1PathEntity.points[var2].zCoord) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ }
+
+ /**
+ * Returns true if the final PathPoint in the PathEntity is equal to Vec3D
+ * coords.
+ */
+ public boolean isDestinationSame(Vec3 par1Vec3) {
+ PathPoint var2 = this.getFinalPathPoint();
+ return var2 == null ? false : var2.xCoord == (int) par1Vec3.xCoord && var2.zCoord == (int) par1Vec3.zCoord;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/PathFinder.java b/sp-server/src/main/java/net/minecraft/src/PathFinder.java
new file mode 100644
index 0000000..ad9e134
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/PathFinder.java
@@ -0,0 +1,349 @@
+package net.minecraft.src;
+
+public class PathFinder {
+ /** Used to find obstacles */
+ private IBlockAccess worldMap;
+
+ /** The path being generated */
+ private Path path = new Path();
+
+ /** The points in the path */
+ private IntHashMap pointMap = new IntHashMap();
+
+ /** Selection of path points to add to the path */
+ private PathPoint[] pathOptions = new PathPoint[32];
+
+ /** should the PathFinder go through wodden door blocks */
+ private boolean isWoddenDoorAllowed;
+
+ /**
+ * should the PathFinder disregard BlockMovement type materials in its path
+ */
+ private boolean isMovementBlockAllowed;
+ private boolean isPathingInWater;
+
+ /** tells the FathFinder to not stop pathing underwater */
+ private boolean canEntityDrown;
+
+ public PathFinder(IBlockAccess par1IBlockAccess, boolean par2, boolean par3, boolean par4, boolean par5) {
+ this.worldMap = par1IBlockAccess;
+ this.isWoddenDoorAllowed = par2;
+ this.isMovementBlockAllowed = par3;
+ this.isPathingInWater = par4;
+ this.canEntityDrown = par5;
+ }
+
+ /**
+ * Creates a path from one entity to another within a minimum distance
+ */
+ public PathEntity createEntityPathTo(Entity par1Entity, Entity par2Entity, float par3) {
+ return this.createEntityPathTo(par1Entity, par2Entity.posX, par2Entity.boundingBox.minY, par2Entity.posZ, par3);
+ }
+
+ /**
+ * Creates a path from an entity to a specified location within a minimum
+ * distance
+ */
+ public PathEntity createEntityPathTo(Entity par1Entity, int par2, int par3, int par4, float par5) {
+ return this.createEntityPathTo(par1Entity, (double) ((float) par2 + 0.5F), (double) ((float) par3 + 0.5F),
+ (double) ((float) par4 + 0.5F), par5);
+ }
+
+ /**
+ * Internal implementation of creating a path from an entity to a point
+ */
+ private PathEntity createEntityPathTo(Entity par1Entity, double par2, double par4, double par6, float par8) {
+ this.path.clearPath();
+ this.pointMap.clearMap();
+ boolean var9 = this.isPathingInWater;
+ int var10 = MathHelper.floor_double(par1Entity.boundingBox.minY + 0.5D);
+
+ if (this.canEntityDrown && par1Entity.isInWater()) {
+ var10 = (int) par1Entity.boundingBox.minY;
+
+ for (int var11 = this.worldMap.getBlockId(MathHelper.floor_double(par1Entity.posX), var10,
+ MathHelper.floor_double(par1Entity.posZ)); var11 == Block.waterMoving.blockID
+ || var11 == Block.waterStill.blockID; var11 = this.worldMap.getBlockId(
+ MathHelper.floor_double(par1Entity.posX), var10,
+ MathHelper.floor_double(par1Entity.posZ))) {
+ ++var10;
+ }
+
+ var9 = this.isPathingInWater;
+ this.isPathingInWater = false;
+ } else {
+ var10 = MathHelper.floor_double(par1Entity.boundingBox.minY + 0.5D);
+ }
+
+ PathPoint var15 = this.openPoint(MathHelper.floor_double(par1Entity.boundingBox.minX), var10,
+ MathHelper.floor_double(par1Entity.boundingBox.minZ));
+ PathPoint var12 = this.openPoint(MathHelper.floor_double(par2 - (double) (par1Entity.width / 2.0F)),
+ MathHelper.floor_double(par4), MathHelper.floor_double(par6 - (double) (par1Entity.width / 2.0F)));
+ PathPoint var13 = new PathPoint(MathHelper.floor_float(par1Entity.width + 1.0F),
+ MathHelper.floor_float(par1Entity.height + 1.0F), MathHelper.floor_float(par1Entity.width + 1.0F));
+ PathEntity var14 = this.addToPath(par1Entity, var15, var12, var13, par8);
+ this.isPathingInWater = var9;
+ return var14;
+ }
+
+ /**
+ * Adds a path from start to end and returns the whole path (args: unused,
+ * start, end, unused, maxDistance)
+ */
+ private PathEntity addToPath(Entity par1Entity, PathPoint par2PathPoint, PathPoint par3PathPoint,
+ PathPoint par4PathPoint, float par5) {
+ par2PathPoint.totalPathDistance = 0.0F;
+ par2PathPoint.distanceToNext = par2PathPoint.func_75832_b(par3PathPoint);
+ par2PathPoint.distanceToTarget = par2PathPoint.distanceToNext;
+ this.path.clearPath();
+ this.path.addPoint(par2PathPoint);
+ PathPoint var6 = par2PathPoint;
+
+ while (!this.path.isPathEmpty()) {
+ PathPoint var7 = this.path.dequeue();
+
+ if (var7.equals(par3PathPoint)) {
+ return this.createEntityPath(par2PathPoint, par3PathPoint);
+ }
+
+ if (var7.func_75832_b(par3PathPoint) < var6.func_75832_b(par3PathPoint)) {
+ var6 = var7;
+ }
+
+ var7.isFirst = true;
+ int var8 = this.findPathOptions(par1Entity, var7, par4PathPoint, par3PathPoint, par5);
+
+ for (int var9 = 0; var9 < var8; ++var9) {
+ PathPoint var10 = this.pathOptions[var9];
+ float var11 = var7.totalPathDistance + var7.func_75832_b(var10);
+
+ if (!var10.isAssigned() || var11 < var10.totalPathDistance) {
+ var10.previous = var7;
+ var10.totalPathDistance = var11;
+ var10.distanceToNext = var10.func_75832_b(par3PathPoint);
+
+ if (var10.isAssigned()) {
+ this.path.changeDistance(var10, var10.totalPathDistance + var10.distanceToNext);
+ } else {
+ var10.distanceToTarget = var10.totalPathDistance + var10.distanceToNext;
+ this.path.addPoint(var10);
+ }
+ }
+ }
+ }
+
+ if (var6 == par2PathPoint) {
+ return null;
+ } else {
+ return this.createEntityPath(par2PathPoint, var6);
+ }
+ }
+
+ /**
+ * populates pathOptions with available points and returns the number of options
+ * found (args: unused1, currentPoint, unused2, targetPoint, maxDistance)
+ */
+ private int findPathOptions(Entity par1Entity, PathPoint par2PathPoint, PathPoint par3PathPoint,
+ PathPoint par4PathPoint, float par5) {
+ int var6 = 0;
+ byte var7 = 0;
+
+ if (this.getVerticalOffset(par1Entity, par2PathPoint.xCoord, par2PathPoint.yCoord + 1, par2PathPoint.zCoord,
+ par3PathPoint) == 1) {
+ var7 = 1;
+ }
+
+ PathPoint var8 = this.getSafePoint(par1Entity, par2PathPoint.xCoord, par2PathPoint.yCoord,
+ par2PathPoint.zCoord + 1, par3PathPoint, var7);
+ PathPoint var9 = this.getSafePoint(par1Entity, par2PathPoint.xCoord - 1, par2PathPoint.yCoord,
+ par2PathPoint.zCoord, par3PathPoint, var7);
+ PathPoint var10 = this.getSafePoint(par1Entity, par2PathPoint.xCoord + 1, par2PathPoint.yCoord,
+ par2PathPoint.zCoord, par3PathPoint, var7);
+ PathPoint var11 = this.getSafePoint(par1Entity, par2PathPoint.xCoord, par2PathPoint.yCoord,
+ par2PathPoint.zCoord - 1, par3PathPoint, var7);
+
+ if (var8 != null && !var8.isFirst && var8.distanceTo(par4PathPoint) < par5) {
+ this.pathOptions[var6++] = var8;
+ }
+
+ if (var9 != null && !var9.isFirst && var9.distanceTo(par4PathPoint) < par5) {
+ this.pathOptions[var6++] = var9;
+ }
+
+ if (var10 != null && !var10.isFirst && var10.distanceTo(par4PathPoint) < par5) {
+ this.pathOptions[var6++] = var10;
+ }
+
+ if (var11 != null && !var11.isFirst && var11.distanceTo(par4PathPoint) < par5) {
+ this.pathOptions[var6++] = var11;
+ }
+
+ return var6;
+ }
+
+ /**
+ * Returns a point that the entity can safely move to
+ */
+ private PathPoint getSafePoint(Entity par1Entity, int par2, int par3, int par4, PathPoint par5PathPoint, int par6) {
+ PathPoint var7 = null;
+ int var8 = this.getVerticalOffset(par1Entity, par2, par3, par4, par5PathPoint);
+
+ if (var8 == 2) {
+ return this.openPoint(par2, par3, par4);
+ } else {
+ if (var8 == 1) {
+ var7 = this.openPoint(par2, par3, par4);
+ }
+
+ if (var7 == null && par6 > 0 && var8 != -3 && var8 != -4
+ && this.getVerticalOffset(par1Entity, par2, par3 + par6, par4, par5PathPoint) == 1) {
+ var7 = this.openPoint(par2, par3 + par6, par4);
+ par3 += par6;
+ }
+
+ if (var7 != null) {
+ int var9 = 0;
+ int var10 = 0;
+
+ while (par3 > 0) {
+ var10 = this.getVerticalOffset(par1Entity, par2, par3 - 1, par4, par5PathPoint);
+
+ if (this.isPathingInWater && var10 == -1) {
+ return null;
+ }
+
+ if (var10 != 1) {
+ break;
+ }
+
+ if (var9++ >= par1Entity.func_82143_as()) {
+ return null;
+ }
+
+ --par3;
+
+ if (par3 > 0) {
+ var7 = this.openPoint(par2, par3, par4);
+ }
+ }
+
+ if (var10 == -2) {
+ return null;
+ }
+ }
+
+ return var7;
+ }
+ }
+
+ /**
+ * Returns a mapped point or creates and adds one
+ */
+ private final PathPoint openPoint(int par1, int par2, int par3) {
+ int var4 = PathPoint.makeHash(par1, par2, par3);
+ PathPoint var5 = (PathPoint) this.pointMap.lookup(var4);
+
+ if (var5 == null) {
+ var5 = new PathPoint(par1, par2, par3);
+ this.pointMap.addKey(var4, var5);
+ }
+
+ return var5;
+ }
+
+ /**
+ * Given an x y z, returns a vertical offset needed to search to find a block to
+ * stand on
+ */
+ public int getVerticalOffset(Entity par1Entity, int par2, int par3, int par4, PathPoint par5PathPoint) {
+ return func_82565_a(par1Entity, par2, par3, par4, par5PathPoint, this.isPathingInWater,
+ this.isMovementBlockAllowed, this.isWoddenDoorAllowed);
+ }
+
+ public static int func_82565_a(Entity par0Entity, int par1, int par2, int par3, PathPoint par4PathPoint,
+ boolean par5, boolean par6, boolean par7) {
+ boolean var8 = false;
+
+ for (int var9 = par1; var9 < par1 + par4PathPoint.xCoord; ++var9) {
+ for (int var10 = par2; var10 < par2 + par4PathPoint.yCoord; ++var10) {
+ for (int var11 = par3; var11 < par3 + par4PathPoint.zCoord; ++var11) {
+ int var12 = par0Entity.worldObj.getBlockId(var9, var10, var11);
+
+ if (var12 > 0) {
+ if (var12 == Block.trapdoor.blockID) {
+ var8 = true;
+ } else if (var12 != Block.waterMoving.blockID && var12 != Block.waterStill.blockID) {
+ if (!par7 && var12 == Block.doorWood.blockID) {
+ return 0;
+ }
+ } else {
+ if (par5) {
+ return -1;
+ }
+
+ var8 = true;
+ }
+
+ Block var13 = Block.blocksList[var12];
+ int var14 = var13.getRenderType();
+
+ if (par0Entity.worldObj.blockGetRenderType(var9, var10, var11) == 9) {
+ int var18 = MathHelper.floor_double(par0Entity.posX);
+ int var16 = MathHelper.floor_double(par0Entity.posY);
+ int var17 = MathHelper.floor_double(par0Entity.posZ);
+
+ if (par0Entity.worldObj.blockGetRenderType(var18, var16, var17) != 9
+ && par0Entity.worldObj.blockGetRenderType(var18, var16 - 1, var17) != 9) {
+ return -3;
+ }
+ } else if (!var13.getBlocksMovement(par0Entity.worldObj, var9, var10, var11)
+ && (!par6 || var12 != Block.doorWood.blockID)) {
+ if (var14 == 11 || var12 == Block.fenceGate.blockID || var14 == 32) {
+ return -3;
+ }
+
+ if (var12 == Block.trapdoor.blockID) {
+ return -4;
+ }
+
+ Material var15 = var13.blockMaterial;
+
+ if (var15 != Material.lava) {
+ return 0;
+ }
+
+ if (!par0Entity.handleLavaMovement()) {
+ return -2;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return var8 ? 2 : 1;
+ }
+
+ /**
+ * Returns a new PathEntity for a given start and end point
+ */
+ private PathEntity createEntityPath(PathPoint par1PathPoint, PathPoint par2PathPoint) {
+ int var3 = 1;
+ PathPoint var4;
+
+ for (var4 = par2PathPoint; var4.previous != null; var4 = var4.previous) {
+ ++var3;
+ }
+
+ PathPoint[] var5 = new PathPoint[var3];
+ var4 = par2PathPoint;
+ --var3;
+
+ for (var5[var3] = par2PathPoint; var4.previous != null; var5[var3] = var4) {
+ var4 = var4.previous;
+ --var3;
+ }
+
+ return new PathEntity(var5);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/PathNavigate.java b/sp-server/src/main/java/net/minecraft/src/PathNavigate.java
new file mode 100644
index 0000000..808a79d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/PathNavigate.java
@@ -0,0 +1,458 @@
+package net.minecraft.src;
+
+public class PathNavigate {
+ private EntityLiving theEntity;
+ private World worldObj;
+
+ /** The PathEntity being followed. */
+ private PathEntity currentPath;
+ private float speed;
+
+ /**
+ * The number of blocks (extra) +/- in each axis that get pulled out as cache
+ * for the pathfinder's search space
+ */
+ private float pathSearchRange;
+ private boolean noSunPathfind = false;
+
+ /** Time, in number of ticks, following the current path */
+ private int totalTicks;
+
+ /**
+ * The time when the last position check was done (to detect successful
+ * movement)
+ */
+ private int ticksAtLastPos;
+
+ /**
+ * Coordinates of the entity's position last time a check was done (part of
+ * monitoring getting 'stuck')
+ */
+ private Vec3 lastPosCheck = Vec3.createVectorHelper(0.0D, 0.0D, 0.0D);
+
+ /**
+ * Specifically, if a wooden door block is even considered to be passable by the
+ * pathfinder
+ */
+ private boolean canPassOpenWoodenDoors = true;
+
+ /** If door blocks are considered passable even when closed */
+ private boolean canPassClosedWoodenDoors = false;
+
+ /** If water blocks are avoided (at least by the pathfinder) */
+ private boolean avoidsWater = false;
+
+ /**
+ * If the entity can swim. Swimming AI enables this and the pathfinder will also
+ * cause the entity to swim straight upwards when underwater
+ */
+ private boolean canSwim = false;
+
+ public PathNavigate(EntityLiving par1EntityLiving, World par2World, float par3) {
+ this.theEntity = par1EntityLiving;
+ this.worldObj = par2World;
+ this.pathSearchRange = par3;
+ }
+
+ public void setAvoidsWater(boolean par1) {
+ this.avoidsWater = par1;
+ }
+
+ public boolean getAvoidsWater() {
+ return this.avoidsWater;
+ }
+
+ public void setBreakDoors(boolean par1) {
+ this.canPassClosedWoodenDoors = par1;
+ }
+
+ /**
+ * Sets if the entity can enter open doors
+ */
+ public void setEnterDoors(boolean par1) {
+ this.canPassOpenWoodenDoors = par1;
+ }
+
+ /**
+ * Returns true if the entity can break doors, false otherwise
+ */
+ public boolean getCanBreakDoors() {
+ return this.canPassClosedWoodenDoors;
+ }
+
+ /**
+ * Sets if the path should avoid sunlight
+ */
+ public void setAvoidSun(boolean par1) {
+ this.noSunPathfind = par1;
+ }
+
+ /**
+ * Sets the speed
+ */
+ public void setSpeed(float par1) {
+ this.speed = par1;
+ }
+
+ /**
+ * Sets if the entity can swim
+ */
+ public void setCanSwim(boolean par1) {
+ this.canSwim = par1;
+ }
+
+ /**
+ * Returns the path to the given coordinates
+ */
+ public PathEntity getPathToXYZ(double par1, double par3, double par5) {
+ return !this.canNavigate() ? null
+ : this.worldObj.getEntityPathToXYZ(this.theEntity, MathHelper.floor_double(par1), (int) par3,
+ MathHelper.floor_double(par5), this.pathSearchRange, this.canPassOpenWoodenDoors,
+ this.canPassClosedWoodenDoors, this.avoidsWater, this.canSwim);
+ }
+
+ /**
+ * Try to find and set a path to XYZ. Returns true if successful.
+ */
+ public boolean tryMoveToXYZ(double par1, double par3, double par5, float par7) {
+ PathEntity var8 = this.getPathToXYZ((double) MathHelper.floor_double(par1), (double) ((int) par3),
+ (double) MathHelper.floor_double(par5));
+ return this.setPath(var8, par7);
+ }
+
+ /**
+ * Returns the path to the given EntityLiving
+ */
+ public PathEntity getPathToEntityLiving(EntityLiving par1EntityLiving) {
+ return !this.canNavigate() ? null
+ : this.worldObj.getPathEntityToEntity(this.theEntity, par1EntityLiving, this.pathSearchRange,
+ this.canPassOpenWoodenDoors, this.canPassClosedWoodenDoors, this.avoidsWater, this.canSwim);
+ }
+
+ /**
+ * Try to find and set a path to EntityLiving. Returns true if successful.
+ */
+ public boolean tryMoveToEntityLiving(EntityLiving par1EntityLiving, float par2) {
+ PathEntity var3 = this.getPathToEntityLiving(par1EntityLiving);
+ return var3 != null ? this.setPath(var3, par2) : false;
+ }
+
+ /**
+ * sets the active path data if path is 100% unique compared to old path, checks
+ * to adjust path for sun avoiding ents and stores end coords
+ */
+ public boolean setPath(PathEntity par1PathEntity, float par2) {
+ if (par1PathEntity == null) {
+ this.currentPath = null;
+ return false;
+ } else {
+ if (!par1PathEntity.isSamePath(this.currentPath)) {
+ this.currentPath = par1PathEntity;
+ }
+
+ if (this.noSunPathfind) {
+ this.removeSunnyPath();
+ }
+
+ if (this.currentPath.getCurrentPathLength() == 0) {
+ return false;
+ } else {
+ this.speed = par2;
+ Vec3 var3 = this.getEntityPosition();
+ this.ticksAtLastPos = this.totalTicks;
+ this.lastPosCheck.xCoord = var3.xCoord;
+ this.lastPosCheck.yCoord = var3.yCoord;
+ this.lastPosCheck.zCoord = var3.zCoord;
+ return true;
+ }
+ }
+ }
+
+ /**
+ * gets the actively used PathEntity
+ */
+ public PathEntity getPath() {
+ return this.currentPath;
+ }
+
+ public void onUpdateNavigation() {
+ ++this.totalTicks;
+
+ if (!this.noPath()) {
+ if (this.canNavigate()) {
+ this.pathFollow();
+ }
+
+ if (!this.noPath()) {
+ Vec3 var1 = this.currentPath.getPosition(this.theEntity);
+
+ if (var1 != null) {
+ this.theEntity.getMoveHelper().setMoveTo(var1.xCoord, var1.yCoord, var1.zCoord, this.speed);
+ }
+ }
+ }
+ }
+
+ private void pathFollow() {
+ Vec3 var1 = this.getEntityPosition();
+ int var2 = this.currentPath.getCurrentPathLength();
+
+ for (int var3 = this.currentPath.getCurrentPathIndex(); var3 < this.currentPath
+ .getCurrentPathLength(); ++var3) {
+ if (this.currentPath.getPathPointFromIndex(var3).yCoord != (int) var1.yCoord) {
+ var2 = var3;
+ break;
+ }
+ }
+
+ float var8 = this.theEntity.width * this.theEntity.width;
+ int var4;
+
+ for (var4 = this.currentPath.getCurrentPathIndex(); var4 < var2; ++var4) {
+ if (var1.squareDistanceTo(this.currentPath.getVectorFromIndex(this.theEntity, var4)) < (double) var8) {
+ this.currentPath.setCurrentPathIndex(var4 + 1);
+ }
+ }
+
+ var4 = MathHelper.ceiling_float_int(this.theEntity.width);
+ int var5 = (int) this.theEntity.height + 1;
+ int var6 = var4;
+
+ for (int var7 = var2 - 1; var7 >= this.currentPath.getCurrentPathIndex(); --var7) {
+ if (this.isDirectPathBetweenPoints(var1, this.currentPath.getVectorFromIndex(this.theEntity, var7), var4,
+ var5, var6)) {
+ this.currentPath.setCurrentPathIndex(var7);
+ break;
+ }
+ }
+
+ if (this.totalTicks - this.ticksAtLastPos > 100) {
+ if (var1.squareDistanceTo(this.lastPosCheck) < 2.25D) {
+ this.clearPathEntity();
+ }
+
+ this.ticksAtLastPos = this.totalTicks;
+ this.lastPosCheck.xCoord = var1.xCoord;
+ this.lastPosCheck.yCoord = var1.yCoord;
+ this.lastPosCheck.zCoord = var1.zCoord;
+ }
+ }
+
+ /**
+ * If null path or reached the end
+ */
+ public boolean noPath() {
+ return this.currentPath == null || this.currentPath.isFinished();
+ }
+
+ /**
+ * sets active PathEntity to null
+ */
+ public void clearPathEntity() {
+ this.currentPath = null;
+ }
+
+ private Vec3 getEntityPosition() {
+ return this.worldObj.getWorldVec3Pool().getVecFromPool(this.theEntity.posX, (double) this.getPathableYPos(),
+ this.theEntity.posZ);
+ }
+
+ /**
+ * Gets the safe pathing Y position for the entity depending on if it can path
+ * swim or not
+ */
+ private int getPathableYPos() {
+ if (this.theEntity.isInWater() && this.canSwim) {
+ int var1 = (int) this.theEntity.boundingBox.minY;
+ int var2 = this.worldObj.getBlockId(MathHelper.floor_double(this.theEntity.posX), var1,
+ MathHelper.floor_double(this.theEntity.posZ));
+ int var3 = 0;
+
+ do {
+ if (var2 != Block.waterMoving.blockID && var2 != Block.waterStill.blockID) {
+ return var1;
+ }
+
+ ++var1;
+ var2 = this.worldObj.getBlockId(MathHelper.floor_double(this.theEntity.posX), var1,
+ MathHelper.floor_double(this.theEntity.posZ));
+ ++var3;
+ } while (var3 <= 16);
+
+ return (int) this.theEntity.boundingBox.minY;
+ } else {
+ return (int) (this.theEntity.boundingBox.minY + 0.5D);
+ }
+ }
+
+ /**
+ * If on ground or swimming and can swim
+ */
+ private boolean canNavigate() {
+ return this.theEntity.onGround || this.canSwim && this.isInFluid();
+ }
+
+ /**
+ * Returns true if the entity is in water or lava, false otherwise
+ */
+ private boolean isInFluid() {
+ return this.theEntity.isInWater() || this.theEntity.handleLavaMovement();
+ }
+
+ /**
+ * Trims path data from the end to the first sun covered block
+ */
+ private void removeSunnyPath() {
+ if (!this.worldObj.canBlockSeeTheSky(MathHelper.floor_double(this.theEntity.posX),
+ (int) (this.theEntity.boundingBox.minY + 0.5D), MathHelper.floor_double(this.theEntity.posZ))) {
+ for (int var1 = 0; var1 < this.currentPath.getCurrentPathLength(); ++var1) {
+ PathPoint var2 = this.currentPath.getPathPointFromIndex(var1);
+
+ if (this.worldObj.canBlockSeeTheSky(var2.xCoord, var2.yCoord, var2.zCoord)) {
+ this.currentPath.setCurrentPathLength(var1 - 1);
+ return;
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns true when an entity of specified size could safely walk in a straight
+ * line between the two points. Args: pos1, pos2, entityXSize, entityYSize,
+ * entityZSize
+ */
+ private boolean isDirectPathBetweenPoints(Vec3 par1Vec3, Vec3 par2Vec3, int par3, int par4, int par5) {
+ int var6 = MathHelper.floor_double(par1Vec3.xCoord);
+ int var7 = MathHelper.floor_double(par1Vec3.zCoord);
+ double var8 = par2Vec3.xCoord - par1Vec3.xCoord;
+ double var10 = par2Vec3.zCoord - par1Vec3.zCoord;
+ double var12 = var8 * var8 + var10 * var10;
+
+ if (var12 < 1.0E-8D) {
+ return false;
+ } else {
+ double var14 = 1.0D / Math.sqrt(var12);
+ var8 *= var14;
+ var10 *= var14;
+ par3 += 2;
+ par5 += 2;
+
+ if (!this.isSafeToStandAt(var6, (int) par1Vec3.yCoord, var7, par3, par4, par5, par1Vec3, var8, var10)) {
+ return false;
+ } else {
+ par3 -= 2;
+ par5 -= 2;
+ double var16 = 1.0D / Math.abs(var8);
+ double var18 = 1.0D / Math.abs(var10);
+ double var20 = (double) (var6 * 1) - par1Vec3.xCoord;
+ double var22 = (double) (var7 * 1) - par1Vec3.zCoord;
+
+ if (var8 >= 0.0D) {
+ ++var20;
+ }
+
+ if (var10 >= 0.0D) {
+ ++var22;
+ }
+
+ var20 /= var8;
+ var22 /= var10;
+ int var24 = var8 < 0.0D ? -1 : 1;
+ int var25 = var10 < 0.0D ? -1 : 1;
+ int var26 = MathHelper.floor_double(par2Vec3.xCoord);
+ int var27 = MathHelper.floor_double(par2Vec3.zCoord);
+ int var28 = var26 - var6;
+ int var29 = var27 - var7;
+
+ do {
+ if (var28 * var24 <= 0 && var29 * var25 <= 0) {
+ return true;
+ }
+
+ if (var20 < var22) {
+ var20 += var16;
+ var6 += var24;
+ var28 = var26 - var6;
+ } else {
+ var22 += var18;
+ var7 += var25;
+ var29 = var27 - var7;
+ }
+ } while (this.isSafeToStandAt(var6, (int) par1Vec3.yCoord, var7, par3, par4, par5, par1Vec3, var8,
+ var10));
+
+ return false;
+ }
+ }
+ }
+
+ /**
+ * Returns true when an entity could stand at a position, including solid blocks
+ * under the entire entity. Args: xOffset, yOffset, zOffset, entityXSize,
+ * entityYSize, entityZSize, originPosition, vecX, vecZ
+ */
+ private boolean isSafeToStandAt(int par1, int par2, int par3, int par4, int par5, int par6, Vec3 par7Vec3,
+ double par8, double par10) {
+ int var12 = par1 - par4 / 2;
+ int var13 = par3 - par6 / 2;
+
+ if (!this.isPositionClear(var12, par2, var13, par4, par5, par6, par7Vec3, par8, par10)) {
+ return false;
+ } else {
+ for (int var14 = var12; var14 < var12 + par4; ++var14) {
+ for (int var15 = var13; var15 < var13 + par6; ++var15) {
+ double var16 = (double) var14 + 0.5D - par7Vec3.xCoord;
+ double var18 = (double) var15 + 0.5D - par7Vec3.zCoord;
+
+ if (var16 * par8 + var18 * par10 >= 0.0D) {
+ int var20 = this.worldObj.getBlockId(var14, par2 - 1, var15);
+
+ if (var20 <= 0) {
+ return false;
+ }
+
+ Material var21 = Block.blocksList[var20].blockMaterial;
+
+ if (var21 == Material.water && !this.theEntity.isInWater()) {
+ return false;
+ }
+
+ if (var21 == Material.lava) {
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+ }
+
+ /**
+ * Returns true if an entity does not collide with any solid blocks at the
+ * position. Args: xOffset, yOffset, zOffset, entityXSize, entityYSize,
+ * entityZSize, originPosition, vecX, vecZ
+ */
+ private boolean isPositionClear(int par1, int par2, int par3, int par4, int par5, int par6, Vec3 par7Vec3,
+ double par8, double par10) {
+ for (int var12 = par1; var12 < par1 + par4; ++var12) {
+ for (int var13 = par2; var13 < par2 + par5; ++var13) {
+ for (int var14 = par3; var14 < par3 + par6; ++var14) {
+ double var15 = (double) var12 + 0.5D - par7Vec3.xCoord;
+ double var17 = (double) var14 + 0.5D - par7Vec3.zCoord;
+
+ if (var15 * par8 + var17 * par10 >= 0.0D) {
+ int var19 = this.worldObj.getBlockId(var12, var13, var14);
+
+ if (var19 > 0
+ && !Block.blocksList[var19].getBlocksMovement(this.worldObj, var12, var13, var14)) {
+ return false;
+ }
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/PathPoint.java b/sp-server/src/main/java/net/minecraft/src/PathPoint.java
new file mode 100644
index 0000000..dac2d28
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/PathPoint.java
@@ -0,0 +1,87 @@
+package net.minecraft.src;
+
+public class PathPoint {
+ /** The x coordinate of this point */
+ public final int xCoord;
+
+ /** The y coordinate of this point */
+ public final int yCoord;
+
+ /** The z coordinate of this point */
+ public final int zCoord;
+
+ /** A hash of the coordinates used to identify this point */
+ private final int hash;
+
+ /** The index of this point in its assigned path */
+ int index = -1;
+
+ /** The distance along the path to this point */
+ float totalPathDistance;
+
+ /** The linear distance to the next point */
+ float distanceToNext;
+
+ /** The distance to the target */
+ float distanceToTarget;
+
+ /** The point preceding this in its assigned path */
+ PathPoint previous;
+
+ /** Indicates this is the origin */
+ public boolean isFirst = false;
+
+ public PathPoint(int par1, int par2, int par3) {
+ this.xCoord = par1;
+ this.yCoord = par2;
+ this.zCoord = par3;
+ this.hash = makeHash(par1, par2, par3);
+ }
+
+ public static int makeHash(int par0, int par1, int par2) {
+ return par1 & 255 | (par0 & 32767) << 8 | (par2 & 32767) << 24 | (par0 < 0 ? Integer.MIN_VALUE : 0)
+ | (par2 < 0 ? 32768 : 0);
+ }
+
+ /**
+ * Returns the linear distance to another path point
+ */
+ public float distanceTo(PathPoint par1PathPoint) {
+ float var2 = (float) (par1PathPoint.xCoord - this.xCoord);
+ float var3 = (float) (par1PathPoint.yCoord - this.yCoord);
+ float var4 = (float) (par1PathPoint.zCoord - this.zCoord);
+ return MathHelper.sqrt_float(var2 * var2 + var3 * var3 + var4 * var4);
+ }
+
+ public float func_75832_b(PathPoint par1PathPoint) {
+ float var2 = (float) (par1PathPoint.xCoord - this.xCoord);
+ float var3 = (float) (par1PathPoint.yCoord - this.yCoord);
+ float var4 = (float) (par1PathPoint.zCoord - this.zCoord);
+ return var2 * var2 + var3 * var3 + var4 * var4;
+ }
+
+ public boolean equals(Object par1Obj) {
+ if (!(par1Obj instanceof PathPoint)) {
+ return false;
+ } else {
+ PathPoint var2 = (PathPoint) par1Obj;
+ return this.hash == var2.hash && this.xCoord == var2.xCoord && this.yCoord == var2.yCoord
+ && this.zCoord == var2.zCoord;
+ }
+ }
+
+ public int hashCode() {
+ return this.hash;
+ }
+
+ /**
+ * Returns true if this point has already been assigned to a path
+ */
+ public boolean isAssigned() {
+ return this.index >= 0;
+ }
+
+ public String toString() {
+ return this.xCoord + ", " + this.yCoord + ", " + this.zCoord;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/PlayerCapabilities.java b/sp-server/src/main/java/net/minecraft/src/PlayerCapabilities.java
new file mode 100644
index 0000000..0fd3fe1
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/PlayerCapabilities.java
@@ -0,0 +1,62 @@
+package net.minecraft.src;
+
+public class PlayerCapabilities {
+ /** Disables player damage. */
+ public boolean disableDamage = false;
+
+ /** Sets/indicates whether the player is flying. */
+ public boolean isFlying = false;
+
+ /** whether or not to allow the player to fly when they double jump. */
+ public boolean allowFlying = false;
+
+ /**
+ * Used to determine if creative mode is enabled, and therefore if items should
+ * be depleted on usage
+ */
+ public boolean isCreativeMode = false;
+
+ /** Indicates whether the player is allowed to modify the surroundings */
+ public boolean allowEdit = true;
+ private float flySpeed = 0.05F;
+ private float walkSpeed = 0.1F;
+
+ public void writeCapabilitiesToNBT(NBTTagCompound par1NBTTagCompound) {
+ NBTTagCompound var2 = new NBTTagCompound();
+ var2.setBoolean("invulnerable", this.disableDamage);
+ var2.setBoolean("flying", this.isFlying);
+ var2.setBoolean("mayfly", this.allowFlying);
+ var2.setBoolean("instabuild", this.isCreativeMode);
+ var2.setBoolean("mayBuild", this.allowEdit);
+ var2.setFloat("flySpeed", this.flySpeed);
+ var2.setFloat("walkSpeed", this.walkSpeed);
+ par1NBTTagCompound.setTag("abilities", var2);
+ }
+
+ public void readCapabilitiesFromNBT(NBTTagCompound par1NBTTagCompound) {
+ if (par1NBTTagCompound.hasKey("abilities")) {
+ NBTTagCompound var2 = par1NBTTagCompound.getCompoundTag("abilities");
+ this.disableDamage = var2.getBoolean("invulnerable");
+ this.isFlying = var2.getBoolean("flying");
+ this.allowFlying = var2.getBoolean("mayfly");
+ this.isCreativeMode = var2.getBoolean("instabuild");
+
+ if (var2.hasKey("flySpeed")) {
+ this.flySpeed = var2.getFloat("flySpeed");
+ this.walkSpeed = var2.getFloat("walkSpeed");
+ }
+
+ if (var2.hasKey("mayBuild")) {
+ this.allowEdit = var2.getBoolean("mayBuild");
+ }
+ }
+ }
+
+ public float getFlySpeed() {
+ return this.flySpeed;
+ }
+
+ public float getWalkSpeed() {
+ return this.walkSpeed;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/PlayerInstance.java b/sp-server/src/main/java/net/minecraft/src/PlayerInstance.java
new file mode 100644
index 0000000..6261ecd
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/PlayerInstance.java
@@ -0,0 +1,202 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.List;
+
+class PlayerInstance {
+ /** the list of all players in this instance (chunk) */
+ private final List players;
+
+ /** the chunk the player currently resides in */
+ private final ChunkCoordIntPair currentChunk;
+
+ /** array of blocks to update this tick */
+ private short[] blocksToUpdate;
+
+ /** the number of blocks that need to be updated next tick */
+ private int numBlocksToUpdate;
+ private int field_73260_f;
+
+ final PlayerManager thePlayerManager;
+
+ public PlayerInstance(PlayerManager par1PlayerManager, int par2, int par3) {
+ this.thePlayerManager = par1PlayerManager;
+ this.players = new ArrayList();
+ this.blocksToUpdate = new short[64];
+ this.numBlocksToUpdate = 0;
+ this.currentChunk = new ChunkCoordIntPair(par2, par3);
+ par1PlayerManager.getMinecraftServer().theChunkProviderServer.loadChunk(par2, par3);
+ }
+
+ /**
+ * adds this player to the playerInstance
+ */
+ public void addPlayer(EntityPlayerMP par1EntityPlayerMP) {
+ if (this.players.contains(par1EntityPlayerMP)) {
+ // fuck you teavm...
+ /*
+ throw new IllegalStateException("Failed to add player. " + par1EntityPlayerMP + " already is in chunk "
+ + this.currentChunk.chunkXPos + ", " + this.currentChunk.chunkZPos);
+ */
+ this.thePlayerManager.getMinecraftServer().getWorldLogAgent().logSevere("Failed to add player. " + par1EntityPlayerMP + " already is in chunk "
+ + this.currentChunk.chunkXPos + ", " + this.currentChunk.chunkZPos);
+ } else {
+ this.players.add(par1EntityPlayerMP);
+ par1EntityPlayerMP.loadedChunks.add(this.currentChunk);
+ }
+ }
+
+ public boolean hasPlayer(EntityPlayerMP player) {
+ return this.players.contains(player);
+ }
+
+ public boolean isEmpty() {
+ return this.players.size() <= 0;
+ }
+
+ /**
+ * remove player from this instance
+ */
+ public void removePlayer(EntityPlayerMP par1EntityPlayerMP) {
+ if (this.players.contains(par1EntityPlayerMP)) {
+ par1EntityPlayerMP.playerNetServerHandler.sendPacket(
+ new Packet51MapChunk(PlayerManager.getWorldServer(this.thePlayerManager).getChunkFromChunkCoords(
+ this.currentChunk.chunkXPos, this.currentChunk.chunkZPos), true, 0));
+ this.players.remove(par1EntityPlayerMP);
+ par1EntityPlayerMP.loadedChunks.remove(this.currentChunk);
+
+ if (this.players.isEmpty()) {
+ long var2 = ((long) this.currentChunk.chunkXPos + 2147483647L)
+ | (((long) this.currentChunk.chunkZPos + 2147483647L) << 32);
+ PlayerManager.getChunkWatchers(this.thePlayerManager).remove(var2);
+
+ if (this.numBlocksToUpdate > 0) {
+ PlayerManager.getChunkWatchersWithPlayers(this.thePlayerManager).remove(this);
+ }
+
+ this.thePlayerManager.getMinecraftServer().theChunkProviderServer.dropChunk(this.currentChunk.chunkXPos,
+ this.currentChunk.chunkZPos);
+ }
+ }
+ }
+
+ /**
+ * mark the block as changed so that it will update clients who need to know
+ * about it
+ */
+ public void markBlockNeedsUpdate(int par1, int par2, int par3) {
+ if (this.numBlocksToUpdate == 0) {
+ PlayerManager.getChunkWatchersWithPlayers(this.thePlayerManager).add(this);
+ }
+
+ this.field_73260_f |= 1 << (par2 >> 4);
+
+ if (this.numBlocksToUpdate < 64) {
+ short var4 = (short) (par1 << 12 | par3 << 8 | par2);
+
+ for (int var5 = 0; var5 < this.numBlocksToUpdate; ++var5) {
+ if (this.blocksToUpdate[var5] == var4) {
+ return;
+ }
+ }
+
+ this.blocksToUpdate[this.numBlocksToUpdate++] = var4;
+ }
+ }
+
+ /**
+ * sends the packet to all players in the current instance
+ */
+ public void sendPacketToPlayersInInstance(Packet par1Packet) {
+ for (int var2 = 0; var2 < this.players.size(); ++var2) {
+ EntityPlayerMP var3 = (EntityPlayerMP) this.players.get(var2);
+
+ if (!var3.loadedChunks.contains(this.currentChunk)) {
+ var3.playerNetServerHandler.sendPacket(par1Packet);
+ }
+ }
+ }
+
+ public void onUpdate() {
+ if (this.numBlocksToUpdate != 0) {
+ int var1;
+ int var2;
+ int var3;
+
+ if (this.numBlocksToUpdate == 1) {
+ var1 = this.currentChunk.chunkXPos * 16 + (this.blocksToUpdate[0] >> 12 & 15);
+ var2 = this.blocksToUpdate[0] & 255;
+ var3 = this.currentChunk.chunkZPos * 16 + (this.blocksToUpdate[0] >> 8 & 15);
+ this.sendPacketToPlayersInInstance(
+ new Packet53BlockChange(var1, var2, var3, PlayerManager.getWorldServer(this.thePlayerManager)));
+
+ if (PlayerManager.getWorldServer(this.thePlayerManager).blockHasTileEntity(var1, var2, var3)) {
+ this.updateTileEntity(
+ PlayerManager.getWorldServer(this.thePlayerManager).getBlockTileEntity(var1, var2, var3));
+ }
+ } else {
+ int var4;
+
+ if (this.numBlocksToUpdate == 64) {
+ var1 = this.currentChunk.chunkXPos * 16;
+ var2 = this.currentChunk.chunkZPos * 16;
+ this.sendPacketToPlayersInInstance(new Packet51MapChunk(
+ PlayerManager.getWorldServer(this.thePlayerManager)
+ .getChunkFromChunkCoords(this.currentChunk.chunkXPos, this.currentChunk.chunkZPos),
+ false, this.field_73260_f));
+
+ for (var3 = 0; var3 < 16; ++var3) {
+ if ((this.field_73260_f & 1 << var3) != 0) {
+ var4 = var3 << 4;
+ List var5 = PlayerManager.getWorldServer(this.thePlayerManager).getTileEntityList(var1,
+ var4, var2, var1 + 16, var4 + 16, var2 + 16);
+
+ for (int var6 = 0; var6 < var5.size(); ++var6) {
+ this.updateTileEntity((TileEntity) var5.get(var6));
+ }
+ }
+ }
+ } else {
+ this.sendPacketToPlayersInInstance(new Packet52MultiBlockChange(this.currentChunk.chunkXPos,
+ this.currentChunk.chunkZPos, this.blocksToUpdate, this.numBlocksToUpdate,
+ PlayerManager.getWorldServer(this.thePlayerManager)));
+
+ for (var1 = 0; var1 < this.numBlocksToUpdate; ++var1) {
+ var2 = this.currentChunk.chunkXPos * 16 + (this.blocksToUpdate[var1] >> 12 & 15);
+ var3 = this.blocksToUpdate[var1] & 255;
+ var4 = this.currentChunk.chunkZPos * 16 + (this.blocksToUpdate[var1] >> 8 & 15);
+
+ if (PlayerManager.getWorldServer(this.thePlayerManager).blockHasTileEntity(var2, var3, var4)) {
+ this.updateTileEntity(PlayerManager.getWorldServer(this.thePlayerManager)
+ .getBlockTileEntity(var2, var3, var4));
+ }
+ }
+ }
+ }
+
+ this.numBlocksToUpdate = 0;
+ this.field_73260_f = 0;
+ }
+ }
+
+ /**
+ * sends players update packet about the given entity
+ */
+ private void updateTileEntity(TileEntity par1TileEntity) {
+ if (par1TileEntity != null) {
+ Packet var2 = par1TileEntity.getDescriptionPacket();
+
+ if (var2 != null) {
+ this.sendPacketToPlayersInInstance(var2);
+ }
+ }
+ }
+
+ static ChunkCoordIntPair getChunkLocation(PlayerInstance par0PlayerInstance) {
+ return par0PlayerInstance.currentChunk;
+ }
+
+ static List getPlayersInChunk(PlayerInstance par0PlayerInstance) {
+ return par0PlayerInstance.players;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/PlayerListBox.java b/sp-server/src/main/java/net/minecraft/src/PlayerListBox.java
new file mode 100644
index 0000000..39c8979
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/PlayerListBox.java
@@ -0,0 +1,36 @@
+package net.minecraft.src;
+
+import java.util.Vector;
+
+import javax.swing.JList;
+
+import net.minecraft.server.MinecraftServer;
+
+public class PlayerListBox extends JList implements IUpdatePlayerListBox {
+ /** Reference to the MinecraftServer object. */
+ private MinecraftServer mcServer;
+
+ /** Counts the number of updates. */
+ private int updateCounter = 0;
+
+ public PlayerListBox(MinecraftServer par1MinecraftServer) {
+ this.mcServer = par1MinecraftServer;
+ par1MinecraftServer.func_82010_a(this);
+ }
+
+ /**
+ * Updates the JList with a new model.
+ */
+ public void update() {
+ if (this.updateCounter++ % 20 == 0) {
+ Vector var1 = new Vector();
+
+ for (int var2 = 0; var2 < this.mcServer.getConfigurationManager().playerEntityList.size(); ++var2) {
+ var1.add(
+ ((EntityPlayerMP) this.mcServer.getConfigurationManager().playerEntityList.get(var2)).username);
+ }
+
+ this.setListData(var1);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/PlayerManager.java b/sp-server/src/main/java/net/minecraft/src/PlayerManager.java
new file mode 100644
index 0000000..56d1839
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/PlayerManager.java
@@ -0,0 +1,297 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class PlayerManager {
+ private final WorldServer theWorldServer;
+
+ /** players in the current instance */
+ private final List players = new ArrayList();
+
+ /** the hash of all playerInstances created */
+ private final LongHashMap playerInstances = new LongHashMap();
+
+ /** the playerInstances(chunks) that need to be updated */
+ private final List playerInstancesToUpdate = new ArrayList();
+
+ /** x, z direction vectors: east, south, west, north */
+ private final int[][] xzDirectionsConst = new int[][] { { 1, 0 }, { 0, 1 }, { -1, 0 }, { 0, -1 } };
+
+ public PlayerManager(WorldServer par1WorldServer, int par2) {
+ if (par2 > 15) {
+ throw new IllegalArgumentException("Too big view radius!");
+ } else if (par2 < 3) {
+ throw new IllegalArgumentException("Too small view radius!");
+ } else {
+ //this.playerViewRadius = par2;
+ this.theWorldServer = par1WorldServer;
+ }
+ }
+
+ /**
+ * Returns the MinecraftServer associated with the PlayerManager.
+ */
+ public WorldServer getMinecraftServer() {
+ return this.theWorldServer;
+ }
+
+ /**
+ * updates all the player instances that need to be updated
+ */
+ public void updatePlayerInstances() {
+ for (int var1 = 0; var1 < this.playerInstancesToUpdate.size(); ++var1) {
+ ((PlayerInstance) this.playerInstancesToUpdate.get(var1)).onUpdate();
+ }
+
+ this.playerInstancesToUpdate.clear();
+
+ if (this.players.isEmpty()) {
+ WorldProvider var2 = this.theWorldServer.provider;
+
+ if (!var2.canRespawnHere()) {
+ this.theWorldServer.theChunkProviderServer.unloadAllChunks();
+ }
+ }
+ }
+
+ /**
+ * passi n the chunk x and y and a flag as to whether or not the instance should
+ * be made if it doesnt exist
+ */
+ public PlayerInstance getPlayerInstance(int par1, int par2, boolean par3) {
+ long var4 = ((long) par1 + 2147483647L) | (((long) par2 + 2147483647L) << 32);
+ PlayerInstance var6 = (PlayerInstance) this.playerInstances.getValueByKey(var4);
+
+ if (var6 == null && par3) {
+ var6 = new PlayerInstance(this, par1, par2);
+ this.playerInstances.add(var4, var6);
+ }
+
+ return var6;
+ }
+
+ public void freePlayerInstance(long l) {
+ this.playerInstances.remove(l);
+ this.playerInstancesToUpdate.remove(l);
+ }
+
+ public void markBlockNeedsUpdate(int par1, int par2, int par3) {
+ int var4 = par1 >> 4;
+ int var5 = par3 >> 4;
+ PlayerInstance var6 = this.getPlayerInstance(var4, var5, false);
+
+ if (var6 != null) {
+ var6.markBlockNeedsUpdate(par1 & 15, par2, par3 & 15);
+ }
+ }
+
+ public void cycleRenderDistance(EntityPlayerMP player) {
+ if(player.lastRenderDistance != player.renderDistance) {
+ //player.lastRenderDistance = player.renderDistance;
+ player.mcServer.getConfigurationManager().updateOnRenderDistanceChange(player);
+ }
+ if(player.mcServer.getServerOwner().equals(player.username)) {
+ cycleAllRenderDistance(player);
+ }
+ }
+
+ public void cycleAllRenderDistance(EntityPlayerMP player) {
+ player.mcServer.getConfigurationManager().viewDistance = player.renderDistance;
+ player.lastRenderDistance = player.renderDistance;
+ List curList = new ArrayList();
+ curList.addAll(player.mcServer.getConfigurationManager().playerEntityList);
+ curList.remove(player);
+ int limited = player.renderDistance > 10 ? 10 : player.renderDistance;
+ for(int i = 0, l = curList.size(); i < l; ++i) {
+ EntityPlayerMP playerReload = (EntityPlayerMP)curList.get(i);
+ if(!player.mcServer.getServerOwner().equals(playerReload.username)) {
+ int targetRenderDist = player.renderDistance > limited ? limited : player.renderDistance;
+ if (playerReload.renderDistance != targetRenderDist) {
+ //playerReload.lastRenderDistance = playerReload.renderDistance = targetRenderDist;
+ playerReload.mcServer.getConfigurationManager().updateOnRenderDistanceChange(playerReload);
+ }
+ }
+ }
+ }
+
+ /**
+ * Adds an EntityPlayerMP to the PlayerManager.
+ */
+ public void addPlayer(EntityPlayerMP par1EntityPlayerMP) {
+ int var2 = (int) par1EntityPlayerMP.posX >> 4;
+ int var3 = (int) par1EntityPlayerMP.posZ >> 4;
+ par1EntityPlayerMP.managedPosX = par1EntityPlayerMP.posX;
+ par1EntityPlayerMP.managedPosZ = par1EntityPlayerMP.posZ;
+
+ int rd = par1EntityPlayerMP.lastRenderDistance = par1EntityPlayerMP.renderDistance;
+
+ for (int var4 = var2 - rd; var4 <= var2 + rd; ++var4) {
+ for (int var5 = var3 - rd; var5 <= var3 + rd; ++var5) {
+ PlayerInstance pi = this.getPlayerInstance(var4, var5, true);
+ if (!pi.hasPlayer(par1EntityPlayerMP)) {
+ pi.addPlayer(par1EntityPlayerMP);
+ }
+ if(!playerInstancesToUpdate.contains(pi)) {
+ playerInstancesToUpdate.add(pi);
+ }
+ }
+ }
+
+ this.players.add(par1EntityPlayerMP);
+ this.filterChunkLoadQueue(par1EntityPlayerMP);
+ }
+
+ /**
+ * Removes all chunks from the given player's chunk load queue that are not in
+ * viewing range of the player.
+ */
+ public void filterChunkLoadQueue(EntityPlayerMP par1EntityPlayerMP) {
+ if(par1EntityPlayerMP.lastRenderDistance != par1EntityPlayerMP.renderDistance) {
+ cycleRenderDistance(par1EntityPlayerMP);
+ }
+ ArrayList var2 = new ArrayList(par1EntityPlayerMP.loadedChunks);
+ int var3 = 0;
+ int var4 = par1EntityPlayerMP.renderDistance;
+ int var5 = (int) par1EntityPlayerMP.posX >> 4;
+ int var6 = (int) par1EntityPlayerMP.posZ >> 4;
+ int var7 = 0;
+ int var8 = 0;
+ ChunkCoordIntPair var9 = PlayerInstance.getChunkLocation(this.getPlayerInstance(var5, var6, true));
+ par1EntityPlayerMP.loadedChunks.clear();
+
+ if (var2.contains(var9)) {
+ par1EntityPlayerMP.loadedChunks.add(var9);
+ }
+
+ int var10;
+
+ for (var10 = 1; var10 <= var4 * 2; ++var10) {
+ for (int var11 = 0; var11 < 2; ++var11) {
+ int[] var12 = this.xzDirectionsConst[var3++ % 4];
+
+ for (int var13 = 0; var13 < var10; ++var13) {
+ var7 += var12[0];
+ var8 += var12[1];
+ var9 = PlayerInstance.getChunkLocation(this.getPlayerInstance(var5 + var7, var6 + var8, true));
+
+ if (var2.contains(var9)) {
+ par1EntityPlayerMP.loadedChunks.add(var9);
+ }
+ }
+ }
+ }
+
+ var3 %= 4;
+
+ for (var10 = 0; var10 < var4 * 2; ++var10) {
+ var7 += this.xzDirectionsConst[var3][0];
+ var8 += this.xzDirectionsConst[var3][1];
+ var9 = PlayerInstance.getChunkLocation(this.getPlayerInstance(var5 + var7, var6 + var8, true));
+
+ if (var2.contains(var9)) {
+ par1EntityPlayerMP.loadedChunks.add(var9);
+ }
+ }
+ }
+
+ /**
+ * Removes an EntityPlayerMP from the PlayerManager.
+ */
+ public void removePlayer(EntityPlayerMP par1EntityPlayerMP) {
+ int var2 = (int) par1EntityPlayerMP.managedPosX >> 4;
+ int var3 = (int) par1EntityPlayerMP.managedPosZ >> 4;
+
+ int rd = par1EntityPlayerMP.lastRenderDistance;
+ for (int var4 = var2 - rd; var4 <= var2 + rd; ++var4) {
+ for (int var5 = var3 - rd; var5 <= var3 + rd; ++var5) {
+ PlayerInstance var6 = this.getPlayerInstance(var4, var5, false);
+
+ if (var6 != null) {
+ var6.removePlayer(par1EntityPlayerMP);
+ // long var7 = ((long) var4 + 2147483647L) | (((long) var5 + 2147483647L) << 32);
+ // this.freePlayerInstance(var7);
+ }
+ }
+ }
+ par1EntityPlayerMP.lastRenderDistance = par1EntityPlayerMP.renderDistance;
+
+ this.players.remove(par1EntityPlayerMP);
+ }
+
+ private boolean func_72684_a(int par1, int par2, int par3, int par4, int par5) {
+ int var6 = par1 - par3;
+ int var7 = par2 - par4;
+ return var6 >= -par5 && var6 <= par5 ? var7 >= -par5 && var7 <= par5 : false;
+ }
+
+ /**
+ * update chunks around a player being moved by server logic (e.g. cart, boat)
+ */
+ public void updateMountedMovingPlayer(EntityPlayerMP par1EntityPlayerMP) {
+ if(par1EntityPlayerMP.renderDistance != par1EntityPlayerMP.lastRenderDistance) {
+ cycleRenderDistance(par1EntityPlayerMP);
+ }
+ int var2 = (int) par1EntityPlayerMP.posX >> 4;
+ int var3 = (int) par1EntityPlayerMP.posZ >> 4;
+ double var4 = par1EntityPlayerMP.managedPosX - par1EntityPlayerMP.posX;
+ double var6 = par1EntityPlayerMP.managedPosZ - par1EntityPlayerMP.posZ;
+ double var8 = var4 * var4 + var6 * var6;
+
+ if (var8 >= 64.0D) {
+ int var10 = (int) par1EntityPlayerMP.managedPosX >> 4;
+ int var11 = (int) par1EntityPlayerMP.managedPosZ >> 4;
+ int var12 = par1EntityPlayerMP.renderDistance;
+ int var13 = var2 - var10;
+ int var14 = var3 - var11;
+
+ if (var13 != 0 || var14 != 0) {
+ for (int var15 = var2 - var12; var15 <= var2 + var12; ++var15) {
+ for (int var16 = var3 - var12; var16 <= var3 + var12; ++var16) {
+ if (!this.func_72684_a(var15, var16, var10, var11, var12)) {
+ this.getPlayerInstance(var15, var16, true).addPlayer(par1EntityPlayerMP);
+ }
+
+ if (!this.func_72684_a(var15 - var13, var16 - var14, var2, var3, var12)) {
+ PlayerInstance var17 = this.getPlayerInstance(var15 - var13, var16 - var14, false);
+
+ if (var17 != null) {
+ var17.removePlayer(par1EntityPlayerMP);
+ }
+ }
+ }
+ }
+
+ this.filterChunkLoadQueue(par1EntityPlayerMP);
+ par1EntityPlayerMP.managedPosX = par1EntityPlayerMP.posX;
+ par1EntityPlayerMP.managedPosZ = par1EntityPlayerMP.posZ;
+ }
+ }
+ }
+
+ public boolean isPlayerWatchingChunk(EntityPlayerMP par1EntityPlayerMP, int par2, int par3) {
+ PlayerInstance var4 = this.getPlayerInstance(par2, par3, false);
+ return var4 == null ? false
+ : PlayerInstance.getPlayersInChunk(var4).contains(par1EntityPlayerMP)
+ && !par1EntityPlayerMP.loadedChunks.contains(PlayerInstance.getChunkLocation(var4));
+ }
+
+ /**
+ * Get the furthest viewable block given player's view distance
+ */
+ public static int getFurthestViewableBlock(int par0) {
+ return par0 * 16 - 16;
+ }
+
+ static WorldServer getWorldServer(PlayerManager par0PlayerManager) {
+ return par0PlayerManager.theWorldServer;
+ }
+
+ static LongHashMap getChunkWatchers(PlayerManager par0PlayerManager) {
+ return par0PlayerManager.playerInstances;
+ }
+
+ static List getChunkWatchersWithPlayers(PlayerManager par0PlayerManager) {
+ return par0PlayerManager.playerInstancesToUpdate;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/PlayerNotFoundException.java b/sp-server/src/main/java/net/minecraft/src/PlayerNotFoundException.java
new file mode 100644
index 0000000..f078172
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/PlayerNotFoundException.java
@@ -0,0 +1,11 @@
+package net.minecraft.src;
+
+public class PlayerNotFoundException extends CommandException {
+ public PlayerNotFoundException() {
+ this("commands.generic.player.notFound", new Object[0]);
+ }
+
+ public PlayerNotFoundException(String par1Str, Object... par2ArrayOfObj) {
+ super(par1Str, par2ArrayOfObj);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/PlayerPositionComparator.java b/sp-server/src/main/java/net/minecraft/src/PlayerPositionComparator.java
new file mode 100644
index 0000000..923eeaa
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/PlayerPositionComparator.java
@@ -0,0 +1,26 @@
+package net.minecraft.src;
+
+import java.util.Comparator;
+
+public class PlayerPositionComparator implements Comparator {
+ private final ChunkCoordinates theChunkCoordinates;
+
+ public PlayerPositionComparator(ChunkCoordinates par1ChunkCoordinates) {
+ this.theChunkCoordinates = par1ChunkCoordinates;
+ }
+
+ /**
+ * Compare the position of two players.
+ */
+ public int comparePlayers(EntityPlayerMP par1EntityPlayerMP, EntityPlayerMP par2EntityPlayerMP) {
+ double var3 = par1EntityPlayerMP.getDistanceSq((double) this.theChunkCoordinates.posX,
+ (double) this.theChunkCoordinates.posY, (double) this.theChunkCoordinates.posZ);
+ double var5 = par2EntityPlayerMP.getDistanceSq((double) this.theChunkCoordinates.posX,
+ (double) this.theChunkCoordinates.posY, (double) this.theChunkCoordinates.posZ);
+ return var3 < var5 ? -1 : (var3 > var5 ? 1 : 0);
+ }
+
+ public int compare(Object par1Obj, Object par2Obj) {
+ return this.comparePlayers((EntityPlayerMP) par1Obj, (EntityPlayerMP) par2Obj);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/PlayerSelector.java b/sp-server/src/main/java/net/minecraft/src/PlayerSelector.java
new file mode 100644
index 0000000..147f84e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/PlayerSelector.java
@@ -0,0 +1,292 @@
+package net.minecraft.src;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import net.minecraft.server.MinecraftServer;
+
+public class PlayerSelector {
+ /**
+ * This matches the at-tokens introduced for command blocks, including their
+ * arguments, if any.
+ */
+ private static final Pattern tokenPattern = Pattern.compile("^@([parf])(?:\\[([\\w=,!-]*)\\])?$");
+
+ /**
+ * This matches things like "-1,,4", and is used for getting x,y,z,range from
+ * the token's argument list.
+ */
+ private static final Pattern intListPattern = Pattern.compile("\\G([-!]?\\w*)(?:$|,)");
+
+ /**
+ * This matches things like "rm=4,c=2" and is used for handling named token
+ * arguments.
+ */
+ private static final Pattern keyValueListPattern = Pattern.compile("\\G(\\w+)=([-!]?\\w*)(?:$|,)");
+
+ /**
+ * Returns the one player that matches the given at-token. Returns null if more
+ * than one player matches.
+ */
+ public static EntityPlayerMP matchOnePlayer(ICommandSender par0ICommandSender, String par1Str) {
+ EntityPlayerMP[] var2 = matchPlayers(par0ICommandSender, par1Str);
+ return var2 != null && var2.length == 1 ? var2[0] : null;
+ }
+
+ /**
+ * Returns a nicely-formatted string listing the matching players.
+ */
+ public static String matchPlayersAsString(ICommandSender par0ICommandSender, String par1Str) {
+ EntityPlayerMP[] var2 = matchPlayers(par0ICommandSender, par1Str);
+
+ if (var2 != null && var2.length != 0) {
+ String[] var3 = new String[var2.length];
+
+ for (int var4 = 0; var4 < var3.length; ++var4) {
+ var3[var4] = var2[var4].getTranslatedEntityName();
+ }
+
+ return CommandBase.joinNiceString(var3);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Returns an array of all players matched by the given at-token.
+ */
+ public static EntityPlayerMP[] matchPlayers(ICommandSender par0ICommandSender, String par1Str) {
+ Matcher var2 = tokenPattern.matcher(par1Str);
+
+ if (var2.matches()) {
+ Map var3 = getArgumentMap(var2.group(2));
+ String var4 = var2.group(1);
+ int var5 = getDefaultMinimumRange(var4);
+ int var6 = getDefaultMaximumRange(var4);
+ int var7 = getDefaultMinimumLevel(var4);
+ int var8 = getDefaultMaximumLevel(var4);
+ int var9 = getDefaultCount(var4);
+ int var10 = EnumGameType.NOT_SET.getID();
+ ChunkCoordinates var11 = par0ICommandSender.getCommandSenderPosition();
+ Map var12 = func_96560_a(var3);
+ String var13 = null;
+ String var14 = null;
+
+ if (var3.containsKey("rm")) {
+ var5 = MathHelper.parseIntWithDefault((String) var3.get("rm"), var5);
+ }
+
+ if (var3.containsKey("r")) {
+ var6 = MathHelper.parseIntWithDefault((String) var3.get("r"), var6);
+ }
+
+ if (var3.containsKey("lm")) {
+ var7 = MathHelper.parseIntWithDefault((String) var3.get("lm"), var7);
+ }
+
+ if (var3.containsKey("l")) {
+ var8 = MathHelper.parseIntWithDefault((String) var3.get("l"), var8);
+ }
+
+ if (var3.containsKey("x")) {
+ var11.posX = MathHelper.parseIntWithDefault((String) var3.get("x"), var11.posX);
+ }
+
+ if (var3.containsKey("y")) {
+ var11.posY = MathHelper.parseIntWithDefault((String) var3.get("y"), var11.posY);
+ }
+
+ if (var3.containsKey("z")) {
+ var11.posZ = MathHelper.parseIntWithDefault((String) var3.get("z"), var11.posZ);
+ }
+
+ if (var3.containsKey("m")) {
+ var10 = MathHelper.parseIntWithDefault((String) var3.get("m"), var10);
+ }
+
+ if (var3.containsKey("c")) {
+ var9 = MathHelper.parseIntWithDefault((String) var3.get("c"), var9);
+ }
+
+ if (var3.containsKey("team")) {
+ var14 = (String) var3.get("team");
+ }
+
+ if (var3.containsKey("name")) {
+ var13 = (String) var3.get("name");
+ }
+
+ List var15;
+
+ if (!var4.equals("p") && !var4.equals("a")) {
+ if (!var4.equals("r")) {
+ return null;
+ } else {
+ var15 = MinecraftServer.getServer().getConfigurationManager().findPlayers(var11, var5, var6, 0,
+ var10, var7, var8, var12, var13, var14);
+ Collections.shuffle(var15);
+ var15 = var15.subList(0, Math.min(var9, var15.size()));
+ return var15 != null && !var15.isEmpty() ? (EntityPlayerMP[]) var15.toArray(new EntityPlayerMP[0])
+ : new EntityPlayerMP[0];
+ }
+ } else {
+ var15 = MinecraftServer.getServer().getConfigurationManager().findPlayers(var11, var5, var6, var9,
+ var10, var7, var8, var12, var13, var14);
+ return var15 != null && !var15.isEmpty() ? (EntityPlayerMP[]) var15.toArray(new EntityPlayerMP[0])
+ : new EntityPlayerMP[0];
+ }
+ } else {
+ return null;
+ }
+ }
+
+ public static Map func_96560_a(Map par0Map) {
+ HashMap var1 = new HashMap();
+ Iterator var2 = par0Map.keySet().iterator();
+
+ while (var2.hasNext()) {
+ String var3 = (String) var2.next();
+
+ if (var3.startsWith("score_") && var3.length() > "score_".length()) {
+ String var4 = var3.substring("score_".length());
+ var1.put(var4, Integer.valueOf(MathHelper.parseIntWithDefault((String) par0Map.get(var3), 1)));
+ }
+ }
+
+ return var1;
+ }
+
+ /**
+ * Returns whether the given pattern can match more than one player.
+ */
+ public static boolean matchesMultiplePlayers(String par0Str) {
+ Matcher var1 = tokenPattern.matcher(par0Str);
+
+ if (var1.matches()) {
+ Map var2 = getArgumentMap(var1.group(2));
+ String var3 = var1.group(1);
+ int var4 = getDefaultCount(var3);
+
+ if (var2.containsKey("c")) {
+ var4 = MathHelper.parseIntWithDefault((String) var2.get("c"), var4);
+ }
+
+ return var4 != 1;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Returns whether the given token (parameter 1) has exactly the given arguments
+ * (parameter 2).
+ */
+ public static boolean hasTheseArguments(String par0Str, String par1Str) {
+ Matcher var2 = tokenPattern.matcher(par0Str);
+
+ if (var2.matches()) {
+ String var3 = var2.group(1);
+ return par1Str == null || par1Str.equals(var3);
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Returns whether the given token has any arguments set.
+ */
+ public static boolean hasArguments(String par0Str) {
+ return hasTheseArguments(par0Str, (String) null);
+ }
+
+ /**
+ * Gets the default minimum range (argument rm).
+ */
+ private static final int getDefaultMinimumRange(String par0Str) {
+ return 0;
+ }
+
+ /**
+ * Gets the default maximum range (argument r).
+ */
+ private static final int getDefaultMaximumRange(String par0Str) {
+ return 0;
+ }
+
+ /**
+ * Gets the default maximum experience level (argument l)
+ */
+ private static final int getDefaultMaximumLevel(String par0Str) {
+ return Integer.MAX_VALUE;
+ }
+
+ /**
+ * Gets the default minimum experience level (argument lm)
+ */
+ private static final int getDefaultMinimumLevel(String par0Str) {
+ return 0;
+ }
+
+ /**
+ * Gets the default number of players to return (argument c, 0 for infinite)
+ */
+ private static final int getDefaultCount(String par0Str) {
+ return par0Str.equals("a") ? 0 : 1;
+ }
+
+ /**
+ * Parses the given argument string, turning it into a HashMap<String,
+ * String> of name->value.
+ */
+ private static Map getArgumentMap(String par0Str) {
+ HashMap var1 = new HashMap();
+
+ if (par0Str == null) {
+ return var1;
+ } else {
+ Matcher var2 = intListPattern.matcher(par0Str);
+ int var3 = 0;
+ int var4;
+
+ for (var4 = -1; var2.find(); var4 = var2.end()) {
+ String var5 = null;
+
+ switch (var3++) {
+ case 0:
+ var5 = "x";
+ break;
+
+ case 1:
+ var5 = "y";
+ break;
+
+ case 2:
+ var5 = "z";
+ break;
+
+ case 3:
+ var5 = "r";
+ }
+
+ if (var5 != null && var2.group(1).length() > 0) {
+ var1.put(var5, var2.group(1));
+ }
+ }
+
+ if (var4 < par0Str.length()) {
+ var2 = keyValueListPattern.matcher(var4 == -1 ? par0Str : par0Str.substring(var4));
+
+ while (var2.find()) {
+ var1.put(var2.group(1), var2.group(2));
+ }
+ }
+
+ return var1;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/PortalPosition.java b/sp-server/src/main/java/net/minecraft/src/PortalPosition.java
new file mode 100644
index 0000000..0d728f2
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/PortalPosition.java
@@ -0,0 +1,15 @@
+package net.minecraft.src;
+
+public class PortalPosition extends ChunkCoordinates {
+ /** The worldtime at which this PortalPosition was last verified */
+ public long lastUpdateTime;
+
+ /** The teleporter to which this PortalPosition applies */
+ final Teleporter teleporterInstance;
+
+ public PortalPosition(Teleporter par1Teleporter, int par2, int par3, int par4, long par5) {
+ super(par2, par3, par4);
+ this.teleporterInstance = par1Teleporter;
+ this.lastUpdateTime = par5;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/PositionImpl.java b/sp-server/src/main/java/net/minecraft/src/PositionImpl.java
new file mode 100644
index 0000000..e0ca181
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/PositionImpl.java
@@ -0,0 +1,25 @@
+package net.minecraft.src;
+
+public class PositionImpl implements IPosition {
+ protected final double x;
+ protected final double y;
+ protected final double z;
+
+ public PositionImpl(double par1, double par3, double par5) {
+ this.x = par1;
+ this.y = par3;
+ this.z = par5;
+ }
+
+ public double getX() {
+ return this.x;
+ }
+
+ public double getY() {
+ return this.y;
+ }
+
+ public double getZ() {
+ return this.z;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Potion.java b/sp-server/src/main/java/net/minecraft/src/Potion.java
new file mode 100644
index 0000000..52a37cc
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Potion.java
@@ -0,0 +1,235 @@
+package net.minecraft.src;
+
+public class Potion {
+ /** The array of potion types. */
+ public static final Potion[] potionTypes = new Potion[32];
+ public static final Potion field_76423_b = null;
+ public static final Potion moveSpeed = (new Potion(1, false, 8171462)).setPotionName("potion.moveSpeed")
+ .setIconIndex(0, 0);
+ public static final Potion moveSlowdown = (new Potion(2, true, 5926017)).setPotionName("potion.moveSlowdown")
+ .setIconIndex(1, 0);
+ public static final Potion digSpeed = (new Potion(3, false, 14270531)).setPotionName("potion.digSpeed")
+ .setIconIndex(2, 0).setEffectiveness(1.5D);
+ public static final Potion digSlowdown = (new Potion(4, true, 4866583)).setPotionName("potion.digSlowDown")
+ .setIconIndex(3, 0);
+ public static final Potion damageBoost = (new Potion(5, false, 9643043)).setPotionName("potion.damageBoost")
+ .setIconIndex(4, 0);
+ public static final Potion heal = (new PotionHealth(6, false, 16262179)).setPotionName("potion.heal");
+ public static final Potion harm = (new PotionHealth(7, true, 4393481)).setPotionName("potion.harm");
+ public static final Potion jump = (new Potion(8, false, 7889559)).setPotionName("potion.jump").setIconIndex(2, 1);
+ public static final Potion confusion = (new Potion(9, true, 5578058)).setPotionName("potion.confusion")
+ .setIconIndex(3, 1).setEffectiveness(0.25D);
+
+ /** The regeneration Potion object. */
+ public static final Potion regeneration = (new Potion(10, false, 13458603)).setPotionName("potion.regeneration")
+ .setIconIndex(7, 0).setEffectiveness(0.25D);
+ public static final Potion resistance = (new Potion(11, false, 10044730)).setPotionName("potion.resistance")
+ .setIconIndex(6, 1);
+
+ /** The fire resistance Potion object. */
+ public static final Potion fireResistance = (new Potion(12, false, 14981690)).setPotionName("potion.fireResistance")
+ .setIconIndex(7, 1);
+
+ /** The water breathing Potion object. */
+ public static final Potion waterBreathing = (new Potion(13, false, 3035801)).setPotionName("potion.waterBreathing")
+ .setIconIndex(0, 2);
+
+ /** The invisibility Potion object. */
+ public static final Potion invisibility = (new Potion(14, false, 8356754)).setPotionName("potion.invisibility")
+ .setIconIndex(0, 1);
+
+ /** The blindness Potion object. */
+ public static final Potion blindness = (new Potion(15, true, 2039587)).setPotionName("potion.blindness")
+ .setIconIndex(5, 1).setEffectiveness(0.25D);
+
+ /** The night vision Potion object. */
+ public static final Potion nightVision = (new Potion(16, false, 2039713)).setPotionName("potion.nightVision")
+ .setIconIndex(4, 1);
+
+ /** The hunger Potion object. */
+ public static final Potion hunger = (new Potion(17, true, 5797459)).setPotionName("potion.hunger").setIconIndex(1,
+ 1);
+
+ /** The weakness Potion object. */
+ public static final Potion weakness = (new Potion(18, true, 4738376)).setPotionName("potion.weakness")
+ .setIconIndex(5, 0);
+
+ /** The poison Potion object. */
+ public static final Potion poison = (new Potion(19, true, 5149489)).setPotionName("potion.poison")
+ .setIconIndex(6, 0).setEffectiveness(0.25D);
+
+ /** The wither Potion object. */
+ public static final Potion wither = (new Potion(20, true, 3484199)).setPotionName("potion.wither")
+ .setIconIndex(1, 2).setEffectiveness(0.25D);
+ public static final Potion field_76434_w = null;
+ public static final Potion field_76444_x = null;
+ public static final Potion field_76443_y = null;
+ public static final Potion field_76442_z = null;
+ public static final Potion field_76409_A = null;
+ public static final Potion field_76410_B = null;
+ public static final Potion field_76411_C = null;
+ public static final Potion field_76405_D = null;
+ public static final Potion field_76406_E = null;
+ public static final Potion field_76407_F = null;
+ public static final Potion field_76408_G = null;
+
+ /** The Id of a Potion object. */
+ public final int id;
+
+ /** The name of the Potion. */
+ private String name = "";
+
+ /** The index for the icon displayed when the potion effect is active. */
+ private int statusIconIndex = -1;
+
+ /**
+ * This field indicated if the effect is 'bad' - negative - for the entity.
+ */
+ private final boolean isBadEffect;
+ private double effectiveness;
+ private boolean usable;
+
+ /** Is the color of the liquid for this potion. */
+ private final int liquidColor;
+
+ protected Potion(int par1, boolean par2, int par3) {
+ this.id = par1;
+ potionTypes[par1] = this;
+ this.isBadEffect = par2;
+
+ if (par2) {
+ this.effectiveness = 0.5D;
+ } else {
+ this.effectiveness = 1.0D;
+ }
+
+ this.liquidColor = par3;
+ }
+
+ /**
+ * Sets the index for the icon displayed in the player's inventory when the
+ * status is active.
+ */
+ protected Potion setIconIndex(int par1, int par2) {
+ this.statusIconIndex = par1 + par2 * 8;
+ return this;
+ }
+
+ /**
+ * returns the ID of the potion
+ */
+ public int getId() {
+ return this.id;
+ }
+
+ public void performEffect(EntityLiving par1EntityLiving, int par2) {
+ if (this.id == regeneration.id) {
+ if (par1EntityLiving.getHealth() < par1EntityLiving.getMaxHealth()) {
+ par1EntityLiving.heal(1);
+ }
+ } else if (this.id == poison.id) {
+ if (par1EntityLiving.getHealth() > 1) {
+ par1EntityLiving.attackEntityFrom(DamageSource.magic, 1);
+ }
+ } else if (this.id == wither.id) {
+ par1EntityLiving.attackEntityFrom(DamageSource.wither, 1);
+ } else if (this.id == hunger.id && par1EntityLiving instanceof EntityPlayer) {
+ ((EntityPlayer) par1EntityLiving).addExhaustion(0.025F * (float) (par2 + 1));
+ } else if ((this.id != heal.id || par1EntityLiving.isEntityUndead())
+ && (this.id != harm.id || !par1EntityLiving.isEntityUndead())) {
+ if (this.id == harm.id && !par1EntityLiving.isEntityUndead()
+ || this.id == heal.id && par1EntityLiving.isEntityUndead()) {
+ par1EntityLiving.attackEntityFrom(DamageSource.magic, 6 << par2);
+ }
+ } else {
+ par1EntityLiving.heal(6 << par2);
+ }
+ }
+
+ /**
+ * Hits the provided entity with this potion's instant effect.
+ */
+ public void affectEntity(EntityLiving par1EntityLiving, EntityLiving par2EntityLiving, int par3, double par4) {
+ int var6;
+
+ if ((this.id != heal.id || par2EntityLiving.isEntityUndead())
+ && (this.id != harm.id || !par2EntityLiving.isEntityUndead())) {
+ if (this.id == harm.id && !par2EntityLiving.isEntityUndead()
+ || this.id == heal.id && par2EntityLiving.isEntityUndead()) {
+ var6 = (int) (par4 * (double) (6 << par3) + 0.5D);
+
+ if (par1EntityLiving == null) {
+ par2EntityLiving.attackEntityFrom(DamageSource.magic, var6);
+ } else {
+ par2EntityLiving.attackEntityFrom(
+ DamageSource.causeIndirectMagicDamage(par2EntityLiving, par1EntityLiving), var6);
+ }
+ }
+ } else {
+ var6 = (int) (par4 * (double) (6 << par3) + 0.5D);
+ par2EntityLiving.heal(var6);
+ }
+ }
+
+ /**
+ * Returns true if the potion has an instant effect instead of a continuous one
+ * (eg Harming)
+ */
+ public boolean isInstant() {
+ return false;
+ }
+
+ /**
+ * checks if Potion effect is ready to be applied this tick.
+ */
+ public boolean isReady(int par1, int par2) {
+ int var3;
+
+ if (this.id != regeneration.id && this.id != poison.id) {
+ if (this.id == wither.id) {
+ var3 = 40 >> par2;
+ return var3 > 0 ? par1 % var3 == 0 : true;
+ } else {
+ return this.id == hunger.id;
+ }
+ } else {
+ var3 = 25 >> par2;
+ return var3 > 0 ? par1 % var3 == 0 : true;
+ }
+ }
+
+ /**
+ * Set the potion name.
+ */
+ public Potion setPotionName(String par1Str) {
+ this.name = par1Str;
+ return this;
+ }
+
+ /**
+ * returns the name of the potion
+ */
+ public String getName() {
+ return this.name;
+ }
+
+ protected Potion setEffectiveness(double par1) {
+ this.effectiveness = par1;
+ return this;
+ }
+
+ public double getEffectiveness() {
+ return this.effectiveness;
+ }
+
+ public boolean isUsable() {
+ return this.usable;
+ }
+
+ /**
+ * Returns the color of the potion liquid.
+ */
+ public int getLiquidColor() {
+ return this.liquidColor;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/PotionEffect.java b/sp-server/src/main/java/net/minecraft/src/PotionEffect.java
new file mode 100644
index 0000000..16495e7
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/PotionEffect.java
@@ -0,0 +1,170 @@
+package net.minecraft.src;
+
+public class PotionEffect {
+ /** ID value of the potion this effect matches. */
+ private int potionID;
+
+ /** The duration of the potion effect */
+ private int duration;
+
+ /** The amplifier of the potion effect */
+ private int amplifier;
+
+ /** Whether the potion is a splash potion */
+ private boolean isSplashPotion;
+
+ /** Whether the potion effect came from a beacon */
+ private boolean isAmbient;
+
+ public PotionEffect(int par1, int par2) {
+ this(par1, par2, 0);
+ }
+
+ public PotionEffect(int par1, int par2, int par3) {
+ this(par1, par2, par3, false);
+ }
+
+ public PotionEffect(int par1, int par2, int par3, boolean par4) {
+ this.potionID = par1;
+ this.duration = par2;
+ this.amplifier = par3;
+ this.isAmbient = par4;
+ }
+
+ public PotionEffect(PotionEffect par1PotionEffect) {
+ this.potionID = par1PotionEffect.potionID;
+ this.duration = par1PotionEffect.duration;
+ this.amplifier = par1PotionEffect.amplifier;
+ }
+
+ /**
+ * merges the input PotionEffect into this one if this.amplifier <=
+ * tomerge.amplifier. The duration in the supplied potion effect is assumed to
+ * be greater.
+ */
+ public void combine(PotionEffect par1PotionEffect) {
+ if (this.potionID != par1PotionEffect.potionID) {
+ System.err.println("This method should only be called for matching effects!");
+ }
+
+ if (par1PotionEffect.amplifier > this.amplifier) {
+ this.amplifier = par1PotionEffect.amplifier;
+ this.duration = par1PotionEffect.duration;
+ } else if (par1PotionEffect.amplifier == this.amplifier && this.duration < par1PotionEffect.duration) {
+ this.duration = par1PotionEffect.duration;
+ } else if (!par1PotionEffect.isAmbient && this.isAmbient) {
+ this.isAmbient = par1PotionEffect.isAmbient;
+ }
+ }
+
+ /**
+ * Retrieve the ID of the potion this effect matches.
+ */
+ public int getPotionID() {
+ return this.potionID;
+ }
+
+ public int getDuration() {
+ return this.duration;
+ }
+
+ public int getAmplifier() {
+ return this.amplifier;
+ }
+
+ public boolean isSplashPotionEffect() {
+ return this.isSplashPotion;
+ }
+
+ /**
+ * Set whether this potion is a splash potion.
+ */
+ public void setSplashPotion(boolean par1) {
+ this.isSplashPotion = par1;
+ }
+
+ /**
+ * Gets whether this potion effect originated from a beacon
+ */
+ public boolean getIsAmbient() {
+ return this.isAmbient;
+ }
+
+ public boolean onUpdate(EntityLiving par1EntityLiving) {
+ if (this.duration > 0) {
+ if (Potion.potionTypes[this.potionID].isReady(this.duration, this.amplifier)) {
+ this.performEffect(par1EntityLiving);
+ }
+
+ this.deincrementDuration();
+ }
+
+ return this.duration > 0;
+ }
+
+ private int deincrementDuration() {
+ return --this.duration;
+ }
+
+ public void performEffect(EntityLiving par1EntityLiving) {
+ if (this.duration > 0) {
+ Potion.potionTypes[this.potionID].performEffect(par1EntityLiving, this.amplifier);
+ }
+ }
+
+ public String getEffectName() {
+ return Potion.potionTypes[this.potionID].getName();
+ }
+
+ public int hashCode() {
+ return this.potionID;
+ }
+
+ public String toString() {
+ String var1 = "";
+
+ if (this.getAmplifier() > 0) {
+ var1 = this.getEffectName() + " x " + (this.getAmplifier() + 1) + ", Duration: " + this.getDuration();
+ } else {
+ var1 = this.getEffectName() + ", Duration: " + this.getDuration();
+ }
+
+ if (this.isSplashPotion) {
+ var1 = var1 + ", Splash: true";
+ }
+
+ return Potion.potionTypes[this.potionID].isUsable() ? "(" + var1 + ")" : var1;
+ }
+
+ public boolean equals(Object par1Obj) {
+ if (!(par1Obj instanceof PotionEffect)) {
+ return false;
+ } else {
+ PotionEffect var2 = (PotionEffect) par1Obj;
+ return this.potionID == var2.potionID && this.amplifier == var2.amplifier && this.duration == var2.duration
+ && this.isSplashPotion == var2.isSplashPotion && this.isAmbient == var2.isAmbient;
+ }
+ }
+
+ /**
+ * Write a custom potion effect to a potion item's NBT data.
+ */
+ public NBTTagCompound writeCustomPotionEffectToNBT(NBTTagCompound par1NBTTagCompound) {
+ par1NBTTagCompound.setByte("Id", (byte) this.getPotionID());
+ par1NBTTagCompound.setByte("Amplifier", (byte) this.getAmplifier());
+ par1NBTTagCompound.setInteger("Duration", this.getDuration());
+ par1NBTTagCompound.setBoolean("Ambient", this.getIsAmbient());
+ return par1NBTTagCompound;
+ }
+
+ /**
+ * Read a custom potion effect from a potion item's NBT data.
+ */
+ public static PotionEffect readCustomPotionEffectFromNBT(NBTTagCompound par0NBTTagCompound) {
+ byte var1 = par0NBTTagCompound.getByte("Id");
+ byte var2 = par0NBTTagCompound.getByte("Amplifier");
+ int var3 = par0NBTTagCompound.getInteger("Duration");
+ boolean var4 = par0NBTTagCompound.getBoolean("Ambient");
+ return new PotionEffect(var1, var3, var2, var4);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/PotionHealth.java b/sp-server/src/main/java/net/minecraft/src/PotionHealth.java
new file mode 100644
index 0000000..f9d60e3
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/PotionHealth.java
@@ -0,0 +1,22 @@
+package net.minecraft.src;
+
+public class PotionHealth extends Potion {
+ public PotionHealth(int par1, boolean par2, int par3) {
+ super(par1, par2, par3);
+ }
+
+ /**
+ * Returns true if the potion has an instant effect instead of a continuous one
+ * (eg Harming)
+ */
+ public boolean isInstant() {
+ return true;
+ }
+
+ /**
+ * checks if Potion effect is ready to be applied this tick.
+ */
+ public boolean isReady(int par1, int par2) {
+ return par1 >= 1;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/PotionHelper.java b/sp-server/src/main/java/net/minecraft/src/PotionHelper.java
new file mode 100644
index 0000000..f171ac1
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/PotionHelper.java
@@ -0,0 +1,481 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+public class PotionHelper {
+ public static final String field_77924_a = null;
+ public static final String sugarEffect;
+ public static final String ghastTearEffect = "+0-1-2-3&4-4+13";
+ public static final String spiderEyeEffect;
+ public static final String fermentedSpiderEyeEffect;
+ public static final String speckledMelonEffect;
+ public static final String blazePowderEffect;
+ public static final String magmaCreamEffect;
+ public static final String redstoneEffect;
+ public static final String glowstoneEffect;
+ public static final String gunpowderEffect;
+ public static final String goldenCarrotEffect;
+ private static final HashMap potionRequirements = new HashMap();
+
+ /** Potion effect amplifier map */
+ private static final HashMap potionAmplifiers = new HashMap();
+ private static final HashMap field_77925_n;
+
+ /** An array of possible potion prefix names, as translation IDs. */
+ private static final String[] potionPrefixes;
+
+ /**
+ * Checks if the bit at 1 << j is on in i.
+ */
+ public static boolean checkFlag(int par0, int par1) {
+ return (par0 & 1 << par1) != 0;
+ }
+
+ /**
+ * Returns 1 if the flag is set, 0 if it is not set.
+ */
+ private static int isFlagSet(int par0, int par1) {
+ return checkFlag(par0, par1) ? 1 : 0;
+ }
+
+ /**
+ * Returns 0 if the flag is set, 1 if it is not set.
+ */
+ private static int isFlagUnset(int par0, int par1) {
+ return checkFlag(par0, par1) ? 0 : 1;
+ }
+
+ public static int func_77909_a(int par0) {
+ return func_77908_a(par0, 5, 4, 3, 2, 1);
+ }
+
+ /**
+ * Given a {@link Collection}<{@link PotionEffect}> will return an Integer
+ * color.
+ */
+ public static int calcPotionLiquidColor(Collection par0Collection) {
+ int var1 = 3694022;
+
+ if (par0Collection != null && !par0Collection.isEmpty()) {
+ float var2 = 0.0F;
+ float var3 = 0.0F;
+ float var4 = 0.0F;
+ float var5 = 0.0F;
+ Iterator var6 = par0Collection.iterator();
+
+ while (var6.hasNext()) {
+ PotionEffect var7 = (PotionEffect) var6.next();
+ int var8 = Potion.potionTypes[var7.getPotionID()].getLiquidColor();
+
+ for (int var9 = 0; var9 <= var7.getAmplifier(); ++var9) {
+ var2 += (float) (var8 >> 16 & 255) / 255.0F;
+ var3 += (float) (var8 >> 8 & 255) / 255.0F;
+ var4 += (float) (var8 >> 0 & 255) / 255.0F;
+ ++var5;
+ }
+ }
+
+ var2 = var2 / var5 * 255.0F;
+ var3 = var3 / var5 * 255.0F;
+ var4 = var4 / var5 * 255.0F;
+ return (int) var2 << 16 | (int) var3 << 8 | (int) var4;
+ } else {
+ return var1;
+ }
+ }
+
+ public static boolean func_82817_b(Collection par0Collection) {
+ Iterator var1 = par0Collection.iterator();
+ PotionEffect var2;
+
+ do {
+ if (!var1.hasNext()) {
+ return true;
+ }
+
+ var2 = (PotionEffect) var1.next();
+ } while (var2.getIsAmbient());
+
+ return false;
+ }
+
+ public static String func_77905_c(int par0) {
+ int var1 = func_77909_a(par0);
+ return potionPrefixes[var1];
+ }
+
+ private static int func_77904_a(boolean par0, boolean par1, boolean par2, int par3, int par4, int par5, int par6) {
+ int var7 = 0;
+
+ if (par0) {
+ var7 = isFlagUnset(par6, par4);
+ } else if (par3 != -1) {
+ if (par3 == 0 && countSetFlags(par6) == par4) {
+ var7 = 1;
+ } else if (par3 == 1 && countSetFlags(par6) > par4) {
+ var7 = 1;
+ } else if (par3 == 2 && countSetFlags(par6) < par4) {
+ var7 = 1;
+ }
+ } else {
+ var7 = isFlagSet(par6, par4);
+ }
+
+ if (par1) {
+ var7 *= par5;
+ }
+
+ if (par2) {
+ var7 *= -1;
+ }
+
+ return var7;
+ }
+
+ /**
+ * Returns the number of 1 bits in the given integer.
+ */
+ private static int countSetFlags(int par0) {
+ int var1;
+
+ for (var1 = 0; par0 > 0; ++var1) {
+ par0 &= par0 - 1;
+ }
+
+ return var1;
+ }
+
+ private static int parsePotionEffects(String par0Str, int par1, int par2, int par3) {
+ if (par1 < par0Str.length() && par2 >= 0 && par1 < par2) {
+ int var4 = par0Str.indexOf(124, par1);
+ int var5;
+ int var17;
+
+ if (var4 >= 0 && var4 < par2) {
+ var5 = parsePotionEffects(par0Str, par1, var4 - 1, par3);
+
+ if (var5 > 0) {
+ return var5;
+ } else {
+ var17 = parsePotionEffects(par0Str, var4 + 1, par2, par3);
+ return var17 > 0 ? var17 : 0;
+ }
+ } else {
+ var5 = par0Str.indexOf(38, par1);
+
+ if (var5 >= 0 && var5 < par2) {
+ var17 = parsePotionEffects(par0Str, par1, var5 - 1, par3);
+
+ if (var17 <= 0) {
+ return 0;
+ } else {
+ int var18 = parsePotionEffects(par0Str, var5 + 1, par2, par3);
+ return var18 <= 0 ? 0 : (var17 > var18 ? var17 : var18);
+ }
+ } else {
+ boolean var6 = false;
+ boolean var7 = false;
+ boolean var8 = false;
+ boolean var9 = false;
+ boolean var10 = false;
+ byte var11 = -1;
+ int var12 = 0;
+ int var13 = 0;
+ int var14 = 0;
+
+ for (int var15 = par1; var15 < par2; ++var15) {
+ char var16 = par0Str.charAt(var15);
+
+ if (var16 >= 48 && var16 <= 57) {
+ if (var6) {
+ var13 = var16 - 48;
+ var7 = true;
+ } else {
+ var12 *= 10;
+ var12 += var16 - 48;
+ var8 = true;
+ }
+ } else if (var16 == 42) {
+ var6 = true;
+ } else if (var16 == 33) {
+ if (var8) {
+ var14 += func_77904_a(var9, var7, var10, var11, var12, var13, par3);
+ var9 = false;
+ var10 = false;
+ var6 = false;
+ var7 = false;
+ var8 = false;
+ var13 = 0;
+ var12 = 0;
+ var11 = -1;
+ }
+
+ var9 = true;
+ } else if (var16 == 45) {
+ if (var8) {
+ var14 += func_77904_a(var9, var7, var10, var11, var12, var13, par3);
+ var9 = false;
+ var10 = false;
+ var6 = false;
+ var7 = false;
+ var8 = false;
+ var13 = 0;
+ var12 = 0;
+ var11 = -1;
+ }
+
+ var10 = true;
+ } else if (var16 != 61 && var16 != 60 && var16 != 62) {
+ if (var16 == 43 && var8) {
+ var14 += func_77904_a(var9, var7, var10, var11, var12, var13, par3);
+ var9 = false;
+ var10 = false;
+ var6 = false;
+ var7 = false;
+ var8 = false;
+ var13 = 0;
+ var12 = 0;
+ var11 = -1;
+ }
+ } else {
+ if (var8) {
+ var14 += func_77904_a(var9, var7, var10, var11, var12, var13, par3);
+ var9 = false;
+ var10 = false;
+ var6 = false;
+ var7 = false;
+ var8 = false;
+ var13 = 0;
+ var12 = 0;
+ var11 = -1;
+ }
+
+ if (var16 == 61) {
+ var11 = 0;
+ } else if (var16 == 60) {
+ var11 = 2;
+ } else if (var16 == 62) {
+ var11 = 1;
+ }
+ }
+ }
+
+ if (var8) {
+ var14 += func_77904_a(var9, var7, var10, var11, var12, var13, par3);
+ }
+
+ return var14;
+ }
+ }
+ } else {
+ return 0;
+ }
+ }
+
+ /**
+ * Returns a list of effects for the specified potion damage value.
+ */
+ public static List getPotionEffects(int par0, boolean par1) {
+ ArrayList var2 = null;
+ Potion[] var3 = Potion.potionTypes;
+ int var4 = var3.length;
+
+ for (int var5 = 0; var5 < var4; ++var5) {
+ Potion var6 = var3[var5];
+
+ if (var6 != null && (!var6.isUsable() || par1)) {
+ String var7 = (String) potionRequirements.get(Integer.valueOf(var6.getId()));
+
+ if (var7 != null) {
+ int var8 = parsePotionEffects(var7, 0, var7.length(), par0);
+
+ if (var8 > 0) {
+ int var9 = 0;
+ String var10 = (String) potionAmplifiers.get(Integer.valueOf(var6.getId()));
+
+ if (var10 != null) {
+ var9 = parsePotionEffects(var10, 0, var10.length(), par0);
+
+ if (var9 < 0) {
+ var9 = 0;
+ }
+ }
+
+ if (var6.isInstant()) {
+ var8 = 1;
+ } else {
+ var8 = 1200 * (var8 * 3 + (var8 - 1) * 2);
+ var8 >>= var9;
+ var8 = (int) Math.round((double) var8 * var6.getEffectiveness());
+
+ if ((par0 & 16384) != 0) {
+ var8 = (int) Math.round((double) var8 * 0.75D + 0.5D);
+ }
+ }
+
+ if (var2 == null) {
+ var2 = new ArrayList();
+ }
+
+ PotionEffect var11 = new PotionEffect(var6.getId(), var8, var9);
+
+ if ((par0 & 16384) != 0) {
+ var11.setSplashPotion(true);
+ }
+
+ var2.add(var11);
+ }
+ }
+ }
+ }
+
+ return var2;
+ }
+
+ /**
+ * Manipulates the specified bit of the potion damage value according to the
+ * rules passed from applyIngredient.
+ */
+ private static int brewBitOperations(int par0, int par1, boolean par2, boolean par3, boolean par4) {
+ if (par4) {
+ if (!checkFlag(par0, par1)) {
+ return 0;
+ }
+ } else if (par2) {
+ par0 &= ~(1 << par1);
+ } else if (par3) {
+ if ((par0 & 1 << par1) == 0) {
+ par0 |= 1 << par1;
+ } else {
+ par0 &= ~(1 << par1);
+ }
+ } else {
+ par0 |= 1 << par1;
+ }
+
+ return par0;
+ }
+
+ /**
+ * Returns the new potion damage value after the specified ingredient info is
+ * applied to the specified potion.
+ */
+ public static int applyIngredient(int par0, String par1Str) {
+ byte var2 = 0;
+ int var3 = par1Str.length();
+ boolean var4 = false;
+ boolean var5 = false;
+ boolean var6 = false;
+ boolean var7 = false;
+ int var8 = 0;
+
+ for (int var9 = var2; var9 < var3; ++var9) {
+ char var10 = par1Str.charAt(var9);
+
+ if (var10 >= 48 && var10 <= 57) {
+ var8 *= 10;
+ var8 += var10 - 48;
+ var4 = true;
+ } else if (var10 == 33) {
+ if (var4) {
+ par0 = brewBitOperations(par0, var8, var6, var5, var7);
+ var7 = false;
+ var5 = false;
+ var6 = false;
+ var4 = false;
+ var8 = 0;
+ }
+
+ var5 = true;
+ } else if (var10 == 45) {
+ if (var4) {
+ par0 = brewBitOperations(par0, var8, var6, var5, var7);
+ var7 = false;
+ var5 = false;
+ var6 = false;
+ var4 = false;
+ var8 = 0;
+ }
+
+ var6 = true;
+ } else if (var10 == 43) {
+ if (var4) {
+ par0 = brewBitOperations(par0, var8, var6, var5, var7);
+ var7 = false;
+ var5 = false;
+ var6 = false;
+ var4 = false;
+ var8 = 0;
+ }
+ } else if (var10 == 38) {
+ if (var4) {
+ par0 = brewBitOperations(par0, var8, var6, var5, var7);
+ var7 = false;
+ var5 = false;
+ var6 = false;
+ var4 = false;
+ var8 = 0;
+ }
+
+ var7 = true;
+ }
+ }
+
+ if (var4) {
+ par0 = brewBitOperations(par0, var8, var6, var5, var7);
+ }
+
+ return par0 & 32767;
+ }
+
+ public static int func_77908_a(int par0, int par1, int par2, int par3, int par4, int par5) {
+ return (checkFlag(par0, par1) ? 16 : 0) | (checkFlag(par0, par2) ? 8 : 0) | (checkFlag(par0, par3) ? 4 : 0)
+ | (checkFlag(par0, par4) ? 2 : 0) | (checkFlag(par0, par5) ? 1 : 0);
+ }
+
+ static {
+ potionRequirements.put(Integer.valueOf(Potion.regeneration.getId()), "0 & !1 & !2 & !3 & 0+6");
+ sugarEffect = "-0+1-2-3&4-4+13";
+ potionRequirements.put(Integer.valueOf(Potion.moveSpeed.getId()), "!0 & 1 & !2 & !3 & 1+6");
+ magmaCreamEffect = "+0+1-2-3&4-4+13";
+ potionRequirements.put(Integer.valueOf(Potion.fireResistance.getId()), "0 & 1 & !2 & !3 & 0+6");
+ speckledMelonEffect = "+0-1+2-3&4-4+13";
+ potionRequirements.put(Integer.valueOf(Potion.heal.getId()), "0 & !1 & 2 & !3");
+ spiderEyeEffect = "-0-1+2-3&4-4+13";
+ potionRequirements.put(Integer.valueOf(Potion.poison.getId()), "!0 & !1 & 2 & !3 & 2+6");
+ fermentedSpiderEyeEffect = "-0+3-4+13";
+ potionRequirements.put(Integer.valueOf(Potion.weakness.getId()), "!0 & !1 & !2 & 3 & 3+6");
+ potionRequirements.put(Integer.valueOf(Potion.harm.getId()), "!0 & !1 & 2 & 3");
+ potionRequirements.put(Integer.valueOf(Potion.moveSlowdown.getId()), "!0 & 1 & !2 & 3 & 3+6");
+ blazePowderEffect = "+0-1-2+3&4-4+13";
+ potionRequirements.put(Integer.valueOf(Potion.damageBoost.getId()), "0 & !1 & !2 & 3 & 3+6");
+ goldenCarrotEffect = "-0+1+2-3+13&4-4";
+ potionRequirements.put(Integer.valueOf(Potion.nightVision.getId()), "!0 & 1 & 2 & !3 & 2+6");
+ potionRequirements.put(Integer.valueOf(Potion.invisibility.getId()), "!0 & 1 & 2 & 3 & 2+6");
+ glowstoneEffect = "+5-6-7";
+ potionAmplifiers.put(Integer.valueOf(Potion.moveSpeed.getId()), "5");
+ potionAmplifiers.put(Integer.valueOf(Potion.digSpeed.getId()), "5");
+ potionAmplifiers.put(Integer.valueOf(Potion.damageBoost.getId()), "5");
+ potionAmplifiers.put(Integer.valueOf(Potion.regeneration.getId()), "5");
+ potionAmplifiers.put(Integer.valueOf(Potion.harm.getId()), "5");
+ potionAmplifiers.put(Integer.valueOf(Potion.heal.getId()), "5");
+ potionAmplifiers.put(Integer.valueOf(Potion.resistance.getId()), "5");
+ potionAmplifiers.put(Integer.valueOf(Potion.poison.getId()), "5");
+ redstoneEffect = "-5+6-7";
+ gunpowderEffect = "+14&13-13";
+ field_77925_n = new HashMap();
+ potionPrefixes = new String[] { "potion.prefix.mundane", "potion.prefix.uninteresting", "potion.prefix.bland",
+ "potion.prefix.clear", "potion.prefix.milky", "potion.prefix.diffuse", "potion.prefix.artless",
+ "potion.prefix.thin", "potion.prefix.awkward", "potion.prefix.flat", "potion.prefix.bulky",
+ "potion.prefix.bungling", "potion.prefix.buttered", "potion.prefix.smooth", "potion.prefix.suave",
+ "potion.prefix.debonair", "potion.prefix.thick", "potion.prefix.elegant", "potion.prefix.fancy",
+ "potion.prefix.charming", "potion.prefix.dashing", "potion.prefix.refined", "potion.prefix.cordial",
+ "potion.prefix.sparkling", "potion.prefix.potent", "potion.prefix.foul", "potion.prefix.odorless",
+ "potion.prefix.rank", "potion.prefix.harsh", "potion.prefix.acrid", "potion.prefix.gross",
+ "potion.prefix.stinky" };
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/PropertyManager.java b/sp-server/src/main/java/net/minecraft/src/PropertyManager.java
new file mode 100644
index 0000000..d02f6ef
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/PropertyManager.java
@@ -0,0 +1,129 @@
+package net.minecraft.src;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Properties;
+
+public class PropertyManager {
+ /** The server properties object. */
+ private final Properties serverProperties = new Properties();
+
+ /** Reference to the logger. */
+ private final ILogAgent logger;
+
+ /** The server properties file. */
+ private final File serverPropertiesFile;
+
+ public PropertyManager(File par1File, ILogAgent par2ILogAgent) {
+ this.serverPropertiesFile = par1File;
+ this.logger = par2ILogAgent;
+
+ if (par1File.exists()) {
+ FileInputStream var3 = null;
+
+ try {
+ var3 = new FileInputStream(par1File);
+ this.serverProperties.load(var3);
+ } catch (Exception var13) {
+ par2ILogAgent.logWarningException("Failed to load " + par1File, var13);
+ this.generateNewProperties();
+ } finally {
+ if (var3 != null) {
+ try {
+ var3.close();
+ } catch (IOException var12) {
+ ;
+ }
+ }
+ }
+ } else {
+ par2ILogAgent.func_98236_b(par1File + " does not exist");
+ this.generateNewProperties();
+ }
+ }
+
+ /**
+ * Generates a new properties file.
+ */
+ public void generateNewProperties() {
+ this.logger.func_98233_a("Generating new properties file");
+ this.saveProperties();
+ }
+
+ /**
+ * Writes the properties to the properties file.
+ */
+ public void saveProperties() {
+ FileOutputStream var1 = null;
+
+ try {
+ var1 = new FileOutputStream(this.serverPropertiesFile);
+ this.serverProperties.store(var1, "Minecraft server properties");
+ } catch (Exception var11) {
+ this.logger.logWarningException("Failed to save " + this.serverPropertiesFile, var11);
+ this.generateNewProperties();
+ } finally {
+ if (var1 != null) {
+ try {
+ var1.close();
+ } catch (IOException var10) {
+ ;
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns this PropertyManager's file object used for property saving.
+ */
+ public File getPropertiesFile() {
+ return this.serverPropertiesFile;
+ }
+
+ /**
+ * Returns a string property. If the property doesn't exist the default is
+ * returned.
+ */
+ public String getStringProperty(String par1Str, String par2Str) {
+ if (!this.serverProperties.containsKey(par1Str)) {
+ this.serverProperties.setProperty(par1Str, par2Str);
+ this.saveProperties();
+ }
+
+ return this.serverProperties.getProperty(par1Str, par2Str);
+ }
+
+ /**
+ * Gets an integer property. If it does not exist, set it to the specified
+ * value.
+ */
+ public int getIntProperty(String par1Str, int par2) {
+ try {
+ return Integer.parseInt(this.getStringProperty(par1Str, "" + par2));
+ } catch (Exception var4) {
+ this.serverProperties.setProperty(par1Str, "" + par2);
+ return par2;
+ }
+ }
+
+ /**
+ * Gets a boolean property. If it does not exist, set it to the specified value.
+ */
+ public boolean getBooleanProperty(String par1Str, boolean par2) {
+ try {
+ return Boolean.parseBoolean(this.getStringProperty(par1Str, "" + par2));
+ } catch (Exception var4) {
+ this.serverProperties.setProperty(par1Str, "" + par2);
+ return par2;
+ }
+ }
+
+ /**
+ * Saves an Object with the given property name.
+ */
+ public void setProperty(String par1Str, Object par2Obj) {
+ this.serverProperties.setProperty(par1Str, "" + par2Obj);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/RandomPositionGenerator.java b/sp-server/src/main/java/net/minecraft/src/RandomPositionGenerator.java
new file mode 100644
index 0000000..ac47653
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/RandomPositionGenerator.java
@@ -0,0 +1,99 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class RandomPositionGenerator {
+ /**
+ * used to store a driection when the user passes a point to move towards or
+ * away from. WARNING: NEVER THREAD SAFE. MULTIPLE findTowards and findAway
+ * calls, will share this var
+ */
+ private static Vec3 staticVector = Vec3.createVectorHelper(0.0D, 0.0D, 0.0D);
+
+ /**
+ * finds a random target within par1(x,z) and par2 (y) blocks
+ */
+ public static Vec3 findRandomTarget(EntityCreature par0EntityCreature, int par1, int par2) {
+ return findRandomTargetBlock(par0EntityCreature, par1, par2, (Vec3) null);
+ }
+
+ /**
+ * finds a random target within par1(x,z) and par2 (y) blocks in the direction
+ * of the point par3
+ */
+ public static Vec3 findRandomTargetBlockTowards(EntityCreature par0EntityCreature, int par1, int par2,
+ Vec3 par3Vec3) {
+ staticVector.xCoord = par3Vec3.xCoord - par0EntityCreature.posX;
+ staticVector.yCoord = par3Vec3.yCoord - par0EntityCreature.posY;
+ staticVector.zCoord = par3Vec3.zCoord - par0EntityCreature.posZ;
+ return findRandomTargetBlock(par0EntityCreature, par1, par2, staticVector);
+ }
+
+ /**
+ * finds a random target within par1(x,z) and par2 (y) blocks in the reverse
+ * direction of the point par3
+ */
+ public static Vec3 findRandomTargetBlockAwayFrom(EntityCreature par0EntityCreature, int par1, int par2,
+ Vec3 par3Vec3) {
+ staticVector.xCoord = par0EntityCreature.posX - par3Vec3.xCoord;
+ staticVector.yCoord = par0EntityCreature.posY - par3Vec3.yCoord;
+ staticVector.zCoord = par0EntityCreature.posZ - par3Vec3.zCoord;
+ return findRandomTargetBlock(par0EntityCreature, par1, par2, staticVector);
+ }
+
+ /**
+ * searches 10 blocks at random in a within par1(x,z) and par2 (y) distance,
+ * ignores those not in the direction of par3Vec3, then points to the tile for
+ * which creature.getBlockPathWeight returns the highest number
+ */
+ private static Vec3 findRandomTargetBlock(EntityCreature par0EntityCreature, int par1, int par2, Vec3 par3Vec3) {
+ EaglercraftRandom var4 = par0EntityCreature.getRNG();
+ boolean var5 = false;
+ int var6 = 0;
+ int var7 = 0;
+ int var8 = 0;
+ float var9 = -99999.0F;
+ boolean var10;
+
+ if (par0EntityCreature.hasHome()) {
+ double var11 = (double) (par0EntityCreature.getHomePosition().getDistanceSquared(
+ MathHelper.floor_double(par0EntityCreature.posX), MathHelper.floor_double(par0EntityCreature.posY),
+ MathHelper.floor_double(par0EntityCreature.posZ)) + 4.0F);
+ double var13 = (double) (par0EntityCreature.getMaximumHomeDistance() + (float) par1);
+ var10 = var11 < var13 * var13;
+ } else {
+ var10 = false;
+ }
+
+ for (int var16 = 0; var16 < 10; ++var16) {
+ int var12 = var4.nextInt(2 * par1) - par1;
+ int var17 = var4.nextInt(2 * par2) - par2;
+ int var14 = var4.nextInt(2 * par1) - par1;
+
+ if (par3Vec3 == null || (double) var12 * par3Vec3.xCoord + (double) var14 * par3Vec3.zCoord >= 0.0D) {
+ var12 += MathHelper.floor_double(par0EntityCreature.posX);
+ var17 += MathHelper.floor_double(par0EntityCreature.posY);
+ var14 += MathHelper.floor_double(par0EntityCreature.posZ);
+
+ if (!var10 || par0EntityCreature.isWithinHomeDistance(var12, var17, var14)) {
+ float var15 = par0EntityCreature.getBlockPathWeight(var12, var17, var14);
+
+ if (var15 > var9) {
+ var9 = var15;
+ var6 = var12;
+ var7 = var17;
+ var8 = var14;
+ var5 = true;
+ }
+ }
+ }
+ }
+
+ if (var5) {
+ return par0EntityCreature.worldObj.getWorldVec3Pool().getVecFromPool((double) var6, (double) var7,
+ (double) var8);
+ } else {
+ return null;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/RecipeFireworks.java b/sp-server/src/main/java/net/minecraft/src/RecipeFireworks.java
new file mode 100644
index 0000000..f1299c9
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/RecipeFireworks.java
@@ -0,0 +1,181 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+
+public class RecipeFireworks implements IRecipe {
+ private ItemStack field_92102_a;
+
+ /**
+ * Used to check if a recipe matches current crafting inventory
+ */
+ public boolean matches(InventoryCrafting par1InventoryCrafting, World par2World) {
+ this.field_92102_a = null;
+ int var3 = 0;
+ int var4 = 0;
+ int var5 = 0;
+ int var6 = 0;
+ int var7 = 0;
+ int var8 = 0;
+
+ for (int var9 = 0; var9 < par1InventoryCrafting.getSizeInventory(); ++var9) {
+ ItemStack var10 = par1InventoryCrafting.getStackInSlot(var9);
+
+ if (var10 != null) {
+ if (var10.itemID == Item.gunpowder.itemID) {
+ ++var4;
+ } else if (var10.itemID == Item.fireworkCharge.itemID) {
+ ++var6;
+ } else if (var10.itemID == Item.dyePowder.itemID) {
+ ++var5;
+ } else if (var10.itemID == Item.paper.itemID) {
+ ++var3;
+ } else if (var10.itemID == Item.lightStoneDust.itemID) {
+ ++var7;
+ } else if (var10.itemID == Item.diamond.itemID) {
+ ++var7;
+ } else if (var10.itemID == Item.fireballCharge.itemID) {
+ ++var8;
+ } else if (var10.itemID == Item.feather.itemID) {
+ ++var8;
+ } else if (var10.itemID == Item.goldNugget.itemID) {
+ ++var8;
+ } else {
+ if (var10.itemID != Item.skull.itemID) {
+ return false;
+ }
+
+ ++var8;
+ }
+ }
+ }
+
+ var7 += var5 + var8;
+
+ if (var4 <= 3 && var3 <= 1) {
+ NBTTagCompound var16;
+ NBTTagCompound var19;
+
+ if (var4 >= 1 && var3 == 1 && var7 == 0) {
+ this.field_92102_a = new ItemStack(Item.firework);
+
+ if (var6 > 0) {
+ var16 = new NBTTagCompound();
+ var19 = new NBTTagCompound("Fireworks");
+ NBTTagList var25 = new NBTTagList("Explosions");
+
+ for (int var22 = 0; var22 < par1InventoryCrafting.getSizeInventory(); ++var22) {
+ ItemStack var26 = par1InventoryCrafting.getStackInSlot(var22);
+
+ if (var26 != null && var26.itemID == Item.fireworkCharge.itemID && var26.hasTagCompound()
+ && var26.getTagCompound().hasKey("Explosion")) {
+ var25.appendTag(var26.getTagCompound().getCompoundTag("Explosion"));
+ }
+ }
+
+ var19.setTag("Explosions", var25);
+ var19.setByte("Flight", (byte) var4);
+ var16.setTag("Fireworks", var19);
+ this.field_92102_a.setTagCompound(var16);
+ }
+
+ return true;
+ } else if (var4 == 1 && var3 == 0 && var6 == 0 && var5 > 0 && var8 <= 1) {
+ this.field_92102_a = new ItemStack(Item.fireworkCharge);
+ var16 = new NBTTagCompound();
+ var19 = new NBTTagCompound("Explosion");
+ byte var23 = 0;
+ ArrayList var12 = new ArrayList();
+
+ for (int var13 = 0; var13 < par1InventoryCrafting.getSizeInventory(); ++var13) {
+ ItemStack var14 = par1InventoryCrafting.getStackInSlot(var13);
+
+ if (var14 != null) {
+ if (var14.itemID == Item.dyePowder.itemID) {
+ var12.add(Integer.valueOf(ItemDye.dyeColors[var14.getItemDamage()]));
+ } else if (var14.itemID == Item.lightStoneDust.itemID) {
+ var19.setBoolean("Flicker", true);
+ } else if (var14.itemID == Item.diamond.itemID) {
+ var19.setBoolean("Trail", true);
+ } else if (var14.itemID == Item.fireballCharge.itemID) {
+ var23 = 1;
+ } else if (var14.itemID == Item.feather.itemID) {
+ var23 = 4;
+ } else if (var14.itemID == Item.goldNugget.itemID) {
+ var23 = 2;
+ } else if (var14.itemID == Item.skull.itemID) {
+ var23 = 3;
+ }
+ }
+ }
+
+ int[] var24 = new int[var12.size()];
+
+ for (int var27 = 0; var27 < var24.length; ++var27) {
+ var24[var27] = ((Integer) var12.get(var27)).intValue();
+ }
+
+ var19.setIntArray("Colors", var24);
+ var19.setByte("Type", var23);
+ var16.setTag("Explosion", var19);
+ this.field_92102_a.setTagCompound(var16);
+ return true;
+ } else if (var4 == 0 && var3 == 0 && var6 == 1 && var5 > 0 && var5 == var7) {
+ ArrayList var15 = new ArrayList();
+
+ for (int var17 = 0; var17 < par1InventoryCrafting.getSizeInventory(); ++var17) {
+ ItemStack var11 = par1InventoryCrafting.getStackInSlot(var17);
+
+ if (var11 != null) {
+ if (var11.itemID == Item.dyePowder.itemID) {
+ var15.add(Integer.valueOf(ItemDye.dyeColors[var11.getItemDamage()]));
+ } else if (var11.itemID == Item.fireworkCharge.itemID) {
+ this.field_92102_a = var11.copy();
+ this.field_92102_a.stackSize = 1;
+ }
+ }
+ }
+
+ int[] var18 = new int[var15.size()];
+
+ for (int var20 = 0; var20 < var18.length; ++var20) {
+ var18[var20] = ((Integer) var15.get(var20)).intValue();
+ }
+
+ if (this.field_92102_a != null && this.field_92102_a.hasTagCompound()) {
+ NBTTagCompound var21 = this.field_92102_a.getTagCompound().getCompoundTag("Explosion");
+
+ if (var21 == null) {
+ return false;
+ } else {
+ var21.setIntArray("FadeColors", var18);
+ return true;
+ }
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Returns an Item that is the result of this recipe
+ */
+ public ItemStack getCraftingResult(InventoryCrafting par1InventoryCrafting) {
+ return this.field_92102_a.copy();
+ }
+
+ /**
+ * Returns the size of the recipe area
+ */
+ public int getRecipeSize() {
+ return 10;
+ }
+
+ public ItemStack getRecipeOutput() {
+ return this.field_92102_a;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/RecipeSorter.java b/sp-server/src/main/java/net/minecraft/src/RecipeSorter.java
new file mode 100644
index 0000000..e658db9
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/RecipeSorter.java
@@ -0,0 +1,22 @@
+package net.minecraft.src;
+
+import java.util.Comparator;
+
+class RecipeSorter implements Comparator {
+ final CraftingManager craftingManager;
+
+ RecipeSorter(CraftingManager par1CraftingManager) {
+ this.craftingManager = par1CraftingManager;
+ }
+
+ public int compareRecipes(IRecipe par1IRecipe, IRecipe par2IRecipe) {
+ return par1IRecipe instanceof ShapelessRecipes && par2IRecipe instanceof ShapedRecipes ? 1
+ : (par2IRecipe instanceof ShapelessRecipes && par1IRecipe instanceof ShapedRecipes ? -1
+ : (par2IRecipe.getRecipeSize() < par1IRecipe.getRecipeSize() ? -1
+ : (par2IRecipe.getRecipeSize() > par1IRecipe.getRecipeSize() ? 1 : 0)));
+ }
+
+ public int compare(Object par1Obj, Object par2Obj) {
+ return this.compareRecipes((IRecipe) par1Obj, (IRecipe) par2Obj);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/RecipesArmor.java b/sp-server/src/main/java/net/minecraft/src/RecipesArmor.java
new file mode 100644
index 0000000..eabd48b
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/RecipesArmor.java
@@ -0,0 +1,30 @@
+package net.minecraft.src;
+
+public class RecipesArmor {
+ private String[][] recipePatterns = new String[][] { { "XXX", "X X" }, { "X X", "XXX", "XXX" },
+ { "XXX", "X X", "X X" }, { "X X", "X X" } };
+ private Object[][] recipeItems;
+
+ public RecipesArmor() {
+ this.recipeItems = new Object[][] { { Item.leather, Block.fire, Item.ingotIron, Item.diamond, Item.ingotGold },
+ { Item.helmetLeather, Item.helmetChain, Item.helmetIron, Item.helmetDiamond, Item.helmetGold },
+ { Item.plateLeather, Item.plateChain, Item.plateIron, Item.plateDiamond, Item.plateGold },
+ { Item.legsLeather, Item.legsChain, Item.legsIron, Item.legsDiamond, Item.legsGold },
+ { Item.bootsLeather, Item.bootsChain, Item.bootsIron, Item.bootsDiamond, Item.bootsGold } };
+ }
+
+ /**
+ * Adds the armor recipes to the CraftingManager.
+ */
+ public void addRecipes(CraftingManager par1CraftingManager) {
+ for (int var2 = 0; var2 < this.recipeItems[0].length; ++var2) {
+ Object var3 = this.recipeItems[0][var2];
+
+ for (int var4 = 0; var4 < this.recipeItems.length - 1; ++var4) {
+ Item var5 = (Item) this.recipeItems[var4 + 1][var2];
+ par1CraftingManager.addRecipe(new ItemStack(var5),
+ new Object[] { this.recipePatterns[var4], 'X', var3 });
+ }
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/RecipesArmorDyes.java b/sp-server/src/main/java/net/minecraft/src/RecipesArmorDyes.java
new file mode 100644
index 0000000..0bf202b
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/RecipesArmorDyes.java
@@ -0,0 +1,124 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+
+public class RecipesArmorDyes implements IRecipe {
+ /**
+ * Used to check if a recipe matches current crafting inventory
+ */
+ public boolean matches(InventoryCrafting par1InventoryCrafting, World par2World) {
+ ItemStack var3 = null;
+ ArrayList var4 = new ArrayList();
+
+ for (int var5 = 0; var5 < par1InventoryCrafting.getSizeInventory(); ++var5) {
+ ItemStack var6 = par1InventoryCrafting.getStackInSlot(var5);
+
+ if (var6 != null) {
+ if (var6.getItem() instanceof ItemArmor) {
+ ItemArmor var7 = (ItemArmor) var6.getItem();
+
+ if (var7.getArmorMaterial() != EnumArmorMaterial.CLOTH || var3 != null) {
+ return false;
+ }
+
+ var3 = var6;
+ } else {
+ if (var6.itemID != Item.dyePowder.itemID) {
+ return false;
+ }
+
+ var4.add(var6);
+ }
+ }
+ }
+
+ return var3 != null && !var4.isEmpty();
+ }
+
+ /**
+ * Returns an Item that is the result of this recipe
+ */
+ public ItemStack getCraftingResult(InventoryCrafting par1InventoryCrafting) {
+ ItemStack var2 = null;
+ int[] var3 = new int[3];
+ int var4 = 0;
+ int var5 = 0;
+ ItemArmor var6 = null;
+ int var7;
+ int var9;
+ float var10;
+ float var11;
+ int var17;
+
+ for (var7 = 0; var7 < par1InventoryCrafting.getSizeInventory(); ++var7) {
+ ItemStack var8 = par1InventoryCrafting.getStackInSlot(var7);
+
+ if (var8 != null) {
+ if (var8.getItem() instanceof ItemArmor) {
+ var6 = (ItemArmor) var8.getItem();
+
+ if (var6.getArmorMaterial() != EnumArmorMaterial.CLOTH || var2 != null) {
+ return null;
+ }
+
+ var2 = var8.copy();
+ var2.stackSize = 1;
+
+ if (var6.hasColor(var8)) {
+ var9 = var6.getColor(var2);
+ var10 = (float) (var9 >> 16 & 255) / 255.0F;
+ var11 = (float) (var9 >> 8 & 255) / 255.0F;
+ float var12 = (float) (var9 & 255) / 255.0F;
+ var4 = (int) ((float) var4 + Math.max(var10, Math.max(var11, var12)) * 255.0F);
+ var3[0] = (int) ((float) var3[0] + var10 * 255.0F);
+ var3[1] = (int) ((float) var3[1] + var11 * 255.0F);
+ var3[2] = (int) ((float) var3[2] + var12 * 255.0F);
+ ++var5;
+ }
+ } else {
+ if (var8.itemID != Item.dyePowder.itemID) {
+ return null;
+ }
+
+ float[] var14 = EntitySheep.fleeceColorTable[BlockCloth.getBlockFromDye(var8.getItemDamage())];
+ int var15 = (int) (var14[0] * 255.0F);
+ int var16 = (int) (var14[1] * 255.0F);
+ var17 = (int) (var14[2] * 255.0F);
+ var4 += Math.max(var15, Math.max(var16, var17));
+ var3[0] += var15;
+ var3[1] += var16;
+ var3[2] += var17;
+ ++var5;
+ }
+ }
+ }
+
+ if (var6 == null) {
+ return null;
+ } else {
+ var7 = var3[0] / var5;
+ int var13 = var3[1] / var5;
+ var9 = var3[2] / var5;
+ var10 = (float) var4 / (float) var5;
+ var11 = (float) Math.max(var7, Math.max(var13, var9));
+ var7 = (int) ((float) var7 * var10 / var11);
+ var13 = (int) ((float) var13 * var10 / var11);
+ var9 = (int) ((float) var9 * var10 / var11);
+ var17 = (var7 << 8) + var13;
+ var17 = (var17 << 8) + var9;
+ var6.func_82813_b(var2, var17);
+ return var2;
+ }
+ }
+
+ /**
+ * Returns the size of the recipe area
+ */
+ public int getRecipeSize() {
+ return 10;
+ }
+
+ public ItemStack getRecipeOutput() {
+ return null;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/RecipesCrafting.java b/sp-server/src/main/java/net/minecraft/src/RecipesCrafting.java
new file mode 100644
index 0000000..1910997
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/RecipesCrafting.java
@@ -0,0 +1,39 @@
+package net.minecraft.src;
+
+public class RecipesCrafting {
+ /**
+ * Adds the crafting recipes to the CraftingManager.
+ */
+ public void addRecipes(CraftingManager par1CraftingManager) {
+ par1CraftingManager.addRecipe(new ItemStack(Block.chest),
+ new Object[] { "###", "# #", "###", '#', Block.planks });
+ par1CraftingManager.addRecipe(new ItemStack(Block.chestTrapped),
+ new Object[] { "#-", '#', Block.chest, '-', Block.tripWireSource });
+ par1CraftingManager.addRecipe(new ItemStack(Block.enderChest),
+ new Object[] { "###", "#E#", "###", '#', Block.obsidian, 'E', Item.eyeOfEnder });
+ par1CraftingManager.addRecipe(new ItemStack(Block.furnaceIdle),
+ new Object[] { "###", "# #", "###", '#', Block.cobblestone });
+ par1CraftingManager.addRecipe(new ItemStack(Block.workbench), new Object[] { "##", "##", '#', Block.planks });
+ par1CraftingManager.addRecipe(new ItemStack(Block.sandStone), new Object[] { "##", "##", '#', Block.sand });
+ par1CraftingManager.addRecipe(new ItemStack(Block.sandStone, 4, 2),
+ new Object[] { "##", "##", '#', Block.sandStone });
+ par1CraftingManager.addRecipe(new ItemStack(Block.sandStone, 1, 1),
+ new Object[] { "#", "#", '#', new ItemStack(Block.stoneSingleSlab, 1, 1) });
+ par1CraftingManager.addRecipe(new ItemStack(Block.blockNetherQuartz, 1, 1),
+ new Object[] { "#", "#", '#', new ItemStack(Block.stoneSingleSlab, 1, 7) });
+ par1CraftingManager.addRecipe(new ItemStack(Block.blockNetherQuartz, 2, 2),
+ new Object[] { "#", "#", '#', new ItemStack(Block.blockNetherQuartz, 1, 0) });
+ par1CraftingManager.addRecipe(new ItemStack(Block.stoneBrick, 4),
+ new Object[] { "##", "##", '#', Block.stone });
+ par1CraftingManager.addRecipe(new ItemStack(Block.fenceIron, 16),
+ new Object[] { "###", "###", '#', Item.ingotIron });
+ par1CraftingManager.addRecipe(new ItemStack(Block.thinGlass, 16),
+ new Object[] { "###", "###", '#', Block.glass });
+ par1CraftingManager.addRecipe(new ItemStack(Block.redstoneLampIdle, 1),
+ new Object[] { " R ", "RGR", " R ", 'R', Item.redstone, 'G', Block.glowStone });
+ par1CraftingManager.addRecipe(new ItemStack(Block.beacon, 1),
+ new Object[] { "GGG", "GSG", "OOO", 'G', Block.glass, 'S', Item.netherStar, 'O', Block.obsidian });
+ par1CraftingManager.addRecipe(new ItemStack(Block.netherBrick, 1),
+ new Object[] { "NN", "NN", 'N', Item.netherrackBrick });
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/RecipesDyes.java b/sp-server/src/main/java/net/minecraft/src/RecipesDyes.java
new file mode 100644
index 0000000..d9213ad
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/RecipesDyes.java
@@ -0,0 +1,46 @@
+package net.minecraft.src;
+
+public class RecipesDyes {
+ /**
+ * Adds the dye recipes to the CraftingManager.
+ */
+ public void addRecipes(CraftingManager par1CraftingManager) {
+ for (int var2 = 0; var2 < 16; ++var2) {
+ par1CraftingManager.addShapelessRecipe(new ItemStack(Block.cloth, 1, BlockCloth.getDyeFromBlock(var2)),
+ new Object[] { new ItemStack(Item.dyePowder, 1, var2),
+ new ItemStack(Item.itemsList[Block.cloth.blockID], 1, 0) });
+ }
+
+ par1CraftingManager.addShapelessRecipe(new ItemStack(Item.dyePowder, 2, 11),
+ new Object[] { Block.plantYellow });
+ par1CraftingManager.addShapelessRecipe(new ItemStack(Item.dyePowder, 2, 1), new Object[] { Block.plantRed });
+ par1CraftingManager.addShapelessRecipe(new ItemStack(Item.dyePowder, 3, 15), new Object[] { Item.bone });
+ par1CraftingManager.addShapelessRecipe(new ItemStack(Item.dyePowder, 2, 9),
+ new Object[] { new ItemStack(Item.dyePowder, 1, 1), new ItemStack(Item.dyePowder, 1, 15) });
+ par1CraftingManager.addShapelessRecipe(new ItemStack(Item.dyePowder, 2, 14),
+ new Object[] { new ItemStack(Item.dyePowder, 1, 1), new ItemStack(Item.dyePowder, 1, 11) });
+ par1CraftingManager.addShapelessRecipe(new ItemStack(Item.dyePowder, 2, 10),
+ new Object[] { new ItemStack(Item.dyePowder, 1, 2), new ItemStack(Item.dyePowder, 1, 15) });
+ par1CraftingManager.addShapelessRecipe(new ItemStack(Item.dyePowder, 2, 8),
+ new Object[] { new ItemStack(Item.dyePowder, 1, 0), new ItemStack(Item.dyePowder, 1, 15) });
+ par1CraftingManager.addShapelessRecipe(new ItemStack(Item.dyePowder, 2, 7),
+ new Object[] { new ItemStack(Item.dyePowder, 1, 8), new ItemStack(Item.dyePowder, 1, 15) });
+ par1CraftingManager.addShapelessRecipe(new ItemStack(Item.dyePowder, 3, 7),
+ new Object[] { new ItemStack(Item.dyePowder, 1, 0), new ItemStack(Item.dyePowder, 1, 15),
+ new ItemStack(Item.dyePowder, 1, 15) });
+ par1CraftingManager.addShapelessRecipe(new ItemStack(Item.dyePowder, 2, 12),
+ new Object[] { new ItemStack(Item.dyePowder, 1, 4), new ItemStack(Item.dyePowder, 1, 15) });
+ par1CraftingManager.addShapelessRecipe(new ItemStack(Item.dyePowder, 2, 6),
+ new Object[] { new ItemStack(Item.dyePowder, 1, 4), new ItemStack(Item.dyePowder, 1, 2) });
+ par1CraftingManager.addShapelessRecipe(new ItemStack(Item.dyePowder, 2, 5),
+ new Object[] { new ItemStack(Item.dyePowder, 1, 4), new ItemStack(Item.dyePowder, 1, 1) });
+ par1CraftingManager.addShapelessRecipe(new ItemStack(Item.dyePowder, 2, 13),
+ new Object[] { new ItemStack(Item.dyePowder, 1, 5), new ItemStack(Item.dyePowder, 1, 9) });
+ par1CraftingManager.addShapelessRecipe(new ItemStack(Item.dyePowder, 3, 13),
+ new Object[] { new ItemStack(Item.dyePowder, 1, 4), new ItemStack(Item.dyePowder, 1, 1),
+ new ItemStack(Item.dyePowder, 1, 9) });
+ par1CraftingManager.addShapelessRecipe(new ItemStack(Item.dyePowder, 4, 13),
+ new Object[] { new ItemStack(Item.dyePowder, 1, 4), new ItemStack(Item.dyePowder, 1, 1),
+ new ItemStack(Item.dyePowder, 1, 1), new ItemStack(Item.dyePowder, 1, 15) });
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/RecipesFood.java b/sp-server/src/main/java/net/minecraft/src/RecipesFood.java
new file mode 100644
index 0000000..baa11a7
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/RecipesFood.java
@@ -0,0 +1,26 @@
+package net.minecraft.src;
+
+public class RecipesFood {
+ /**
+ * Adds the food recipes to the CraftingManager.
+ */
+ public void addRecipes(CraftingManager par1CraftingManager) {
+ par1CraftingManager.addShapelessRecipe(new ItemStack(Item.bowlSoup),
+ new Object[] { Block.mushroomBrown, Block.mushroomRed, Item.bowlEmpty });
+ par1CraftingManager.addRecipe(new ItemStack(Item.cookie, 8),
+ new Object[] { "#X#", 'X', new ItemStack(Item.dyePowder, 1, 3), '#', Item.wheat });
+ par1CraftingManager.addRecipe(new ItemStack(Block.melon),
+ new Object[] { "MMM", "MMM", "MMM", 'M', Item.melon });
+ par1CraftingManager.addRecipe(new ItemStack(Item.melonSeeds), new Object[] { "M", 'M', Item.melon });
+ par1CraftingManager.addRecipe(new ItemStack(Item.pumpkinSeeds, 4), new Object[] { "M", 'M', Block.pumpkin });
+ par1CraftingManager.addShapelessRecipe(new ItemStack(Item.pumpkinPie),
+ new Object[] { Block.pumpkin, Item.sugar, Item.egg });
+ par1CraftingManager.addShapelessRecipe(new ItemStack(Item.fermentedSpiderEye),
+ new Object[] { Item.spiderEye, Block.mushroomBrown, Item.sugar });
+ par1CraftingManager.addShapelessRecipe(new ItemStack(Item.speckledMelon),
+ new Object[] { Item.melon, Item.goldNugget });
+ par1CraftingManager.addShapelessRecipe(new ItemStack(Item.blazePowder, 2), new Object[] { Item.blazeRod });
+ par1CraftingManager.addShapelessRecipe(new ItemStack(Item.magmaCream),
+ new Object[] { Item.blazePowder, Item.slimeBall });
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/RecipesIngots.java b/sp-server/src/main/java/net/minecraft/src/RecipesIngots.java
new file mode 100644
index 0000000..add44ae
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/RecipesIngots.java
@@ -0,0 +1,30 @@
+package net.minecraft.src;
+
+public class RecipesIngots {
+ private Object[][] recipeItems;
+
+ public RecipesIngots() {
+ this.recipeItems = new Object[][] { { Block.blockGold, new ItemStack(Item.ingotGold, 9) },
+ { Block.blockIron, new ItemStack(Item.ingotIron, 9) },
+ { Block.blockDiamond, new ItemStack(Item.diamond, 9) },
+ { Block.blockEmerald, new ItemStack(Item.emerald, 9) },
+ { Block.blockLapis, new ItemStack(Item.dyePowder, 9, 4) },
+ { Block.blockRedstone, new ItemStack(Item.redstone, 9) } };
+ }
+
+ /**
+ * Adds the ingot recipes to the CraftingManager.
+ */
+ public void addRecipes(CraftingManager par1CraftingManager) {
+ for (int var2 = 0; var2 < this.recipeItems.length; ++var2) {
+ Block var3 = (Block) this.recipeItems[var2][0];
+ ItemStack var4 = (ItemStack) this.recipeItems[var2][1];
+ par1CraftingManager.addRecipe(new ItemStack(var3), new Object[] { "###", "###", "###", '#', var4 });
+ par1CraftingManager.addRecipe(var4, new Object[] { "#", '#', var3 });
+ }
+
+ par1CraftingManager.addRecipe(new ItemStack(Item.ingotGold),
+ new Object[] { "###", "###", "###", '#', Item.goldNugget });
+ par1CraftingManager.addRecipe(new ItemStack(Item.goldNugget, 9), new Object[] { "#", '#', Item.ingotGold });
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/RecipesMapCloning.java b/sp-server/src/main/java/net/minecraft/src/RecipesMapCloning.java
new file mode 100644
index 0000000..fa7ec00
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/RecipesMapCloning.java
@@ -0,0 +1,84 @@
+package net.minecraft.src;
+
+public class RecipesMapCloning implements IRecipe {
+ /**
+ * Used to check if a recipe matches current crafting inventory
+ */
+ public boolean matches(InventoryCrafting par1InventoryCrafting, World par2World) {
+ int var3 = 0;
+ ItemStack var4 = null;
+
+ for (int var5 = 0; var5 < par1InventoryCrafting.getSizeInventory(); ++var5) {
+ ItemStack var6 = par1InventoryCrafting.getStackInSlot(var5);
+
+ if (var6 != null) {
+ if (var6.itemID == Item.map.itemID) {
+ if (var4 != null) {
+ return false;
+ }
+
+ var4 = var6;
+ } else {
+ if (var6.itemID != Item.emptyMap.itemID) {
+ return false;
+ }
+
+ ++var3;
+ }
+ }
+ }
+
+ return var4 != null && var3 > 0;
+ }
+
+ /**
+ * Returns an Item that is the result of this recipe
+ */
+ public ItemStack getCraftingResult(InventoryCrafting par1InventoryCrafting) {
+ int var2 = 0;
+ ItemStack var3 = null;
+
+ for (int var4 = 0; var4 < par1InventoryCrafting.getSizeInventory(); ++var4) {
+ ItemStack var5 = par1InventoryCrafting.getStackInSlot(var4);
+
+ if (var5 != null) {
+ if (var5.itemID == Item.map.itemID) {
+ if (var3 != null) {
+ return null;
+ }
+
+ var3 = var5;
+ } else {
+ if (var5.itemID != Item.emptyMap.itemID) {
+ return null;
+ }
+
+ ++var2;
+ }
+ }
+ }
+
+ if (var3 != null && var2 >= 1) {
+ ItemStack var6 = new ItemStack(Item.map, var2 + 1, var3.getItemDamage());
+
+ if (var3.hasDisplayName()) {
+ var6.setItemName(var3.getDisplayName());
+ }
+
+ return var6;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Returns the size of the recipe area
+ */
+ public int getRecipeSize() {
+ return 9;
+ }
+
+ public ItemStack getRecipeOutput() {
+ return null;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/RecipesMapExtending.java b/sp-server/src/main/java/net/minecraft/src/RecipesMapExtending.java
new file mode 100644
index 0000000..9bd9c70
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/RecipesMapExtending.java
@@ -0,0 +1,62 @@
+package net.minecraft.src;
+
+public class RecipesMapExtending extends ShapedRecipes {
+ public RecipesMapExtending() {
+ super(3, 3,
+ new ItemStack[] { new ItemStack(Item.paper), new ItemStack(Item.paper), new ItemStack(Item.paper),
+ new ItemStack(Item.paper), new ItemStack(Item.map, 0, 32767), new ItemStack(Item.paper),
+ new ItemStack(Item.paper), new ItemStack(Item.paper), new ItemStack(Item.paper) },
+ new ItemStack(Item.emptyMap, 0, 0));
+ }
+
+ /**
+ * Used to check if a recipe matches current crafting inventory
+ */
+ public boolean matches(InventoryCrafting par1InventoryCrafting, World par2World) {
+ if (!super.matches(par1InventoryCrafting, par2World)) {
+ return false;
+ } else {
+ ItemStack var3 = null;
+
+ for (int var4 = 0; var4 < par1InventoryCrafting.getSizeInventory() && var3 == null; ++var4) {
+ ItemStack var5 = par1InventoryCrafting.getStackInSlot(var4);
+
+ if (var5 != null && var5.itemID == Item.map.itemID) {
+ var3 = var5;
+ }
+ }
+
+ if (var3 == null) {
+ return false;
+ } else {
+ MapData var6 = Item.map.getMapData(var3, par2World);
+ return var6 == null ? false : var6.scale < 4;
+ }
+ }
+ }
+
+ /**
+ * Returns an Item that is the result of this recipe
+ */
+ public ItemStack getCraftingResult(InventoryCrafting par1InventoryCrafting) {
+ ItemStack var2 = null;
+
+ for (int var3 = 0; var3 < par1InventoryCrafting.getSizeInventory() && var2 == null; ++var3) {
+ ItemStack var4 = par1InventoryCrafting.getStackInSlot(var3);
+
+ if (var4 != null && var4.itemID == Item.map.itemID) {
+ var2 = var4;
+ }
+ }
+
+ var2 = var2.copy();
+ var2.stackSize = 1;
+
+ if (var2.getTagCompound() == null) {
+ var2.setTagCompound(new NBTTagCompound());
+ }
+
+ var2.getTagCompound().setBoolean("map_is_scaling", true);
+ return var2;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/RecipesTools.java b/sp-server/src/main/java/net/minecraft/src/RecipesTools.java
new file mode 100644
index 0000000..3bf3894
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/RecipesTools.java
@@ -0,0 +1,33 @@
+package net.minecraft.src;
+
+public class RecipesTools {
+ private String[][] recipePatterns = new String[][] { { "XXX", " # ", " # " }, { "X", "#", "#" },
+ { "XX", "X#", " #" }, { "XX", " #", " #" } };
+ private Object[][] recipeItems;
+
+ public RecipesTools() {
+ this.recipeItems = new Object[][] {
+ { Block.planks, Block.cobblestone, Item.ingotIron, Item.diamond, Item.ingotGold },
+ { Item.pickaxeWood, Item.pickaxeStone, Item.pickaxeIron, Item.pickaxeDiamond, Item.pickaxeGold },
+ { Item.shovelWood, Item.shovelStone, Item.shovelIron, Item.shovelDiamond, Item.shovelGold },
+ { Item.axeWood, Item.axeStone, Item.axeIron, Item.axeDiamond, Item.axeGold },
+ { Item.hoeWood, Item.hoeStone, Item.hoeIron, Item.hoeDiamond, Item.hoeGold } };
+ }
+
+ /**
+ * Adds the tool recipes to the CraftingManager.
+ */
+ public void addRecipes(CraftingManager par1CraftingManager) {
+ for (int var2 = 0; var2 < this.recipeItems[0].length; ++var2) {
+ Object var3 = this.recipeItems[0][var2];
+
+ for (int var4 = 0; var4 < this.recipeItems.length - 1; ++var4) {
+ Item var5 = (Item) this.recipeItems[var4 + 1][var2];
+ par1CraftingManager.addRecipe(new ItemStack(var5),
+ new Object[] { this.recipePatterns[var4], '#', Item.stick, 'X', var3 });
+ }
+ }
+
+ par1CraftingManager.addRecipe(new ItemStack(Item.shears), new Object[] { " #", "# ", '#', Item.ingotIron });
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/RecipesWeapons.java b/sp-server/src/main/java/net/minecraft/src/RecipesWeapons.java
new file mode 100644
index 0000000..7596fa5
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/RecipesWeapons.java
@@ -0,0 +1,32 @@
+package net.minecraft.src;
+
+public class RecipesWeapons {
+ private String[][] recipePatterns = new String[][] { { "X", "X", "#" } };
+ private Object[][] recipeItems;
+
+ public RecipesWeapons() {
+ this.recipeItems = new Object[][] {
+ { Block.planks, Block.cobblestone, Item.ingotIron, Item.diamond, Item.ingotGold },
+ { Item.swordWood, Item.swordStone, Item.swordIron, Item.swordDiamond, Item.swordGold } };
+ }
+
+ /**
+ * Adds the weapon recipes to the CraftingManager.
+ */
+ public void addRecipes(CraftingManager par1CraftingManager) {
+ for (int var2 = 0; var2 < this.recipeItems[0].length; ++var2) {
+ Object var3 = this.recipeItems[0][var2];
+
+ for (int var4 = 0; var4 < this.recipeItems.length - 1; ++var4) {
+ Item var5 = (Item) this.recipeItems[var4 + 1][var2];
+ par1CraftingManager.addRecipe(new ItemStack(var5),
+ new Object[] { this.recipePatterns[var4], '#', Item.stick, 'X', var3 });
+ }
+ }
+
+ par1CraftingManager.addRecipe(new ItemStack(Item.bow, 1),
+ new Object[] { " #X", "# X", " #X", 'X', Item.silk, '#', Item.stick });
+ par1CraftingManager.addRecipe(new ItemStack(Item.arrow, 4),
+ new Object[] { "X", "#", "Y", 'Y', Item.feather, 'X', Item.flint, '#', Item.stick });
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/RedstoneUpdateInfo.java b/sp-server/src/main/java/net/minecraft/src/RedstoneUpdateInfo.java
new file mode 100644
index 0000000..be32de2
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/RedstoneUpdateInfo.java
@@ -0,0 +1,15 @@
+package net.minecraft.src;
+
+class RedstoneUpdateInfo {
+ int x;
+ int y;
+ int z;
+ long updateTime;
+
+ public RedstoneUpdateInfo(int par1, int par2, int par3, long par4) {
+ this.x = par1;
+ this.y = par2;
+ this.z = par3;
+ this.updateTime = par4;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/RegionFile.java b/sp-server/src/main/java/net/minecraft/src/RegionFile.java
new file mode 100644
index 0000000..4ad6459
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/RegionFile.java
@@ -0,0 +1,293 @@
+package net.minecraft.src;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.zip.DeflaterOutputStream;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.InflaterInputStream;
+
+import net.lax1dude.eaglercraft.sp.RandomAccessMemoryFile;
+
+public class RegionFile {
+ private static final byte[] emptySector = new byte[4096];
+ private RandomAccessMemoryFile dataFile;
+ private final int[] offsets = new int[1024];
+ private final int[] chunkTimestamps = new int[1024];
+ private ArrayList sectorFree;
+
+ /** McRegion sizeDelta */
+ private int sizeDelta;
+ private long lastModified = 0L;
+
+ public RegionFile(RandomAccessMemoryFile dataFile) {
+ this.sizeDelta = 0;
+
+ try {
+ this.dataFile = dataFile;
+ int var2;
+
+ if (this.dataFile.getLength() < 4096L) {
+ for (var2 = 0; var2 < 1024; ++var2) {
+ this.dataFile.writeInt(0);
+ }
+
+ for (var2 = 0; var2 < 1024; ++var2) {
+ this.dataFile.writeInt(0);
+ }
+
+ this.sizeDelta += 8192;
+ }
+
+ if ((this.dataFile.getLength() & 4095L) != 0L) {
+ for (var2 = 0; (long) var2 < (this.dataFile.getLength() & 4095L); ++var2) {
+ this.dataFile.write(0);
+ }
+ }
+
+ var2 = (int) this.dataFile.getLength() / 4096;
+ this.sectorFree = new ArrayList(var2);
+ int var3;
+
+ for (var3 = 0; var3 < var2; ++var3) {
+ this.sectorFree.add(Boolean.valueOf(true));
+ }
+
+ this.sectorFree.set(0, Boolean.valueOf(false));
+ this.sectorFree.set(1, Boolean.valueOf(false));
+ this.dataFile.seek(0);
+ int var4;
+
+ for (var3 = 0; var3 < 1024; ++var3) {
+ var4 = this.dataFile.readInt();
+ this.offsets[var3] = var4;
+
+ if (var4 != 0 && (var4 >> 8) + (var4 & 255) <= this.sectorFree.size()) {
+ for (int var5 = 0; var5 < (var4 & 255); ++var5) {
+ this.sectorFree.set((var4 >> 8) + var5, Boolean.valueOf(false));
+ }
+ }
+ }
+
+ for (var3 = 0; var3 < 1024; ++var3) {
+ var4 = this.dataFile.readInt();
+ this.chunkTimestamps[var3] = var4;
+ }
+ } catch (IOException var6) {
+ var6.printStackTrace();
+ }
+ }
+
+ /**
+ * args: x, y - get uncompressed chunk stream from the region file
+ */
+ public synchronized DataInputStream getChunkDataInputStream(int par1, int par2) {
+ if (this.outOfBounds(par1, par2)) {
+ return null;
+ } else {
+ try {
+ int var3 = this.getOffset(par1, par2);
+
+ if (var3 == 0) {
+ return null;
+ } else {
+ int var4 = var3 >> 8;
+ int var5 = var3 & 255;
+
+ if (var4 + var5 > this.sectorFree.size()) {
+ return null;
+ } else {
+ this.dataFile.seek(var4 * 4096);
+ int var6 = this.dataFile.readInt();
+
+ if (var6 > 4096 * var5) {
+ return null;
+ } else if (var6 <= 0) {
+ return null;
+ } else {
+ byte var7 = this.dataFile.readByte();
+ byte[] var8;
+
+ if (var7 == 1) {
+ var8 = new byte[var6 - 1];
+ this.dataFile.read(var8);
+ return new DataInputStream(
+ new BufferedInputStream(new GZIPInputStream(new ByteArrayInputStream(var8))));
+ } else if (var7 == 2) {
+ var8 = new byte[var6 - 1];
+ this.dataFile.read(var8);
+ return new DataInputStream(new BufferedInputStream(
+ new InflaterInputStream(new ByteArrayInputStream(var8))));
+ } else {
+ return null;
+ }
+ }
+ }
+ }
+ } catch (IOException var9) {
+ return null;
+ }
+ }
+ }
+
+ /**
+ * args: x, z - get an output stream used to write chunk data, data is on disk
+ * when the returned stream is closed
+ */
+ public DataOutputStream getChunkDataOutputStream(int par1, int par2) {
+ return this.outOfBounds(par1, par2) ? null
+ : new DataOutputStream(new DeflaterOutputStream(new ChunkBuffer(par1, par2)));
+ }
+
+ /**
+ * args: x, z, data, length - write chunk data at (x, z) to disk
+ */
+ protected synchronized void write(int par1, int par2, byte[] par3ArrayOfByte, int par4) {
+ try {
+ int var5 = this.getOffset(par1, par2);
+ int var6 = var5 >> 8;
+ int var7 = var5 & 255;
+ int var8 = (par4 + 5) / 4096 + 1;
+
+ if (var8 >= 256) {
+ return;
+ }
+
+ if (var6 != 0 && var7 == var8) {
+ this.write(var6, par3ArrayOfByte, par4);
+ } else {
+ int var9;
+
+ for (var9 = 0; var9 < var7; ++var9) {
+ this.sectorFree.set(var6 + var9, Boolean.valueOf(true));
+ }
+
+ var9 = this.sectorFree.indexOf(Boolean.valueOf(true));
+ int var10 = 0;
+ int var11;
+
+ if (var9 != -1) {
+ for (var11 = var9; var11 < this.sectorFree.size(); ++var11) {
+ if (var10 != 0) {
+ if (((Boolean) this.sectorFree.get(var11)).booleanValue()) {
+ ++var10;
+ } else {
+ var10 = 0;
+ }
+ } else if (((Boolean) this.sectorFree.get(var11)).booleanValue()) {
+ var9 = var11;
+ var10 = 1;
+ }
+
+ if (var10 >= var8) {
+ break;
+ }
+ }
+ }
+
+ if (var10 >= var8) {
+ var6 = var9;
+ this.setOffset(par1, par2, var9 << 8 | var8);
+
+ for (var11 = 0; var11 < var8; ++var11) {
+ this.sectorFree.set(var6 + var11, Boolean.valueOf(false));
+ }
+
+ this.write(var6, par3ArrayOfByte, par4);
+ } else {
+ this.dataFile.seek(this.dataFile.getLength());
+ var6 = this.sectorFree.size();
+
+ for (var11 = 0; var11 < var8; ++var11) {
+ this.dataFile.write(emptySector);
+ this.sectorFree.add(Boolean.valueOf(false));
+ }
+
+ this.sizeDelta += 4096 * var8;
+ this.write(var6, par3ArrayOfByte, par4);
+ this.setOffset(par1, par2, var6 << 8 | var8);
+ }
+ }
+
+ this.setChunkTimestamp(par1, par2, (int) (System.currentTimeMillis() / 1000L));
+ } catch (IOException var12) {
+ var12.printStackTrace();
+ }
+ }
+
+ /**
+ * args: sectorNumber, data, length - write the chunk data to this RegionFile
+ */
+ private void write(int par1, byte[] par2ArrayOfByte, int par3) throws IOException {
+ this.dataFile.seek(par1 * 4096);
+ this.dataFile.writeInt(par3 + 1);
+ this.dataFile.writeByte(2);
+ this.dataFile.write(par2ArrayOfByte, 0, par3);
+ }
+
+ /**
+ * args: x, z - check region bounds
+ */
+ private boolean outOfBounds(int par1, int par2) {
+ return par1 < 0 || par1 >= 32 || par2 < 0 || par2 >= 32;
+ }
+
+ /**
+ * args: x, y - get chunk's offset in region file
+ */
+ private int getOffset(int par1, int par2) {
+ return this.offsets[par1 + par2 * 32];
+ }
+
+ /**
+ * args: x, z, - true if chunk has been saved / converted
+ */
+ public boolean isChunkSaved(int par1, int par2) {
+ return this.getOffset(par1, par2) != 0;
+ }
+
+ /**
+ * args: x, z, offset - sets the chunk's offset in the region file
+ */
+ private void setOffset(int par1, int par2, int par3) throws IOException {
+ this.offsets[par1 + par2 * 32] = par3;
+ this.dataFile.seek((par1 + par2 * 32) * 4);
+ this.dataFile.writeInt(par3);
+ }
+
+ /**
+ * args: x, z, timestamp - sets the chunk's write timestamp
+ */
+ private void setChunkTimestamp(int par1, int par2, int par3) throws IOException {
+ this.chunkTimestamps[par1 + par2 * 32] = par3;
+ this.dataFile.seek(4096 + (par1 + par2 * 32) * 4);
+ this.dataFile.writeInt(par3);
+ }
+
+ public RandomAccessMemoryFile getFile() {
+ return dataFile;
+ }
+
+ class ChunkBuffer extends ByteArrayOutputStream {
+ private int chunkX;
+ private int chunkZ;
+
+ public ChunkBuffer(int x, int z) {
+ super(8096);
+ this.chunkX = x;
+ this.chunkZ = z;
+ }
+
+ /**+
+ * close this RegionFile and prevent further writes
+ */
+ public void close() throws IOException {
+ RegionFile.this.write(this.chunkX, this.chunkZ, this.buf, this.count);
+ }
+ }
+
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/RegistryDefaulted.java b/sp-server/src/main/java/net/minecraft/src/RegistryDefaulted.java
new file mode 100644
index 0000000..4881f01
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/RegistryDefaulted.java
@@ -0,0 +1,17 @@
+package net.minecraft.src;
+
+public class RegistryDefaulted extends RegistrySimple {
+ /**
+ * Default object for this registry, returned when an object is not found.
+ */
+ private final Object defaultObject;
+
+ public RegistryDefaulted(Object par1Obj) {
+ this.defaultObject = par1Obj;
+ }
+
+ public Object func_82594_a(Object par1Obj) {
+ Object var2 = super.func_82594_a(par1Obj);
+ return var2 == null ? this.defaultObject : var2;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/RegistrySimple.java b/sp-server/src/main/java/net/minecraft/src/RegistrySimple.java
new file mode 100644
index 0000000..9ebb4d8
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/RegistrySimple.java
@@ -0,0 +1,20 @@
+package net.minecraft.src;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class RegistrySimple implements IRegistry {
+ /** Objects registered on this registry. */
+ protected final Map registryObjects = new HashMap();
+
+ public Object func_82594_a(Object par1Obj) {
+ return this.registryObjects.get(par1Obj);
+ }
+
+ /**
+ * Register an object on this registry.
+ */
+ public void putObject(Object par1Obj, Object par2Obj) {
+ this.registryObjects.put(par1Obj, par2Obj);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Score.java b/sp-server/src/main/java/net/minecraft/src/Score.java
new file mode 100644
index 0000000..59acc03
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Score.java
@@ -0,0 +1,71 @@
+package net.minecraft.src;
+
+import java.util.Comparator;
+import java.util.List;
+
+public class Score {
+ public static final Comparator field_96658_a = new ScoreComparator();
+ private final Scoreboard theScoreboard;
+ private final ScoreObjective field_96657_c;
+ private final String field_96654_d;
+ private int field_96655_e;
+
+ public Score(Scoreboard par1Scoreboard, ScoreObjective par2ScoreObjective, String par3Str) {
+ this.theScoreboard = par1Scoreboard;
+ this.field_96657_c = par2ScoreObjective;
+ this.field_96654_d = par3Str;
+ }
+
+ public void func_96649_a(int par1) {
+ if (this.field_96657_c.getCriteria().isReadOnly()) {
+ throw new IllegalStateException("Cannot modify read-only score");
+ } else {
+ this.func_96647_c(this.func_96652_c() + par1);
+ }
+ }
+
+ public void func_96646_b(int par1) {
+ if (this.field_96657_c.getCriteria().isReadOnly()) {
+ throw new IllegalStateException("Cannot modify read-only score");
+ } else {
+ this.func_96647_c(this.func_96652_c() - par1);
+ }
+ }
+
+ public void func_96648_a() {
+ if (this.field_96657_c.getCriteria().isReadOnly()) {
+ throw new IllegalStateException("Cannot modify read-only score");
+ } else {
+ this.func_96649_a(1);
+ }
+ }
+
+ public int func_96652_c() {
+ return this.field_96655_e;
+ }
+
+ public void func_96647_c(int par1) {
+ int var2 = this.field_96655_e;
+ this.field_96655_e = par1;
+
+ if (var2 != par1) {
+ this.func_96650_f().func_96536_a(this);
+ }
+ }
+
+ public ScoreObjective func_96645_d() {
+ return this.field_96657_c;
+ }
+
+ public String func_96653_e() {
+ return this.field_96654_d;
+ }
+
+ public Scoreboard func_96650_f() {
+ return this.theScoreboard;
+ }
+
+ public void func_96651_a(List par1List) {
+ this.func_96647_c(this.field_96657_c.getCriteria().func_96635_a(par1List));
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ScoreComparator.java b/sp-server/src/main/java/net/minecraft/src/ScoreComparator.java
new file mode 100644
index 0000000..924521f
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ScoreComparator.java
@@ -0,0 +1,14 @@
+package net.minecraft.src;
+
+import java.util.Comparator;
+
+final class ScoreComparator implements Comparator {
+ public int func_96659_a(Score par1Score, Score par2Score) {
+ return par1Score.func_96652_c() > par2Score.func_96652_c() ? 1
+ : (par1Score.func_96652_c() < par2Score.func_96652_c() ? -1 : 0);
+ }
+
+ public int compare(Object par1Obj, Object par2Obj) {
+ return this.func_96659_a((Score) par1Obj, (Score) par2Obj);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ScoreDummyCriteria.java b/sp-server/src/main/java/net/minecraft/src/ScoreDummyCriteria.java
new file mode 100644
index 0000000..68c8a32
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ScoreDummyCriteria.java
@@ -0,0 +1,24 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+public class ScoreDummyCriteria implements ScoreObjectiveCriteria {
+ private final String field_96644_g;
+
+ public ScoreDummyCriteria(String par1Str) {
+ this.field_96644_g = par1Str;
+ ScoreObjectiveCriteria.field_96643_a.put(par1Str, this);
+ }
+
+ public String func_96636_a() {
+ return this.field_96644_g;
+ }
+
+ public int func_96635_a(List par1List) {
+ return 0;
+ }
+
+ public boolean isReadOnly() {
+ return false;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ScoreHealthCriteria.java b/sp-server/src/main/java/net/minecraft/src/ScoreHealthCriteria.java
new file mode 100644
index 0000000..99748d2
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ScoreHealthCriteria.java
@@ -0,0 +1,40 @@
+package net.minecraft.src;
+
+import java.util.Iterator;
+import java.util.List;
+
+public class ScoreHealthCriteria extends ScoreDummyCriteria {
+ public ScoreHealthCriteria(String par1Str) {
+ super(par1Str);
+ }
+
+ public int func_96635_a(List par1List) {
+ float var2 = 0.0F;
+ int var5;
+ float var6;
+
+ for (Iterator var3 = par1List.iterator(); var3.hasNext(); var2 += (float) var5 / var6) {
+ EntityPlayer var4 = (EntityPlayer) var3.next();
+ var5 = var4.getHealth();
+ var6 = (float) var4.getMaxHealth();
+
+ if (var5 < 0) {
+ var5 = 0;
+ }
+
+ if ((float) var5 > var6) {
+ var5 = var4.getMaxHealth();
+ }
+ }
+
+ if (par1List.size() > 0) {
+ var2 /= (float) par1List.size();
+ }
+
+ return MathHelper.floor_float(var2 * 19.0F) + (var2 > 0.0F ? 1 : 0);
+ }
+
+ public boolean isReadOnly() {
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ScoreObjective.java b/sp-server/src/main/java/net/minecraft/src/ScoreObjective.java
new file mode 100644
index 0000000..4788598
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ScoreObjective.java
@@ -0,0 +1,35 @@
+package net.minecraft.src;
+
+public class ScoreObjective {
+ private final Scoreboard theScoreboard;
+ private final String name;
+
+ /** The ScoreObjectiveCriteria for this objetive */
+ private final ScoreObjectiveCriteria objectiveCriteria;
+ private String displayName;
+
+ public ScoreObjective(Scoreboard par1Scoreboard, String par2Str,
+ ScoreObjectiveCriteria par3ScoreObjectiveCriteria) {
+ this.theScoreboard = par1Scoreboard;
+ this.name = par2Str;
+ this.objectiveCriteria = par3ScoreObjectiveCriteria;
+ this.displayName = par2Str;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public ScoreObjectiveCriteria getCriteria() {
+ return this.objectiveCriteria;
+ }
+
+ public String getDisplayName() {
+ return this.displayName;
+ }
+
+ public void setDisplayName(String par1Str) {
+ this.displayName = par1Str;
+ this.theScoreboard.func_96532_b(this);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ScoreObjectiveCriteria.java b/sp-server/src/main/java/net/minecraft/src/ScoreObjectiveCriteria.java
new file mode 100644
index 0000000..df4ca25
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ScoreObjectiveCriteria.java
@@ -0,0 +1,20 @@
+package net.minecraft.src;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public interface ScoreObjectiveCriteria {
+ Map field_96643_a = new HashMap();
+ ScoreObjectiveCriteria field_96641_b = new ScoreDummyCriteria("dummy");
+ ScoreObjectiveCriteria field_96642_c = new ScoreDummyCriteria("deathCount");
+ ScoreObjectiveCriteria field_96639_d = new ScoreDummyCriteria("playerKillCount");
+ ScoreObjectiveCriteria field_96640_e = new ScoreDummyCriteria("totalKillCount");
+ ScoreObjectiveCriteria field_96638_f = new ScoreHealthCriteria("health");
+
+ String func_96636_a();
+
+ int func_96635_a(List var1);
+
+ boolean isReadOnly();
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ScorePlayerTeam.java b/sp-server/src/main/java/net/minecraft/src/ScorePlayerTeam.java
new file mode 100644
index 0000000..13b4f15
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ScorePlayerTeam.java
@@ -0,0 +1,109 @@
+package net.minecraft.src;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+public class ScorePlayerTeam {
+ private final Scoreboard theScoreboard;
+ private final String field_96675_b;
+
+ /** A set of all team member usernames. */
+ private final Set membershipSet = new HashSet();
+ private String field_96673_d;
+ private String field_96674_e = "";
+ private String field_96671_f = "";
+ private boolean field_96672_g = true;
+ private boolean field_98301_h = true;
+
+ public ScorePlayerTeam(Scoreboard par1Scoreboard, String par2Str) {
+ this.theScoreboard = par1Scoreboard;
+ this.field_96675_b = par2Str;
+ this.field_96673_d = par2Str;
+ }
+
+ public String func_96661_b() {
+ return this.field_96675_b;
+ }
+
+ public String func_96669_c() {
+ return this.field_96673_d;
+ }
+
+ public void func_96664_a(String par1Str) {
+ if (par1Str == null) {
+ throw new IllegalArgumentException("Name cannot be null");
+ } else {
+ this.field_96673_d = par1Str;
+ this.theScoreboard.func_96538_b(this);
+ }
+ }
+
+ public Collection getMembershipCollection() {
+ return this.membershipSet;
+ }
+
+ public String func_96668_e() {
+ return this.field_96674_e;
+ }
+
+ public void func_96666_b(String par1Str) {
+ if (par1Str == null) {
+ throw new IllegalArgumentException("Prefix cannot be null");
+ } else {
+ this.field_96674_e = par1Str;
+ this.theScoreboard.func_96538_b(this);
+ }
+ }
+
+ public String func_96663_f() {
+ return this.field_96671_f;
+ }
+
+ public void func_96662_c(String par1Str) {
+ if (par1Str == null) {
+ throw new IllegalArgumentException("Suffix cannot be null");
+ } else {
+ this.field_96671_f = par1Str;
+ this.theScoreboard.func_96538_b(this);
+ }
+ }
+
+ public static String func_96667_a(ScorePlayerTeam par0ScorePlayerTeam, String par1Str) {
+ return par0ScorePlayerTeam == null ? par1Str
+ : par0ScorePlayerTeam.func_96668_e() + par1Str + par0ScorePlayerTeam.func_96663_f();
+ }
+
+ public boolean func_96665_g() {
+ return this.field_96672_g;
+ }
+
+ public void func_96660_a(boolean par1) {
+ this.field_96672_g = par1;
+ this.theScoreboard.func_96538_b(this);
+ }
+
+ public boolean func_98297_h() {
+ return this.field_98301_h;
+ }
+
+ public void func_98300_b(boolean par1) {
+ this.field_98301_h = par1;
+ this.theScoreboard.func_96538_b(this);
+ }
+
+ public int func_98299_i() {
+ int var1 = 0;
+ int var2 = 0;
+
+ if (this.func_96665_g()) {
+ var1 |= 1 << var2++;
+ }
+
+ if (this.func_98297_h()) {
+ var1 |= 1 << var2++;
+ }
+
+ return var1;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Scoreboard.java b/sp-server/src/main/java/net/minecraft/src/Scoreboard.java
new file mode 100644
index 0000000..fd6e0e6
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Scoreboard.java
@@ -0,0 +1,295 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+public class Scoreboard {
+ /** Map of objective names to ScoreObjective objects. */
+ private final Map scoreObjectives = new HashMap();
+ private final Map field_96543_b = new HashMap();
+ private final Map field_96544_c = new HashMap();
+ private final ScoreObjective[] field_96541_d = new ScoreObjective[3];
+ private final Map field_96542_e = new HashMap();
+
+ /** Map of usernames to ScorePlayerTeam objects. */
+ private final Map teamMemberships = new HashMap();
+
+ /**
+ * Returns a ScoreObjective for the objective name
+ */
+ public ScoreObjective getObjective(String par1Str) {
+ return (ScoreObjective) this.scoreObjectives.get(par1Str);
+ }
+
+ public ScoreObjective func_96535_a(String par1Str, ScoreObjectiveCriteria par2ScoreObjectiveCriteria) {
+ ScoreObjective var3 = this.getObjective(par1Str);
+
+ if (var3 != null) {
+ throw new IllegalArgumentException("An objective with the name \'" + par1Str + "\' already exists!");
+ } else {
+ var3 = new ScoreObjective(this, par1Str, par2ScoreObjectiveCriteria);
+ Object var4 = (List) this.field_96543_b.get(par2ScoreObjectiveCriteria);
+
+ if (var4 == null) {
+ var4 = new ArrayList();
+ this.field_96543_b.put(par2ScoreObjectiveCriteria, var4);
+ }
+
+ ((List) var4).add(var3);
+ this.scoreObjectives.put(par1Str, var3);
+ this.func_96522_a(var3);
+ return var3;
+ }
+ }
+
+ public Collection func_96520_a(ScoreObjectiveCriteria par1ScoreObjectiveCriteria) {
+ Collection var2 = (Collection) this.field_96543_b.get(par1ScoreObjectiveCriteria);
+ return var2 == null ? new ArrayList() : new ArrayList(var2);
+ }
+
+ public Score func_96529_a(String par1Str, ScoreObjective par2ScoreObjective) {
+ Object var3 = (Map) this.field_96544_c.get(par1Str);
+
+ if (var3 == null) {
+ var3 = new HashMap();
+ this.field_96544_c.put(par1Str, var3);
+ }
+
+ Score var4 = (Score) ((Map) var3).get(par2ScoreObjective);
+
+ if (var4 == null) {
+ var4 = new Score(this, par2ScoreObjective, par1Str);
+ ((Map) var3).put(par2ScoreObjective, var4);
+ }
+
+ return var4;
+ }
+
+ public Collection func_96534_i(ScoreObjective par1ScoreObjective) {
+ ArrayList var2 = new ArrayList();
+ Iterator var3 = this.field_96544_c.values().iterator();
+
+ while (var3.hasNext()) {
+ Map var4 = (Map) var3.next();
+ Score var5 = (Score) var4.get(par1ScoreObjective);
+
+ if (var5 != null) {
+ var2.add(var5);
+ }
+ }
+
+ Collections.sort(var2, Score.field_96658_a);
+ return var2;
+ }
+
+ public Collection getScoreObjectives() {
+ return this.scoreObjectives.values();
+ }
+
+ public Collection getObjectiveNames() {
+ return this.field_96544_c.keySet();
+ }
+
+ public void func_96515_c(String par1Str) {
+ Map var2 = (Map) this.field_96544_c.remove(par1Str);
+
+ if (var2 != null) {
+ this.func_96516_a(par1Str);
+ }
+ }
+
+ public Collection func_96528_e() {
+ Collection var1 = this.field_96544_c.values();
+ ArrayList var2 = new ArrayList();
+
+ if (var1 != null) {
+ Iterator var3 = var1.iterator();
+
+ while (var3.hasNext()) {
+ Map var4 = (Map) var3.next();
+ var2.addAll(var4.values());
+ }
+ }
+
+ return var2;
+ }
+
+ public Map func_96510_d(String par1Str) {
+ Object var2 = (Map) this.field_96544_c.get(par1Str);
+
+ if (var2 == null) {
+ var2 = new HashMap();
+ }
+
+ return (Map) var2;
+ }
+
+ public void func_96519_k(ScoreObjective par1ScoreObjective) {
+ this.scoreObjectives.remove(par1ScoreObjective.getName());
+
+ for (int var2 = 0; var2 < 3; ++var2) {
+ if (this.func_96539_a(var2) == par1ScoreObjective) {
+ this.func_96530_a(var2, (ScoreObjective) null);
+ }
+ }
+
+ List var5 = (List) this.field_96543_b.get(par1ScoreObjective.getCriteria());
+
+ if (var5 != null) {
+ var5.remove(par1ScoreObjective);
+ }
+
+ Iterator var3 = this.field_96544_c.values().iterator();
+
+ while (var3.hasNext()) {
+ Map var4 = (Map) var3.next();
+ var4.remove(par1ScoreObjective);
+ }
+
+ this.func_96533_c(par1ScoreObjective);
+ }
+
+ public void func_96530_a(int par1, ScoreObjective par2ScoreObjective) {
+ this.field_96541_d[par1] = par2ScoreObjective;
+ }
+
+ public ScoreObjective func_96539_a(int par1) {
+ return this.field_96541_d[par1];
+ }
+
+ public ScorePlayerTeam func_96508_e(String par1Str) {
+ return (ScorePlayerTeam) this.field_96542_e.get(par1Str);
+ }
+
+ public ScorePlayerTeam func_96527_f(String par1Str) {
+ ScorePlayerTeam var2 = this.func_96508_e(par1Str);
+
+ if (var2 != null) {
+ throw new IllegalArgumentException("An objective with the name \'" + par1Str + "\' already exists!");
+ } else {
+ var2 = new ScorePlayerTeam(this, par1Str);
+ this.field_96542_e.put(par1Str, var2);
+ this.func_96523_a(var2);
+ return var2;
+ }
+ }
+
+ public void func_96511_d(ScorePlayerTeam par1ScorePlayerTeam) {
+ this.field_96542_e.remove(par1ScorePlayerTeam.func_96661_b());
+ Iterator var2 = par1ScorePlayerTeam.getMembershipCollection().iterator();
+
+ while (var2.hasNext()) {
+ String var3 = (String) var2.next();
+ this.teamMemberships.remove(var3);
+ }
+
+ this.func_96513_c(par1ScorePlayerTeam);
+ }
+
+ public void func_96521_a(String par1Str, ScorePlayerTeam par2ScorePlayerTeam) {
+ if (this.getPlayersTeam(par1Str) != null) {
+ this.func_96524_g(par1Str);
+ }
+
+ this.teamMemberships.put(par1Str, par2ScorePlayerTeam);
+ par2ScorePlayerTeam.getMembershipCollection().add(par1Str);
+ }
+
+ public boolean func_96524_g(String par1Str) {
+ ScorePlayerTeam var2 = this.getPlayersTeam(par1Str);
+
+ if (var2 != null) {
+ this.removePlayerFromTeam(par1Str, var2);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Removes the given username from the given ScorePlayerTeam. If the player is
+ * not on the team then an IllegalStateException is thrown.
+ */
+ public void removePlayerFromTeam(String par1Str, ScorePlayerTeam par2ScorePlayerTeam) {
+ if (this.getPlayersTeam(par1Str) != par2ScorePlayerTeam) {
+ throw new IllegalStateException(
+ "Player is either on another team or not on any team. Cannot remove from team \'"
+ + par2ScorePlayerTeam.func_96661_b() + "\'.");
+ } else {
+ this.teamMemberships.remove(par1Str);
+ par2ScorePlayerTeam.getMembershipCollection().remove(par1Str);
+ }
+ }
+
+ public Collection func_96531_f() {
+ return this.field_96542_e.keySet();
+ }
+
+ public Collection func_96525_g() {
+ return this.field_96542_e.values();
+ }
+
+ /**
+ * Gets the ScorePlayerTeam object for the given username.
+ */
+ public ScorePlayerTeam getPlayersTeam(String par1Str) {
+ return (ScorePlayerTeam) this.teamMemberships.get(par1Str);
+ }
+
+ public void func_96522_a(ScoreObjective par1ScoreObjective) {
+ }
+
+ public void func_96532_b(ScoreObjective par1ScoreObjective) {
+ }
+
+ public void func_96533_c(ScoreObjective par1ScoreObjective) {
+ }
+
+ public void func_96536_a(Score par1Score) {
+ }
+
+ public void func_96516_a(String par1Str) {
+ }
+
+ public void func_96523_a(ScorePlayerTeam par1ScorePlayerTeam) {
+ }
+
+ public void func_96538_b(ScorePlayerTeam par1ScorePlayerTeam) {
+ }
+
+ public void func_96513_c(ScorePlayerTeam par1ScorePlayerTeam) {
+ }
+
+ /**
+ * Returns 'list' for 0, 'sidebar' for 1, 'belowName for 2, otherwise null.
+ */
+ public static String getObjectiveDisplaySlot(int par0) {
+ switch (par0) {
+ case 0:
+ return "list";
+
+ case 1:
+ return "sidebar";
+
+ case 2:
+ return "belowName";
+
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Returns 0 for (case-insensitive) 'list', 1 for 'sidebar', 2 for 'belowName',
+ * otherwise -1.
+ */
+ public static int getObjectiveDisplaySlotNumber(String par0Str) {
+ return par0Str.equalsIgnoreCase("list") ? 0
+ : (par0Str.equalsIgnoreCase("sidebar") ? 1 : (par0Str.equalsIgnoreCase("belowName") ? 2 : -1));
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ScoreboardSaveData.java b/sp-server/src/main/java/net/minecraft/src/ScoreboardSaveData.java
new file mode 100644
index 0000000..23ab38e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ScoreboardSaveData.java
@@ -0,0 +1,199 @@
+package net.minecraft.src;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import net.minecraft.server.MinecraftServer;
+
+public class ScoreboardSaveData extends WorldSavedData {
+ private Scoreboard field_96507_a;
+ private NBTTagCompound field_96506_b;
+
+ public ScoreboardSaveData() {
+ this("scoreboard");
+ }
+
+ public ScoreboardSaveData(String par1Str) {
+ super(par1Str);
+ }
+
+ public void func_96499_a(Scoreboard par1Scoreboard) {
+ this.field_96507_a = par1Scoreboard;
+
+ if (this.field_96506_b != null) {
+ this.readFromNBT(this.field_96506_b);
+ }
+ }
+
+ /**
+ * reads in data from the NBTTagCompound into this MapDataBase
+ */
+ public void readFromNBT(NBTTagCompound par1NBTTagCompound) {
+ if (this.field_96507_a == null) {
+ this.field_96506_b = par1NBTTagCompound;
+ } else {
+ this.func_96501_b(par1NBTTagCompound.getTagList("Objectives"));
+ this.func_96500_c(par1NBTTagCompound.getTagList("PlayerScores"));
+
+ if (par1NBTTagCompound.hasKey("DisplaySlots")) {
+ this.func_96504_c(par1NBTTagCompound.getCompoundTag("DisplaySlots"));
+ }
+
+ if (par1NBTTagCompound.hasKey("Teams")) {
+ this.func_96498_a(par1NBTTagCompound.getTagList("Teams"));
+ }
+ }
+ }
+
+ protected void func_96498_a(NBTTagList par1NBTTagList) {
+ for (int var2 = 0; var2 < par1NBTTagList.tagCount(); ++var2) {
+ NBTTagCompound var3 = (NBTTagCompound) par1NBTTagList.tagAt(var2);
+ ScorePlayerTeam var4 = this.field_96507_a.func_96527_f(var3.getString("Name"));
+ var4.func_96664_a(var3.getString("DisplayName"));
+ var4.func_96666_b(var3.getString("Prefix"));
+ var4.func_96662_c(var3.getString("Suffix"));
+
+ if (var3.hasKey("AllowFriendlyFire")) {
+ var4.func_96660_a(var3.getBoolean("AllowFriendlyFire"));
+ }
+
+ if (var3.hasKey("SeeFriendlyInvisibles")) {
+ var4.func_98300_b(var3.getBoolean("SeeFriendlyInvisibles"));
+ }
+
+ this.func_96502_a(var4, var3.getTagList("Players"));
+ }
+ }
+
+ protected void func_96502_a(ScorePlayerTeam par1ScorePlayerTeam, NBTTagList par2NBTTagList) {
+ for (int var3 = 0; var3 < par2NBTTagList.tagCount(); ++var3) {
+ this.field_96507_a.func_96521_a(((NBTTagString) par2NBTTagList.tagAt(var3)).data, par1ScorePlayerTeam);
+ }
+ }
+
+ protected void func_96504_c(NBTTagCompound par1NBTTagCompound) {
+ for (int var2 = 0; var2 < 3; ++var2) {
+ if (par1NBTTagCompound.hasKey("slot_" + var2)) {
+ String var3 = par1NBTTagCompound.getString("slot_" + var2);
+ ScoreObjective var4 = this.field_96507_a.getObjective(var3);
+ this.field_96507_a.func_96530_a(var2, var4);
+ }
+ }
+ }
+
+ protected void func_96501_b(NBTTagList par1NBTTagList) {
+ for (int var2 = 0; var2 < par1NBTTagList.tagCount(); ++var2) {
+ NBTTagCompound var3 = (NBTTagCompound) par1NBTTagList.tagAt(var2);
+ ScoreObjectiveCriteria var4 = (ScoreObjectiveCriteria) ScoreObjectiveCriteria.field_96643_a
+ .get(var3.getString("CriteriaName"));
+ ScoreObjective var5 = this.field_96507_a.func_96535_a(var3.getString("Name"), var4);
+ var5.setDisplayName(var3.getString("DisplayName"));
+ }
+ }
+
+ protected void func_96500_c(NBTTagList par1NBTTagList) {
+ for (int var2 = 0; var2 < par1NBTTagList.tagCount(); ++var2) {
+ NBTTagCompound var3 = (NBTTagCompound) par1NBTTagList.tagAt(var2);
+ ScoreObjective var4 = this.field_96507_a.getObjective(var3.getString("Objective"));
+ Score var5 = this.field_96507_a.func_96529_a(var3.getString("Name"), var4);
+ var5.func_96647_c(var3.getInteger("Score"));
+ }
+ }
+
+ /**
+ * write data to NBTTagCompound from this MapDataBase, similar to Entities and
+ * TileEntities
+ */
+ public void writeToNBT(NBTTagCompound par1NBTTagCompound) {
+ if (this.field_96507_a == null) {
+ MinecraftServer.getServer().getLogAgent()
+ .func_98236_b("Tried to save scoreboard without having a scoreboard...");
+ } else {
+ par1NBTTagCompound.setTag("Objectives", this.func_96505_b());
+ par1NBTTagCompound.setTag("PlayerScores", this.func_96503_e());
+ par1NBTTagCompound.setTag("Teams", this.func_96496_a());
+ this.func_96497_d(par1NBTTagCompound);
+ }
+ }
+
+ protected NBTTagList func_96496_a() {
+ NBTTagList var1 = new NBTTagList();
+ Collection var2 = this.field_96507_a.func_96525_g();
+ Iterator var3 = var2.iterator();
+
+ while (var3.hasNext()) {
+ ScorePlayerTeam var4 = (ScorePlayerTeam) var3.next();
+ NBTTagCompound var5 = new NBTTagCompound();
+ var5.setString("Name", var4.func_96661_b());
+ var5.setString("DisplayName", var4.func_96669_c());
+ var5.setString("Prefix", var4.func_96668_e());
+ var5.setString("Suffix", var4.func_96663_f());
+ var5.setBoolean("AllowFriendlyFire", var4.func_96665_g());
+ var5.setBoolean("SeeFriendlyInvisibles", var4.func_98297_h());
+ NBTTagList var6 = new NBTTagList();
+ Iterator var7 = var4.getMembershipCollection().iterator();
+
+ while (var7.hasNext()) {
+ String var8 = (String) var7.next();
+ var6.appendTag(new NBTTagString("", var8));
+ }
+
+ var5.setTag("Players", var6);
+ var1.appendTag(var5);
+ }
+
+ return var1;
+ }
+
+ protected void func_96497_d(NBTTagCompound par1NBTTagCompound) {
+ NBTTagCompound var2 = new NBTTagCompound();
+ boolean var3 = false;
+
+ for (int var4 = 0; var4 < 3; ++var4) {
+ ScoreObjective var5 = this.field_96507_a.func_96539_a(var4);
+
+ if (var5 != null) {
+ var2.setString("slot_" + var4, var5.getName());
+ var3 = true;
+ }
+ }
+
+ if (var3) {
+ par1NBTTagCompound.setCompoundTag("DisplaySlots", var2);
+ }
+ }
+
+ protected NBTTagList func_96505_b() {
+ NBTTagList var1 = new NBTTagList();
+ Collection var2 = this.field_96507_a.getScoreObjectives();
+ Iterator var3 = var2.iterator();
+
+ while (var3.hasNext()) {
+ ScoreObjective var4 = (ScoreObjective) var3.next();
+ NBTTagCompound var5 = new NBTTagCompound();
+ var5.setString("Name", var4.getName());
+ var5.setString("CriteriaName", var4.getCriteria().func_96636_a());
+ var5.setString("DisplayName", var4.getDisplayName());
+ var1.appendTag(var5);
+ }
+
+ return var1;
+ }
+
+ protected NBTTagList func_96503_e() {
+ NBTTagList var1 = new NBTTagList();
+ Collection var2 = this.field_96507_a.func_96528_e();
+ Iterator var3 = var2.iterator();
+
+ while (var3.hasNext()) {
+ Score var4 = (Score) var3.next();
+ NBTTagCompound var5 = new NBTTagCompound();
+ var5.setString("Name", var4.func_96653_e());
+ var5.setString("Objective", var4.func_96645_d().getName());
+ var5.setInteger("Score", var4.func_96652_c());
+ var1.appendTag(var5);
+ }
+
+ return var1;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ServerBlockEvent.java b/sp-server/src/main/java/net/minecraft/src/ServerBlockEvent.java
new file mode 100644
index 0000000..4f7f9b9
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ServerBlockEvent.java
@@ -0,0 +1,4 @@
+package net.minecraft.src;
+
+class ServerBlockEvent {
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ServerBlockEventList.java b/sp-server/src/main/java/net/minecraft/src/ServerBlockEventList.java
new file mode 100644
index 0000000..55215ce
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ServerBlockEventList.java
@@ -0,0 +1,12 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+
+class ServerBlockEventList extends ArrayList {
+ private ServerBlockEventList() {
+ }
+
+ ServerBlockEventList(ServerBlockEvent par1ServerBlockEvent) {
+ this();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ServerCommand.java b/sp-server/src/main/java/net/minecraft/src/ServerCommand.java
new file mode 100644
index 0000000..2bf2776
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ServerCommand.java
@@ -0,0 +1,12 @@
+package net.minecraft.src;
+
+public class ServerCommand {
+ /** The command string. */
+ public final String command;
+ public final ICommandSender sender;
+
+ public ServerCommand(String par1Str, ICommandSender par2ICommandSender) {
+ this.command = par1Str;
+ this.sender = par2ICommandSender;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ServerCommandManager.java b/sp-server/src/main/java/net/minecraft/src/ServerCommandManager.java
new file mode 100644
index 0000000..2bfe631
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ServerCommandManager.java
@@ -0,0 +1,73 @@
+package net.minecraft.src;
+
+import java.util.Iterator;
+
+import net.minecraft.server.MinecraftServer;
+
+public class ServerCommandManager extends CommandHandler implements IAdminCommand {
+ public ServerCommandManager() {
+ this.registerCommand(new CommandKick());
+ this.registerCommand(new CommandTime());
+ this.registerCommand(new CommandGameMode());
+ this.registerCommand(new CommandDifficulty());
+ this.registerCommand(new CommandDefaultGameMode());
+ this.registerCommand(new CommandKill());
+ this.registerCommand(new CommandToggleDownfall());
+ this.registerCommand(new CommandWeather());
+ this.registerCommand(new CommandXP());
+ this.registerCommand(new CommandServerTp());
+ this.registerCommand(new CommandGive());
+ this.registerCommand(new CommandEffect());
+ this.registerCommand(new CommandEnchant());
+ this.registerCommand(new CommandServerEmote());
+ this.registerCommand(new CommandShowSeed());
+ this.registerCommand(new CommandHelp());
+ this.registerCommand(new CommandServerMessage());
+ this.registerCommand(new CommandServerSay());
+ this.registerCommand(new CommandSetSpawnpoint());
+ this.registerCommand(new CommandGameRule());
+ this.registerCommand(new CommandClearInventory());
+ this.registerCommand(new ServerCommandTestFor());
+ this.registerCommand(new ServerCommandScoreboard());
+
+ CommandBase.setAdminCommander(this);
+ }
+
+ /**
+ * Sends a message to the admins of the server from a given CommandSender with
+ * the given resource string and given extra srings. If the int par2 is even or
+ * zero, the original sender is also notified.
+ */
+ public void notifyAdmins(ICommandSender par1ICommandSender, int par2, String par3Str, Object... par4ArrayOfObj) {
+ boolean var5 = true;
+
+ if (par1ICommandSender instanceof TileEntityCommandBlock && !MinecraftServer.getServer().worldServers[0]
+ .getGameRules().getGameRuleBooleanValue("commandBlockOutput")) {
+ var5 = false;
+ }
+
+ if (var5) {
+ Iterator var6 = MinecraftServer.getServer().getConfigurationManager().playerEntityList.iterator();
+
+ while (var6.hasNext()) {
+ EntityPlayerMP var7 = (EntityPlayerMP) var6.next();
+
+ if (var7 != par1ICommandSender
+ && MinecraftServer.getServer().getConfigurationManager().areCommandsAllowed(var7.username)) {
+ var7.sendChatToPlayer("" + EnumChatFormatting.GRAY + "" + EnumChatFormatting.ITALIC + "["
+ + par1ICommandSender.getCommandSenderName() + ": "
+ + var7.translateString(par3Str, par4ArrayOfObj) + "]");
+ }
+ }
+ }
+
+ if (par1ICommandSender != MinecraftServer.getServer()) {
+ MinecraftServer.getServer().getLogAgent().func_98233_a("[" + par1ICommandSender.getCommandSenderName()
+ + ": " + MinecraftServer.getServer().translateString(par3Str, par4ArrayOfObj) + "]");
+ }
+
+ if ((par2 & 1) != 1) {
+ par1ICommandSender.sendChatToPlayer(par1ICommandSender.translateString(par3Str, par4ArrayOfObj));
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ServerCommandScoreboard.java b/sp-server/src/main/java/net/minecraft/src/ServerCommandScoreboard.java
new file mode 100644
index 0000000..a4661d5
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ServerCommandScoreboard.java
@@ -0,0 +1,746 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import net.minecraft.server.MinecraftServer;
+
+public class ServerCommandScoreboard extends CommandBase {
+ public String getCommandName() {
+ return "scoreboard";
+ }
+
+ /**
+ * Return the required permission level for this command.
+ */
+ public int getRequiredPermissionLevel() {
+ return 2;
+ }
+
+ public void processCommand(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) {
+ if (par2ArrayOfStr.length >= 1) {
+ if (par2ArrayOfStr[0].equalsIgnoreCase("objectives")) {
+ if (par2ArrayOfStr.length == 1) {
+ throw new WrongUsageException("commands.scoreboard.objectives.usage", new Object[0]);
+ }
+
+ if (par2ArrayOfStr[1].equalsIgnoreCase("list")) {
+ this.getObjectivesList(par1ICommandSender);
+ } else if (par2ArrayOfStr[1].equalsIgnoreCase("add")) {
+ if (par2ArrayOfStr.length < 4) {
+ throw new WrongUsageException("commands.scoreboard.objectives.add.usage", new Object[0]);
+ }
+
+ this.addObjective(par1ICommandSender, par2ArrayOfStr, 2);
+ } else if (par2ArrayOfStr[1].equalsIgnoreCase("remove")) {
+ if (par2ArrayOfStr.length != 3) {
+ throw new WrongUsageException("commands.scoreboard.objectives.remove.usage", new Object[0]);
+ }
+
+ this.removeObjective(par1ICommandSender, par2ArrayOfStr[2]);
+ } else {
+ if (!par2ArrayOfStr[1].equalsIgnoreCase("setdisplay")) {
+ throw new WrongUsageException("commands.scoreboard.objectives.usage", new Object[0]);
+ }
+
+ if (par2ArrayOfStr.length != 3 && par2ArrayOfStr.length != 4) {
+ throw new WrongUsageException("commands.scoreboard.objectives.setdisplay.usage", new Object[0]);
+ }
+
+ this.setObjectivesDisplay(par1ICommandSender, par2ArrayOfStr, 2);
+ }
+
+ return;
+ }
+
+ if (par2ArrayOfStr[0].equalsIgnoreCase("players")) {
+ if (par2ArrayOfStr.length == 1) {
+ throw new WrongUsageException("commands.scoreboard.players.usage", new Object[0]);
+ }
+
+ if (par2ArrayOfStr[1].equalsIgnoreCase("list")) {
+ if (par2ArrayOfStr.length > 3) {
+ throw new WrongUsageException("commands.scoreboard.players.list.usage", new Object[0]);
+ }
+
+ this.listPlayers(par1ICommandSender, par2ArrayOfStr, 2);
+ } else if (par2ArrayOfStr[1].equalsIgnoreCase("add")) {
+ if (par2ArrayOfStr.length != 5) {
+ throw new WrongUsageException("commands.scoreboard.players.add.usage", new Object[0]);
+ }
+
+ this.setPlayerScore(par1ICommandSender, par2ArrayOfStr, 2);
+ } else if (par2ArrayOfStr[1].equalsIgnoreCase("remove")) {
+ if (par2ArrayOfStr.length != 5) {
+ throw new WrongUsageException("commands.scoreboard.players.remove.usage", new Object[0]);
+ }
+
+ this.setPlayerScore(par1ICommandSender, par2ArrayOfStr, 2);
+ } else if (par2ArrayOfStr[1].equalsIgnoreCase("set")) {
+ if (par2ArrayOfStr.length != 5) {
+ throw new WrongUsageException("commands.scoreboard.players.set.usage", new Object[0]);
+ }
+
+ this.setPlayerScore(par1ICommandSender, par2ArrayOfStr, 2);
+ } else {
+ if (!par2ArrayOfStr[1].equalsIgnoreCase("reset")) {
+ throw new WrongUsageException("commands.scoreboard.players.usage", new Object[0]);
+ }
+
+ if (par2ArrayOfStr.length != 3) {
+ throw new WrongUsageException("commands.scoreboard.players.reset.usage", new Object[0]);
+ }
+
+ this.resetPlayerScore(par1ICommandSender, par2ArrayOfStr, 2);
+ }
+
+ return;
+ }
+
+ if (par2ArrayOfStr[0].equalsIgnoreCase("teams")) {
+ if (par2ArrayOfStr.length == 1) {
+ throw new WrongUsageException("commands.scoreboard.teams.usage", new Object[0]);
+ }
+
+ if (par2ArrayOfStr[1].equalsIgnoreCase("list")) {
+ if (par2ArrayOfStr.length > 3) {
+ throw new WrongUsageException("commands.scoreboard.teams.list.usage", new Object[0]);
+ }
+
+ this.getTeamList(par1ICommandSender, par2ArrayOfStr, 2);
+ } else if (par2ArrayOfStr[1].equalsIgnoreCase("add")) {
+ if (par2ArrayOfStr.length < 3) {
+ throw new WrongUsageException("commands.scoreboard.teams.add.usage", new Object[0]);
+ }
+
+ this.addTeam(par1ICommandSender, par2ArrayOfStr, 2);
+ } else if (par2ArrayOfStr[1].equalsIgnoreCase("remove")) {
+ if (par2ArrayOfStr.length != 3) {
+ throw new WrongUsageException("commands.scoreboard.teams.remove.usage", new Object[0]);
+ }
+
+ this.removeTeam(par1ICommandSender, par2ArrayOfStr, 2);
+ } else if (par2ArrayOfStr[1].equalsIgnoreCase("empty")) {
+ if (par2ArrayOfStr.length != 3) {
+ throw new WrongUsageException("commands.scoreboard.teams.empty.usage", new Object[0]);
+ }
+
+ this.emptyTeam(par1ICommandSender, par2ArrayOfStr, 2);
+ } else if (par2ArrayOfStr[1].equalsIgnoreCase("join")) {
+ if (par2ArrayOfStr.length < 4
+ && (par2ArrayOfStr.length != 3 || !(par1ICommandSender instanceof EntityPlayer))) {
+ throw new WrongUsageException("commands.scoreboard.teams.join.usage", new Object[0]);
+ }
+
+ this.joinTeam(par1ICommandSender, par2ArrayOfStr, 2);
+ } else if (par2ArrayOfStr[1].equalsIgnoreCase("leave")) {
+ if (par2ArrayOfStr.length < 3 && !(par1ICommandSender instanceof EntityPlayer)) {
+ throw new WrongUsageException("commands.scoreboard.teams.leave.usage", new Object[0]);
+ }
+
+ this.leaveTeam(par1ICommandSender, par2ArrayOfStr, 2);
+ } else {
+ if (!par2ArrayOfStr[1].equalsIgnoreCase("option")) {
+ throw new WrongUsageException("commands.scoreboard.teams.usage", new Object[0]);
+ }
+
+ if (par2ArrayOfStr.length != 4 && par2ArrayOfStr.length != 5) {
+ throw new WrongUsageException("commands.scoreboard.teams.option.usage", new Object[0]);
+ }
+
+ this.setTeamOption(par1ICommandSender, par2ArrayOfStr, 2);
+ }
+
+ return;
+ }
+ }
+
+ throw new WrongUsageException("commands.scoreboard.usage", new Object[0]);
+ }
+
+ protected Scoreboard getScoreboardFromWorldServer() {
+ return MinecraftServer.getServer().worldServerForDimension(0).getScoreboard();
+ }
+
+ /**
+ * User-safe version of Scoreboard.getObjective, does checks against the
+ * objective not being found and whether it's read-only or not. If true, the
+ * second parameter makes the function throw an exception if the objective is
+ * read- only.
+ */
+ protected ScoreObjective getScoreObjective(String par1Str, boolean par2) {
+ Scoreboard var3 = this.getScoreboardFromWorldServer();
+ ScoreObjective var4 = var3.getObjective(par1Str);
+
+ if (var4 == null) {
+ throw new CommandException("commands.scoreboard.objectiveNotFound", new Object[] { par1Str });
+ } else if (par2 && var4.getCriteria().isReadOnly()) {
+ throw new CommandException("commands.scoreboard.objectiveReadOnly", new Object[] { par1Str });
+ } else {
+ return var4;
+ }
+ }
+
+ /**
+ * Returns the ScorePlayerTeam for the given team name.
+ */
+ protected ScorePlayerTeam getTeam(String par1Str) {
+ Scoreboard var2 = this.getScoreboardFromWorldServer();
+ ScorePlayerTeam var3 = var2.func_96508_e(par1Str);
+
+ if (var3 == null) {
+ throw new CommandException("commands.scoreboard.teamNotFound", new Object[] { par1Str });
+ } else {
+ return var3;
+ }
+ }
+
+ /**
+ * Handler for the 'scoreboard objectives add' command.
+ */
+ protected void addObjective(ICommandSender par1ICommandSender, String[] par2ArrayOfStr, int par3) {
+ String var4 = par2ArrayOfStr[par3++];
+ String var5 = par2ArrayOfStr[par3++];
+ Scoreboard var6 = this.getScoreboardFromWorldServer();
+ ScoreObjectiveCriteria var7 = (ScoreObjectiveCriteria) ScoreObjectiveCriteria.field_96643_a.get(var5);
+
+ if (var7 == null) {
+ String[] var10 = (String[]) ScoreObjectiveCriteria.field_96643_a.keySet().toArray(new String[0]);
+ throw new WrongUsageException("commands.scoreboard.objectives.add.wrongType",
+ new Object[] { joinNiceString(var10) });
+ } else if (var6.getObjective(var4) != null) {
+ throw new CommandException("commands.scoreboard.objectives.add.alreadyExists", new Object[] { var4 });
+ } else if (var4.length() > 16) {
+ throw new SyntaxErrorException("commands.scoreboard.objectives.add.tooLong",
+ new Object[] { var4, Integer.valueOf(16) });
+ } else {
+ ScoreObjective var8 = var6.func_96535_a(var4, var7);
+
+ if (par2ArrayOfStr.length > par3) {
+ String var9 = func_82360_a(par1ICommandSender, par2ArrayOfStr, par3);
+
+ if (var9.length() > 32) {
+ throw new SyntaxErrorException("commands.scoreboard.objectives.add.displayTooLong",
+ new Object[] { var9, Integer.valueOf(32) });
+ }
+
+ if (var9.length() > 0) {
+ var8.setDisplayName(var9);
+ }
+ }
+
+ notifyAdmins(par1ICommandSender, "commands.scoreboard.objectives.add.success", new Object[] { var4 });
+ }
+ }
+
+ /**
+ * Handler for the 'scoreboard teams add' command.
+ */
+ protected void addTeam(ICommandSender par1ICommandSender, String[] par2ArrayOfStr, int par3) {
+ String var4 = par2ArrayOfStr[par3++];
+ Scoreboard var5 = this.getScoreboardFromWorldServer();
+
+ if (var5.func_96508_e(var4) != null) {
+ throw new CommandException("commands.scoreboard.teams.add.alreadyExists", new Object[] { var4 });
+ } else if (var4.length() > 16) {
+ throw new SyntaxErrorException("commands.scoreboard.teams.add.tooLong",
+ new Object[] { var4, Integer.valueOf(16) });
+ } else {
+ ScorePlayerTeam var6 = var5.func_96527_f(var4);
+
+ if (par2ArrayOfStr.length > par3) {
+ String var7 = func_82360_a(par1ICommandSender, par2ArrayOfStr, par3);
+
+ if (var7.length() > 32) {
+ throw new SyntaxErrorException("commands.scoreboard.teams.add.displayTooLong",
+ new Object[] { var7, Integer.valueOf(32) });
+ }
+
+ if (var7.length() > 0) {
+ var6.func_96664_a(var7);
+ }
+ }
+
+ notifyAdmins(par1ICommandSender, "commands.scoreboard.teams.add.success", new Object[] { var4 });
+ }
+ }
+
+ /**
+ * Handler for the 'scoreboard teams option' command.
+ */
+ protected void setTeamOption(ICommandSender par1ICommandSender, String[] par2ArrayOfStr, int par3) {
+ ScorePlayerTeam var4 = this.getTeam(par2ArrayOfStr[par3++]);
+ String var5 = par2ArrayOfStr[par3++].toLowerCase();
+
+ if (!var5.equalsIgnoreCase("color") && !var5.equalsIgnoreCase("friendlyfire")
+ && !var5.equalsIgnoreCase("seeFriendlyInvisibles")) {
+ throw new WrongUsageException("commands.scoreboard.teams.option.usage", new Object[0]);
+ } else if (par2ArrayOfStr.length == 4) {
+ if (var5.equalsIgnoreCase("color")) {
+ throw new WrongUsageException("commands.scoreboard.teams.option.noValue",
+ new Object[] { var5, func_96333_a(EnumChatFormatting.func_96296_a(true, false)) });
+ } else if (!var5.equalsIgnoreCase("friendlyfire") && !var5.equalsIgnoreCase("seeFriendlyInvisibles")) {
+ throw new WrongUsageException("commands.scoreboard.teams.option.usage", new Object[0]);
+ } else {
+ throw new WrongUsageException("commands.scoreboard.teams.option.noValue",
+ new Object[] { var5, func_96333_a(Arrays.asList(new String[] { "true", "false" })) });
+ }
+ } else {
+ String var6 = par2ArrayOfStr[par3++];
+
+ if (var5.equalsIgnoreCase("color")) {
+ EnumChatFormatting var7 = EnumChatFormatting.func_96300_b(var6);
+
+ if (var6 == null) {
+ throw new WrongUsageException("commands.scoreboard.teams.option.noValue",
+ new Object[] { var5, func_96333_a(EnumChatFormatting.func_96296_a(true, false)) });
+ }
+
+ var4.func_96666_b(var7.toString());
+ var4.func_96662_c(EnumChatFormatting.RESET.toString());
+ } else if (var5.equalsIgnoreCase("friendlyfire")) {
+ if (!var6.equalsIgnoreCase("true") && !var6.equalsIgnoreCase("false")) {
+ throw new WrongUsageException("commands.scoreboard.teams.option.noValue",
+ new Object[] { var5, func_96333_a(Arrays.asList(new String[] { "true", "false" })) });
+ }
+
+ var4.func_96660_a(var6.equalsIgnoreCase("true"));
+ } else if (var5.equalsIgnoreCase("seeFriendlyInvisibles")) {
+ if (!var6.equalsIgnoreCase("true") && !var6.equalsIgnoreCase("false")) {
+ throw new WrongUsageException("commands.scoreboard.teams.option.noValue",
+ new Object[] { var5, func_96333_a(Arrays.asList(new String[] { "true", "false" })) });
+ }
+
+ var4.func_98300_b(var6.equalsIgnoreCase("true"));
+ }
+
+ notifyAdmins(par1ICommandSender, "commands.scoreboard.teams.option.success",
+ new Object[] { var5, var4.func_96661_b(), var6 });
+ }
+ }
+
+ /**
+ * Handler for the 'scoreboard teams remove' command.
+ */
+ protected void removeTeam(ICommandSender par1ICommandSender, String[] par2ArrayOfStr, int par3) {
+ Scoreboard var4 = this.getScoreboardFromWorldServer();
+ ScorePlayerTeam var5 = this.getTeam(par2ArrayOfStr[par3++]);
+ var4.func_96511_d(var5);
+ notifyAdmins(par1ICommandSender, "commands.scoreboard.teams.remove.success",
+ new Object[] { var5.func_96661_b() });
+ }
+
+ /**
+ * Handler for the 'scoreboard teams list' command.
+ */
+ protected void getTeamList(ICommandSender par1ICommandSender, String[] par2ArrayOfStr, int par3) {
+ Scoreboard var4 = this.getScoreboardFromWorldServer();
+
+ if (par2ArrayOfStr.length > par3) {
+ ScorePlayerTeam var5 = this.getTeam(par2ArrayOfStr[par3++]);
+ Collection var6 = var5.getMembershipCollection();
+
+ if (var6.size() <= 0) {
+ throw new CommandException("commands.scoreboard.teams.list.player.empty",
+ new Object[] { var5.func_96661_b() });
+ }
+
+ par1ICommandSender.sendChatToPlayer(EnumChatFormatting.DARK_GREEN
+ + par1ICommandSender.translateString("commands.scoreboard.teams.list.player.count",
+ new Object[] { Integer.valueOf(var6.size()), var5.func_96661_b() }));
+ par1ICommandSender.sendChatToPlayer(joinNiceString(var6.toArray()));
+ } else {
+ Collection var8 = var4.func_96525_g();
+
+ if (var8.size() <= 0) {
+ throw new CommandException("commands.scoreboard.teams.list.empty", new Object[0]);
+ }
+
+ par1ICommandSender.sendChatToPlayer(EnumChatFormatting.DARK_GREEN + par1ICommandSender.translateString(
+ "commands.scoreboard.teams.list.count", new Object[] { Integer.valueOf(var8.size()) }));
+ Iterator var9 = var8.iterator();
+
+ while (var9.hasNext()) {
+ ScorePlayerTeam var7 = (ScorePlayerTeam) var9.next();
+ par1ICommandSender.sendChatToPlayer(par1ICommandSender
+ .translateString("commands.scoreboard.teams.list.entry", new Object[] { var7.func_96661_b(),
+ var7.func_96669_c(), Integer.valueOf(var7.getMembershipCollection().size()) }));
+ }
+ }
+ }
+
+ /**
+ * Handler for the 'scoreboard teams join' command.
+ */
+ protected void joinTeam(ICommandSender par1ICommandSender, String[] par2ArrayOfStr, int par3) {
+ Scoreboard var4 = this.getScoreboardFromWorldServer();
+ ScorePlayerTeam var5 = var4.func_96508_e(par2ArrayOfStr[par3++]);
+ HashSet var6 = new HashSet();
+ String var7;
+
+ if (par1ICommandSender instanceof EntityPlayer && par3 == par2ArrayOfStr.length) {
+ var7 = getCommandSenderAsPlayer(par1ICommandSender).getEntityName();
+ var4.func_96521_a(var7, var5);
+ var6.add(var7);
+ } else {
+ while (par3 < par2ArrayOfStr.length) {
+ var7 = func_96332_d(par1ICommandSender, par2ArrayOfStr[par3++]);
+ var4.func_96521_a(var7, var5);
+ var6.add(var7);
+ }
+ }
+
+ if (!var6.isEmpty()) {
+ notifyAdmins(par1ICommandSender, "commands.scoreboard.teams.join.success", new Object[] {
+ Integer.valueOf(var6.size()), var5.func_96661_b(), joinNiceString(var6.toArray(new String[0])) });
+ }
+ }
+
+ /**
+ * Handler for the 'scoreboard teams leave' command.
+ */
+ protected void leaveTeam(ICommandSender par1ICommandSender, String[] par2ArrayOfStr, int par3) {
+ Scoreboard var4 = this.getScoreboardFromWorldServer();
+ HashSet var5 = new HashSet();
+ HashSet var6 = new HashSet();
+ String var7;
+
+ if (par1ICommandSender instanceof EntityPlayer && par3 == par2ArrayOfStr.length) {
+ var7 = getCommandSenderAsPlayer(par1ICommandSender).getEntityName();
+
+ if (var4.func_96524_g(var7)) {
+ var5.add(var7);
+ } else {
+ var6.add(var7);
+ }
+ } else {
+ while (par3 < par2ArrayOfStr.length) {
+ var7 = func_96332_d(par1ICommandSender, par2ArrayOfStr[par3++]);
+
+ if (var4.func_96524_g(var7)) {
+ var5.add(var7);
+ } else {
+ var6.add(var7);
+ }
+ }
+ }
+
+ if (!var5.isEmpty()) {
+ notifyAdmins(par1ICommandSender, "commands.scoreboard.teams.leave.success",
+ new Object[] { Integer.valueOf(var5.size()), joinNiceString(var5.toArray(new String[0])) });
+ }
+
+ if (!var6.isEmpty()) {
+ throw new CommandException("commands.scoreboard.teams.leave.failure",
+ new Object[] { Integer.valueOf(var6.size()), joinNiceString(var6.toArray(new String[0])) });
+ }
+ }
+
+ /**
+ * Handler for the 'scoreboard teams empty' command.
+ */
+ protected void emptyTeam(ICommandSender par1ICommandSender, String[] par2ArrayOfStr, int par3) {
+ Scoreboard var4 = this.getScoreboardFromWorldServer();
+ ScorePlayerTeam var5 = this.getTeam(par2ArrayOfStr[par3++]);
+ ArrayList var6 = new ArrayList(var5.getMembershipCollection());
+
+ if (var6.isEmpty()) {
+ throw new CommandException("commands.scoreboard.teams.empty.alreadyEmpty",
+ new Object[] { var5.func_96661_b() });
+ } else {
+ Iterator var7 = var6.iterator();
+
+ while (var7.hasNext()) {
+ String var8 = (String) var7.next();
+ var4.removePlayerFromTeam(var8, var5);
+ }
+
+ notifyAdmins(par1ICommandSender, "commands.scoreboard.teams.empty.success",
+ new Object[] { Integer.valueOf(var6.size()), var5.func_96661_b() });
+ }
+ }
+
+ /**
+ * Handler for the 'scoreboard objectives remove' command.
+ */
+ protected void removeObjective(ICommandSender par1ICommandSender, String par2Str) {
+ Scoreboard var3 = this.getScoreboardFromWorldServer();
+ ScoreObjective var4 = this.getScoreObjective(par2Str, false);
+ var3.func_96519_k(var4);
+ notifyAdmins(par1ICommandSender, "commands.scoreboard.objectives.remove.success", new Object[] { par2Str });
+ }
+
+ /**
+ * Handler for the 'scoreboard objectives list' command.
+ */
+ protected void getObjectivesList(ICommandSender par1ICommandSender) {
+ Scoreboard var2 = this.getScoreboardFromWorldServer();
+ Collection var3 = var2.getScoreObjectives();
+
+ if (var3.size() <= 0) {
+ throw new CommandException("commands.scoreboard.objectives.list.empty", new Object[0]);
+ } else {
+ par1ICommandSender.sendChatToPlayer(EnumChatFormatting.DARK_GREEN + par1ICommandSender.translateString(
+ "commands.scoreboard.objectives.list.count", new Object[] { Integer.valueOf(var3.size()) }));
+ Iterator var4 = var3.iterator();
+
+ while (var4.hasNext()) {
+ ScoreObjective var5 = (ScoreObjective) var4.next();
+ par1ICommandSender.sendChatToPlayer(par1ICommandSender.translateString(
+ "commands.scoreboard.objectives.list.entry",
+ new Object[] { var5.getName(), var5.getDisplayName(), var5.getCriteria().func_96636_a() }));
+ }
+ }
+ }
+
+ /**
+ * Handler for the 'scoreboard objectives setdisplay' command.
+ */
+ protected void setObjectivesDisplay(ICommandSender par1ICommandSender, String[] par2ArrayOfStr, int par3) {
+ Scoreboard var4 = this.getScoreboardFromWorldServer();
+ String var5 = par2ArrayOfStr[par3++];
+ int var6 = Scoreboard.getObjectiveDisplaySlotNumber(var5);
+ ScoreObjective var7 = null;
+
+ if (par2ArrayOfStr.length == 4) {
+ var7 = this.getScoreObjective(par2ArrayOfStr[par3++], false);
+ }
+
+ if (var6 < 0) {
+ throw new CommandException("commands.scoreboard.objectives.setdisplay.invalidSlot", new Object[] { var5 });
+ } else {
+ var4.func_96530_a(var6, var7);
+
+ if (var7 != null) {
+ notifyAdmins(par1ICommandSender, "commands.scoreboard.objectives.setdisplay.successSet",
+ new Object[] { Scoreboard.getObjectiveDisplaySlot(var6), var7.getName() });
+ } else {
+ notifyAdmins(par1ICommandSender, "commands.scoreboard.objectives.setdisplay.successCleared",
+ new Object[] { Scoreboard.getObjectiveDisplaySlot(var6) });
+ }
+ }
+ }
+
+ /**
+ * Handler for the 'scoreboard players list' command.
+ */
+ protected void listPlayers(ICommandSender par1ICommandSender, String[] par2ArrayOfStr, int par3) {
+ Scoreboard var4 = this.getScoreboardFromWorldServer();
+
+ if (par2ArrayOfStr.length > par3) {
+ String var5 = func_96332_d(par1ICommandSender, par2ArrayOfStr[par3++]);
+ Map var6 = var4.func_96510_d(var5);
+
+ if (var6.size() <= 0) {
+ throw new CommandException("commands.scoreboard.players.list.player.empty", new Object[] { var5 });
+ }
+
+ par1ICommandSender.sendChatToPlayer(EnumChatFormatting.DARK_GREEN
+ + par1ICommandSender.translateString("commands.scoreboard.players.list.player.count",
+ new Object[] { Integer.valueOf(var6.size()), var5 }));
+ Iterator var7 = var6.values().iterator();
+
+ while (var7.hasNext()) {
+ Score var8 = (Score) var7.next();
+ par1ICommandSender.sendChatToPlayer(
+ par1ICommandSender.translateString("commands.scoreboard.players.list.player.entry",
+ new Object[] { Integer.valueOf(var8.func_96652_c()),
+ var8.func_96645_d().getDisplayName(), var8.func_96645_d().getName() }));
+ }
+ } else {
+ Collection var9 = var4.getObjectiveNames();
+
+ if (var9.size() <= 0) {
+ throw new CommandException("commands.scoreboard.players.list.empty", new Object[0]);
+ }
+
+ par1ICommandSender.sendChatToPlayer(EnumChatFormatting.DARK_GREEN + par1ICommandSender.translateString(
+ "commands.scoreboard.players.list.count", new Object[] { Integer.valueOf(var9.size()) }));
+ par1ICommandSender.sendChatToPlayer(joinNiceString(var9.toArray()));
+ }
+ }
+
+ /**
+ * Handler for the 'scoreboard players [add|remove|set]' commands.
+ */
+ protected void setPlayerScore(ICommandSender par1ICommandSender, String[] par2ArrayOfStr, int par3) {
+ String var4 = par2ArrayOfStr[par3 - 1];
+ String var5 = func_96332_d(par1ICommandSender, par2ArrayOfStr[par3++]);
+ ScoreObjective var6 = this.getScoreObjective(par2ArrayOfStr[par3++], true);
+ int var7 = var4.equalsIgnoreCase("set") ? parseInt(par1ICommandSender, par2ArrayOfStr[par3++])
+ : parseIntWithMin(par1ICommandSender, par2ArrayOfStr[par3++], 1);
+ Scoreboard var8 = this.getScoreboardFromWorldServer();
+ Score var9 = var8.func_96529_a(var5, var6);
+
+ if (var4.equalsIgnoreCase("set")) {
+ var9.func_96647_c(var7);
+ } else if (var4.equalsIgnoreCase("add")) {
+ var9.func_96649_a(var7);
+ } else {
+ var9.func_96646_b(var7);
+ }
+
+ notifyAdmins(par1ICommandSender, "commands.scoreboard.players.set.success",
+ new Object[] { var6.getName(), var5, Integer.valueOf(var9.func_96652_c()) });
+ }
+
+ /**
+ * Handler for the 'scoreboard players reset' command.
+ */
+ protected void resetPlayerScore(ICommandSender par1ICommandSender, String[] par2ArrayOfStr, int par3) {
+ Scoreboard var4 = this.getScoreboardFromWorldServer();
+ String var5 = func_96332_d(par1ICommandSender, par2ArrayOfStr[par3++]);
+ var4.func_96515_c(var5);
+ notifyAdmins(par1ICommandSender, "commands.scoreboard.players.reset.success", new Object[] { var5 });
+ }
+
+ /**
+ * Adds the strings available in this command to the given list of tab
+ * completion options.
+ */
+ public List addTabCompletionOptions(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) {
+ if (par2ArrayOfStr.length == 1) {
+ return getListOfStringsMatchingLastWord(par2ArrayOfStr, new String[] { "objectives", "players", "teams" });
+ } else {
+ if (par2ArrayOfStr[0].equalsIgnoreCase("objectives")) {
+ if (par2ArrayOfStr.length == 2) {
+ return getListOfStringsMatchingLastWord(par2ArrayOfStr,
+ new String[] { "list", "add", "remove", "setdisplay" });
+ }
+
+ if (par2ArrayOfStr[1].equalsIgnoreCase("add")) {
+ if (par2ArrayOfStr.length == 4) {
+ return getListOfStringsFromIterableMatchingLastWord(par2ArrayOfStr,
+ ScoreObjectiveCriteria.field_96643_a.keySet());
+ }
+ } else if (par2ArrayOfStr[1].equalsIgnoreCase("remove")) {
+ if (par2ArrayOfStr.length == 3) {
+ return getListOfStringsFromIterableMatchingLastWord(par2ArrayOfStr,
+ this.getScoreObjectivesList(false));
+ }
+ } else if (par2ArrayOfStr[1].equalsIgnoreCase("setdisplay")) {
+ if (par2ArrayOfStr.length == 3) {
+ return getListOfStringsMatchingLastWord(par2ArrayOfStr,
+ new String[] { "list", "sidebar", "belowName" });
+ }
+
+ if (par2ArrayOfStr.length == 4) {
+ return getListOfStringsFromIterableMatchingLastWord(par2ArrayOfStr,
+ this.getScoreObjectivesList(false));
+ }
+ }
+ } else if (par2ArrayOfStr[0].equalsIgnoreCase("players")) {
+ if (par2ArrayOfStr.length == 2) {
+ return getListOfStringsMatchingLastWord(par2ArrayOfStr,
+ new String[] { "set", "add", "remove", "reset", "list" });
+ }
+
+ if (!par2ArrayOfStr[1].equalsIgnoreCase("set") && !par2ArrayOfStr[1].equalsIgnoreCase("add")
+ && !par2ArrayOfStr[1].equalsIgnoreCase("remove")) {
+ if ((par2ArrayOfStr[1].equalsIgnoreCase("reset") || par2ArrayOfStr[1].equalsIgnoreCase("list"))
+ && par2ArrayOfStr.length == 3) {
+ return getListOfStringsFromIterableMatchingLastWord(par2ArrayOfStr,
+ this.getScoreboardFromWorldServer().getObjectiveNames());
+ }
+ } else {
+ if (par2ArrayOfStr.length == 3) {
+ return getListOfStringsMatchingLastWord(par2ArrayOfStr,
+ MinecraftServer.getServer().getAllUsernames());
+ }
+
+ if (par2ArrayOfStr.length == 4) {
+ return getListOfStringsFromIterableMatchingLastWord(par2ArrayOfStr,
+ this.getScoreObjectivesList(true));
+ }
+ }
+ } else if (par2ArrayOfStr[0].equalsIgnoreCase("teams")) {
+ if (par2ArrayOfStr.length == 2) {
+ return getListOfStringsMatchingLastWord(par2ArrayOfStr,
+ new String[] { "add", "remove", "join", "leave", "empty", "list", "option" });
+ }
+
+ if (par2ArrayOfStr[1].equalsIgnoreCase("join")) {
+ if (par2ArrayOfStr.length == 3) {
+ return getListOfStringsFromIterableMatchingLastWord(par2ArrayOfStr,
+ this.getScoreboardFromWorldServer().func_96531_f());
+ }
+
+ if (par2ArrayOfStr.length >= 4) {
+ return getListOfStringsMatchingLastWord(par2ArrayOfStr,
+ MinecraftServer.getServer().getAllUsernames());
+ }
+ } else {
+ if (par2ArrayOfStr[1].equalsIgnoreCase("leave")) {
+ return getListOfStringsMatchingLastWord(par2ArrayOfStr,
+ MinecraftServer.getServer().getAllUsernames());
+ }
+
+ if (!par2ArrayOfStr[1].equalsIgnoreCase("empty") && !par2ArrayOfStr[1].equalsIgnoreCase("list")
+ && !par2ArrayOfStr[1].equalsIgnoreCase("remove")) {
+ if (par2ArrayOfStr[1].equalsIgnoreCase("option")) {
+ if (par2ArrayOfStr.length == 3) {
+ return getListOfStringsFromIterableMatchingLastWord(par2ArrayOfStr,
+ this.getScoreboardFromWorldServer().func_96531_f());
+ }
+
+ if (par2ArrayOfStr.length == 4) {
+ return getListOfStringsMatchingLastWord(par2ArrayOfStr,
+ new String[] { "color", "friendlyfire", "seeFriendlyInvisibles" });
+ }
+
+ if (par2ArrayOfStr.length == 5) {
+ if (par2ArrayOfStr[3].equalsIgnoreCase("color")) {
+ return getListOfStringsFromIterableMatchingLastWord(par2ArrayOfStr,
+ EnumChatFormatting.func_96296_a(true, false));
+ }
+
+ if (par2ArrayOfStr[3].equalsIgnoreCase("friendlyfire")
+ || par2ArrayOfStr[3].equalsIgnoreCase("seeFriendlyInvisibles")) {
+ return getListOfStringsMatchingLastWord(par2ArrayOfStr,
+ new String[] { "true", "false" });
+ }
+ }
+ }
+ } else if (par2ArrayOfStr.length == 3) {
+ return getListOfStringsFromIterableMatchingLastWord(par2ArrayOfStr,
+ this.getScoreboardFromWorldServer().func_96531_f());
+ }
+ }
+ }
+
+ return null;
+ }
+ }
+
+ /**
+ * If the parameter is true, does not return read-only entries.
+ */
+ protected List getScoreObjectivesList(boolean par1) {
+ Collection var2 = this.getScoreboardFromWorldServer().getScoreObjectives();
+ ArrayList var3 = new ArrayList();
+ Iterator var4 = var2.iterator();
+
+ while (var4.hasNext()) {
+ ScoreObjective var5 = (ScoreObjective) var4.next();
+
+ if (!par1 || !var5.getCriteria().isReadOnly()) {
+ var3.add(var5.getName());
+ }
+ }
+
+ return var3;
+ }
+
+ /**
+ * Return whether the specified command parameter index is a username parameter.
+ */
+ public boolean isUsernameIndex(String[] par1ArrayOfStr, int par2) {
+ return par1ArrayOfStr[0].equalsIgnoreCase("players") ? par2 == 2
+ : (!par1ArrayOfStr[0].equalsIgnoreCase("teams") ? false : par2 == 2 || par2 == 3);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ServerCommandTestFor.java b/sp-server/src/main/java/net/minecraft/src/ServerCommandTestFor.java
new file mode 100644
index 0000000..330a8cf
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ServerCommandTestFor.java
@@ -0,0 +1,31 @@
+package net.minecraft.src;
+
+public class ServerCommandTestFor extends CommandBase {
+ public String getCommandName() {
+ return "testfor";
+ }
+
+ /**
+ * Return the required permission level for this command.
+ */
+ public int getRequiredPermissionLevel() {
+ return 2;
+ }
+
+ public void processCommand(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) {
+ if (par2ArrayOfStr.length != 1) {
+ throw new WrongUsageException("commands.testfor.usage", new Object[0]);
+ } else if (!(par1ICommandSender instanceof TileEntityCommandBlock)) {
+ throw new CommandException("commands.testfor.failed", new Object[0]);
+ } else {
+ func_82359_c(par1ICommandSender, par2ArrayOfStr[0]);
+ }
+ }
+
+ /**
+ * Return whether the specified command parameter index is a username parameter.
+ */
+ public boolean isUsernameIndex(String[] par1ArrayOfStr, int par2) {
+ return par2 == 0;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ServerConfigurationManager.java b/sp-server/src/main/java/net/minecraft/src/ServerConfigurationManager.java
new file mode 100644
index 0000000..59f99aa
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ServerConfigurationManager.java
@@ -0,0 +1,918 @@
+package net.minecraft.src;
+
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import net.lax1dude.eaglercraft.sp.SkinsPlugin;
+import net.lax1dude.eaglercraft.sp.VoiceChatPlugin;
+import net.minecraft.server.MinecraftServer;
+
+public class ServerConfigurationManager {
+ private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd \'at\' HH:mm:ss z");
+
+ /** Reference to the MinecraftServer object. */
+ private final MinecraftServer mcServer;
+
+ /** A list of player entities that exist on this server. */
+ public final List playerEntityList = new ArrayList();
+
+ /** A set containing the OPs. */
+ private Set ops = new HashSet();
+
+ /** The Set of all whitelisted players. */
+ private Set whiteListedPlayers = new HashSet();
+
+ /** Reference to the PlayerNBTManager object. */
+ private IPlayerFileData playerNBTManagerObj;
+
+ /**
+ * Server setting to only allow OPs and whitelisted players to join the server.
+ */
+ private boolean whiteListEnforced;
+
+ /** The maximum number of players that can be connected at a time. */
+ protected int maxPlayers;
+ protected int viewDistance;
+ private EnumGameType gameType;
+
+ /** True if all players are allowed to use commands (cheats). */
+ private boolean commandsAllowedForAll;
+
+ /**
+ * index into playerEntities of player to ping, updated every tick; currently
+ * hardcoded to max at 200 players
+ */
+ private int playerPingIndex = 0;
+
+ private EnumGameType lanGamemode = EnumGameType.SURVIVAL;
+ private boolean lanCheats = false;
+
+ public ServerConfigurationManager(MinecraftServer par1MinecraftServer) {
+ this.mcServer = par1MinecraftServer;
+ this.maxPlayers = 50;
+ }
+
+ public void initializeConnectionToPlayer(INetworkManager par1INetworkManager, EntityPlayerMP par2EntityPlayerMP) {
+ if(par2EntityPlayerMP.username.equals(mcServer.getServerOwner())) {
+ viewDistance = par2EntityPlayerMP.renderDistance;
+ }
+ NBTTagCompound var3 = this.readPlayerDataFromFile(par2EntityPlayerMP);
+ par2EntityPlayerMP.setWorld(this.mcServer.worldServerForDimension(par2EntityPlayerMP.dimension));
+ par2EntityPlayerMP.theItemInWorldManager.setWorld((WorldServer) par2EntityPlayerMP.worldObj);
+ String var4 = "local";
+
+ this.mcServer.getLogAgent()
+ .func_98233_a(par2EntityPlayerMP.username + "[" + var4 + "] logged in with entity id "
+ + par2EntityPlayerMP.entityId + " at (" + par2EntityPlayerMP.posX + ", "
+ + par2EntityPlayerMP.posY + ", " + par2EntityPlayerMP.posZ + ")");
+ WorldServer var5 = this.mcServer.worldServerForDimension(par2EntityPlayerMP.dimension);
+ ChunkCoordinates var6 = var5.getSpawnPoint();
+ this.func_72381_a(par2EntityPlayerMP, (EntityPlayerMP) null, var5);
+ NetServerHandler var7 = new NetServerHandler(this.mcServer, par1INetworkManager, par2EntityPlayerMP);
+ var7.sendPacket(new Packet1Login(par2EntityPlayerMP.entityId, var5.getWorldInfo().getTerrainType(),
+ par2EntityPlayerMP.theItemInWorldManager.getGameType(), var5.getWorldInfo().isHardcoreModeEnabled(),
+ var5.provider.dimensionId, var5.difficultySetting, var5.getHeight(), this.getMaxPlayers()));
+ var7.sendPacket(new Packet6SpawnPosition(var6.posX, var6.posY, var6.posZ));
+ var7.sendPacket(new Packet202PlayerAbilities(par2EntityPlayerMP.capabilities));
+ var7.sendPacket(new Packet16BlockItemSwitch(par2EntityPlayerMP.inventory.currentItem));
+ this.func_96456_a((ServerScoreboard) var5.getScoreboard(), par2EntityPlayerMP);
+ this.updateTimeAndWeatherForPlayer(par2EntityPlayerMP, var5);
+ this.sendPacketToAllPlayers(new Packet3Chat(EnumChatFormatting.YELLOW
+ + par2EntityPlayerMP.getTranslatedEntityName() + EnumChatFormatting.YELLOW + " joined the game."));
+ this.playerLoggedIn(par2EntityPlayerMP);
+ var7.setPlayerLocation(par2EntityPlayerMP.posX, par2EntityPlayerMP.posY, par2EntityPlayerMP.posZ,
+ par2EntityPlayerMP.rotationYaw, par2EntityPlayerMP.rotationPitch);
+ //this.mcServer.getNetworkThread().addPlayer(var7);
+ var7.sendPacket(new Packet4UpdateTime(var5.getTotalWorldTime(), var5.getWorldTime()));
+ VoiceChatPlugin.handleConnect(par2EntityPlayerMP);
+
+ //if (this.mcServer.getTexturePack().length() > 0) {
+ // par2EntityPlayerMP.requestTexturePackLoad(this.mcServer.getTexturePack(), this.mcServer.textureSize());
+ //}
+
+ Iterator var8 = par2EntityPlayerMP.getActivePotionEffects().iterator();
+
+ while (var8.hasNext()) {
+ PotionEffect var9 = (PotionEffect) var8.next();
+ var7.sendPacket(new Packet41EntityEffect(par2EntityPlayerMP.entityId, var9));
+ }
+
+ par2EntityPlayerMP.addSelfToInternalCraftingInventory();
+
+ if (var3 != null && var3.hasKey("Riding")) {
+ Entity var10 = EntityList.createEntityFromNBT(var3.getCompoundTag("Riding"), var5);
+
+ if (var10 != null) {
+ var10.field_98038_p = true;
+ var5.spawnEntityInWorld(var10);
+ par2EntityPlayerMP.mountEntity(var10);
+ var10.field_98038_p = false;
+ }
+ }
+ }
+
+ protected void func_96456_a(ServerScoreboard par1ServerScoreboard, EntityPlayerMP par2EntityPlayerMP) {
+ HashSet var3 = new HashSet();
+ Iterator var4 = par1ServerScoreboard.func_96525_g().iterator();
+
+ while (var4.hasNext()) {
+ ScorePlayerTeam var5 = (ScorePlayerTeam) var4.next();
+ par2EntityPlayerMP.playerNetServerHandler.sendPacket(new Packet209SetPlayerTeam(var5, 0));
+ }
+
+ for (int var9 = 0; var9 < 3; ++var9) {
+ ScoreObjective var10 = par1ServerScoreboard.func_96539_a(var9);
+
+ if (var10 != null && !var3.contains(var10)) {
+ List var6 = par1ServerScoreboard.func_96550_d(var10);
+ Iterator var7 = var6.iterator();
+
+ while (var7.hasNext()) {
+ Packet var8 = (Packet) var7.next();
+ par2EntityPlayerMP.playerNetServerHandler.sendPacket(var8);
+ }
+
+ var3.add(var10);
+ }
+ }
+ }
+
+ /**
+ * Sets the NBT manager to the one for the WorldServer given.
+ */
+ public void setPlayerManager(WorldServer[] par1ArrayOfWorldServer) {
+ this.playerNBTManagerObj = par1ArrayOfWorldServer[0].getSaveHandler().getPlayerNBTManager();
+ }
+
+ public void func_72375_a(EntityPlayerMP par1EntityPlayerMP, WorldServer par2WorldServer) {
+ WorldServer var3 = par1EntityPlayerMP.getServerForPlayer();
+
+ if (par2WorldServer != null) {
+ par2WorldServer.getPlayerManager().removePlayer(par1EntityPlayerMP);
+ }
+
+ var3.getPlayerManager().addPlayer(par1EntityPlayerMP);
+ var3.theChunkProviderServer.loadChunk((int) par1EntityPlayerMP.posX >> 4, (int) par1EntityPlayerMP.posZ >> 4);
+ }
+
+ public int getEntityViewDistance() {
+ return PlayerManager.getFurthestViewableBlock(this.getViewDistance());
+ }
+
+ /**
+ * called during player login. reads the player information from disk.
+ */
+ public NBTTagCompound readPlayerDataFromFile(EntityPlayerMP par1EntityPlayerMP) {
+ NBTTagCompound var2 = this.mcServer.worldServers[0].getWorldInfo().getPlayerNBTTagCompound();
+ NBTTagCompound var3;
+
+ if (par1EntityPlayerMP.getCommandSenderName().equals(this.mcServer.getServerOwner()) && var2 != null) {
+ par1EntityPlayerMP.readFromNBT(var2);
+ var3 = var2;
+ System.out.println("loading single player");
+ } else {
+ var3 = this.playerNBTManagerObj.readPlayerData(par1EntityPlayerMP);
+ }
+
+ return var3;
+ }
+
+ /**
+ * also stores the NBTTags if this is an intergratedPlayerList
+ */
+ protected void writePlayerData(EntityPlayerMP par1EntityPlayerMP) {
+ this.playerNBTManagerObj.writePlayerData(par1EntityPlayerMP);
+ }
+
+ /**
+ * Called when a player successfully logs in. Reads player data from disk and
+ * inserts the player into the world.
+ */
+ public void playerLoggedIn(EntityPlayerMP par1EntityPlayerMP) {
+ this.sendPacketToAllPlayers(new Packet201PlayerInfo(par1EntityPlayerMP.username, true, 1000));
+ this.playerEntityList.add(par1EntityPlayerMP);
+ WorldServer var2 = this.mcServer.worldServerForDimension(par1EntityPlayerMP.dimension);
+ var2.spawnEntityInWorld(par1EntityPlayerMP);
+ this.func_72375_a(par1EntityPlayerMP, (WorldServer) null);
+
+ for (int var3 = 0; var3 < this.playerEntityList.size(); ++var3) {
+ EntityPlayerMP var4 = (EntityPlayerMP) this.playerEntityList.get(var3);
+ par1EntityPlayerMP.playerNetServerHandler
+ .sendPacket(new Packet201PlayerInfo(var4.username, true, var4.ping));
+ }
+ }
+
+ /**
+ * using player's dimension, update their movement when in a vehicle (e.g. cart,
+ * boat)
+ */
+ public void serverUpdateMountedMovingPlayer(EntityPlayerMP par1EntityPlayerMP) {
+ par1EntityPlayerMP.getServerForPlayer().getPlayerManager().updateMountedMovingPlayer(par1EntityPlayerMP);
+ }
+
+ /**
+ * Called when a player disconnects from the game. Writes player data to disk
+ * and removes them from the world.
+ */
+ public void playerLoggedOut(EntityPlayerMP par1EntityPlayerMP) {
+ this.writePlayerData(par1EntityPlayerMP);
+ WorldServer var2 = par1EntityPlayerMP.getServerForPlayer();
+
+ if (par1EntityPlayerMP.ridingEntity != null) {
+ var2.removeEntity(par1EntityPlayerMP.ridingEntity);
+ System.out.println("removing player mount");
+ }
+
+ var2.removeEntity(par1EntityPlayerMP);
+ var2.getPlayerManager().removePlayer(par1EntityPlayerMP);
+ this.playerEntityList.remove(par1EntityPlayerMP);
+ this.sendPacketToAllPlayers(new Packet201PlayerInfo(par1EntityPlayerMP.username, false, 9999));
+ SkinsPlugin.handleDisconnect(par1EntityPlayerMP);
+ VoiceChatPlugin.handleDisconnect(par1EntityPlayerMP);
+ }
+
+ /**
+ * checks ban-lists, then white-lists, then space for the server. Returns null
+ * on success, or an error message
+ */
+ public String allowUserToConnect(String par2Str) {
+ if(this.playerEntityList.size() >= this.maxPlayers) {
+ return "The server is full!";
+ }else {
+ for(EntityPlayerMP pp : (List)this.playerEntityList) {
+ if(pp.username.equalsIgnoreCase(par2Str)) {
+ return "Someone with your username is already on this world";
+ }
+ }
+ return null;
+ }
+ }
+
+ /**
+ * also checks for multiple logins
+ */
+ public EntityPlayerMP createPlayerForUser(String par1Str) {
+ ArrayList var2 = new ArrayList();
+ EntityPlayerMP var4;
+
+ for (int var3 = 0; var3 < this.playerEntityList.size(); ++var3) {
+ var4 = (EntityPlayerMP) this.playerEntityList.get(var3);
+
+ if (var4.username.equalsIgnoreCase(par1Str)) {
+ var2.add(var4);
+ }
+ }
+
+ Iterator var5 = var2.iterator();
+
+ while (var5.hasNext()) {
+ var4 = (EntityPlayerMP) var5.next();
+ var4.playerNetServerHandler.kickPlayer("You logged in from another location");
+ }
+
+ Object var6 = new ItemInWorldManager(this.mcServer.worldServerForDimension(0));
+
+ return new EntityPlayerMP(this.mcServer, this.mcServer.worldServerForDimension(0), par1Str, (ItemInWorldManager) var6);
+ }
+
+ /**
+ * Called on render distance change
+ */
+ public void updateOnRenderDistanceChange(EntityPlayerMP par1EntityPlayerMP) {
+ double posX = par1EntityPlayerMP.posX;
+ double posY = par1EntityPlayerMP.posY;
+ double posZ = par1EntityPlayerMP.posZ;
+ float rotationYaw = par1EntityPlayerMP.rotationYaw;
+ float rotationPitch = par1EntityPlayerMP.rotationPitch;
+
+ par1EntityPlayerMP.getServerForPlayer().getEntityTracker().removePlayerFromTrackers(par1EntityPlayerMP, true);
+ par1EntityPlayerMP.getServerForPlayer().getEntityTracker().untrackEntity(par1EntityPlayerMP, true);
+ par1EntityPlayerMP.getServerForPlayer().getPlayerManager().removePlayer(par1EntityPlayerMP);
+ this.playerEntityList.remove(par1EntityPlayerMP);
+
+ WorldServer var8 = this.mcServer.worldServerForDimension(par1EntityPlayerMP.dimension);
+
+ par1EntityPlayerMP.setLocationAndAngles(posX, posY, posZ, rotationYaw, rotationPitch);
+
+ var8.theChunkProviderServer.loadChunk((int) par1EntityPlayerMP.posX >> 4, (int) par1EntityPlayerMP.posZ >> 4);
+
+ // see https://wiki.vg/index.php?title=Protocol&oldid=1092
+ // footnotes of packet Respawn (0x09)
+ par1EntityPlayerMP.playerNetServerHandler.sendPacket(new Packet9Respawn(((par1EntityPlayerMP.dimension + 2) % 3) - 1,
+ (byte) par1EntityPlayerMP.worldObj.difficultySetting, par1EntityPlayerMP.worldObj.getWorldInfo().getTerrainType(),
+ 69, par1EntityPlayerMP.theItemInWorldManager.getGameType()));
+ par1EntityPlayerMP.playerNetServerHandler.setPlayerLocation(posX, posY, posZ, rotationYaw, rotationPitch);
+ par1EntityPlayerMP.playerNetServerHandler.sendPacket(new Packet9Respawn(par1EntityPlayerMP.dimension,
+ (byte) par1EntityPlayerMP.worldObj.difficultySetting, par1EntityPlayerMP.worldObj.getWorldInfo().getTerrainType(),
+ 69, par1EntityPlayerMP.theItemInWorldManager.getGameType()));
+ par1EntityPlayerMP.playerNetServerHandler.setPlayerLocation(posX, posY, posZ, rotationYaw, rotationPitch);
+
+ this.updateTimeAndWeatherForPlayer(par1EntityPlayerMP, var8);
+ this.syncPlayerInventory(par1EntityPlayerMP);
+ Iterator var6 = par1EntityPlayerMP.getActivePotionEffects().iterator();
+
+ while (var6.hasNext()) {
+ PotionEffect var7 = (PotionEffect) var6.next();
+ par1EntityPlayerMP.playerNetServerHandler
+ .sendPacket(new Packet41EntityEffect(par1EntityPlayerMP.entityId, var7));
+ }
+ par1EntityPlayerMP.sendPlayerAbilities();
+ var8.getPlayerManager().addPlayer(par1EntityPlayerMP);
+ par1EntityPlayerMP.getServerForPlayer().getEntityTracker().trackEntity(par1EntityPlayerMP);
+ this.playerEntityList.add(par1EntityPlayerMP);
+ }
+
+ /**
+ * Called on respawn
+ */
+ public EntityPlayerMP recreatePlayerEntity(EntityPlayerMP par1EntityPlayerMP, int par2, boolean par3) {
+ par1EntityPlayerMP.getServerForPlayer().getEntityTracker().removePlayerFromTrackers(par1EntityPlayerMP);
+ par1EntityPlayerMP.getServerForPlayer().getEntityTracker().untrackEntity(par1EntityPlayerMP);
+ par1EntityPlayerMP.getServerForPlayer().getPlayerManager().removePlayer(par1EntityPlayerMP);
+ this.playerEntityList.remove(par1EntityPlayerMP);
+ this.mcServer.worldServerForDimension(par1EntityPlayerMP.dimension)
+ .removePlayerEntityDangerously(par1EntityPlayerMP);
+ ChunkCoordinates var4 = par1EntityPlayerMP.getBedLocation();
+ boolean var5 = par1EntityPlayerMP.isSpawnForced();
+ int startDim = par1EntityPlayerMP.dimension;
+ par1EntityPlayerMP.dimension = par2;
+ Object var6 = new ItemInWorldManager(this.mcServer.worldServerForDimension(par1EntityPlayerMP.dimension));
+
+ EntityPlayerMP var7 = new EntityPlayerMP(this.mcServer,
+ this.mcServer.worldServerForDimension(par1EntityPlayerMP.dimension), par1EntityPlayerMP.username,
+ (ItemInWorldManager) var6);
+ var7.playerNetServerHandler = par1EntityPlayerMP.playerNetServerHandler;
+ var7.clonePlayer(par1EntityPlayerMP, par3);
+ var7.entityId = par1EntityPlayerMP.entityId;
+ WorldServer var8 = this.mcServer.worldServerForDimension(par1EntityPlayerMP.dimension);
+ this.func_72381_a(var7, par1EntityPlayerMP, var8);
+ ChunkCoordinates var9;
+
+ if (var4 != null) {
+ var9 = EntityPlayer.verifyRespawnCoordinates(
+ this.mcServer.worldServerForDimension(par1EntityPlayerMP.dimension), var4, var5);
+
+ if (var9 != null) {
+ var7.setLocationAndAngles((double) ((float) var9.posX + 0.5F), (double) ((float) var9.posY + 0.1F),
+ (double) ((float) var9.posZ + 0.5F), 0.0F, 0.0F);
+ var7.setSpawnChunk(var4, var5);
+ } else {
+ var7.playerNetServerHandler.sendPacket(new Packet70GameEvent(0, 0));
+ }
+ }
+
+ var8.theChunkProviderServer.loadChunk((int) var7.posX >> 4, (int) var7.posZ >> 4);
+
+ while (!var8.getCollidingBoundingBoxes(var7, var7.boundingBox).isEmpty()) {
+ var7.setPosition(var7.posX, var7.posY + 1.0D, var7.posZ);
+ }
+
+ var7.playerNetServerHandler.sendPacket(new Packet9Respawn(var7.dimension,
+ (byte) var7.worldObj.difficultySetting, var7.worldObj.getWorldInfo().getTerrainType(),
+ var7.worldObj.getHeight(), var7.theItemInWorldManager.getGameType()));
+ var9 = var8.getSpawnPoint();
+ var7.playerNetServerHandler.setPlayerLocation(var7.posX, var7.posY, var7.posZ, var7.rotationYaw,
+ var7.rotationPitch);
+ var7.playerNetServerHandler.sendPacket(new Packet6SpawnPosition(var9.posX, var9.posY, var9.posZ));
+ var7.playerNetServerHandler
+ .sendPacket(new Packet43Experience(var7.experience, var7.experienceTotal, var7.experienceLevel));
+ this.updateTimeAndWeatherForPlayer(var7, var8);
+ var8.getPlayerManager().addPlayer(var7);
+ var8.spawnEntityInWorld(var7);
+ this.playerEntityList.add(var7);
+ var7.addSelfToInternalCraftingInventory();
+ var7.setEntityHealth(var7.getHealth());
+ return var7;
+ }
+
+ /**
+ * moves provided player from overworld to nether or vice versa
+ */
+ public void transferPlayerToDimension(EntityPlayerMP par1EntityPlayerMP, int par2) {
+ int var3 = par1EntityPlayerMP.dimension;
+ WorldServer var4 = this.mcServer.worldServerForDimension(par1EntityPlayerMP.dimension);
+ par1EntityPlayerMP.dimension = par2;
+ WorldServer var5 = this.mcServer.worldServerForDimension(par1EntityPlayerMP.dimension);
+ par1EntityPlayerMP.playerNetServerHandler.sendPacket(new Packet9Respawn(par1EntityPlayerMP.dimension,
+ (byte) par1EntityPlayerMP.worldObj.difficultySetting, var5.getWorldInfo().getTerrainType(),
+ var5.getHeight(), par1EntityPlayerMP.theItemInWorldManager.getGameType()));
+ var4.removePlayerEntityDangerously(par1EntityPlayerMP);
+ par1EntityPlayerMP.isDead = false;
+ this.transferEntityToWorld(par1EntityPlayerMP, var3, var4, var5);
+ this.func_72375_a(par1EntityPlayerMP, var4);
+ par1EntityPlayerMP.playerNetServerHandler.setPlayerLocation(par1EntityPlayerMP.posX, par1EntityPlayerMP.posY,
+ par1EntityPlayerMP.posZ, par1EntityPlayerMP.rotationYaw, par1EntityPlayerMP.rotationPitch);
+ par1EntityPlayerMP.theItemInWorldManager.setWorld(var5);
+ this.updateTimeAndWeatherForPlayer(par1EntityPlayerMP, var5);
+ this.syncPlayerInventory(par1EntityPlayerMP);
+ Iterator var6 = par1EntityPlayerMP.getActivePotionEffects().iterator();
+
+ while (var6.hasNext()) {
+ PotionEffect var7 = (PotionEffect) var6.next();
+ par1EntityPlayerMP.playerNetServerHandler
+ .sendPacket(new Packet41EntityEffect(par1EntityPlayerMP.entityId, var7));
+ }
+ }
+
+ /**
+ * Transfers an entity from a world to another world.
+ */
+ public void transferEntityToWorld(Entity par1Entity, int par2, WorldServer par3WorldServer,
+ WorldServer par4WorldServer) {
+ double var5 = par1Entity.posX;
+ double var7 = par1Entity.posZ;
+ double var9 = 8.0D;
+ double var11 = par1Entity.posX;
+ double var13 = par1Entity.posY;
+ double var15 = par1Entity.posZ;
+ float var17 = par1Entity.rotationYaw;
+
+ if (par1Entity.dimension == -1) {
+ var5 /= var9;
+ var7 /= var9;
+ par1Entity.setLocationAndAngles(var5, par1Entity.posY, var7, par1Entity.rotationYaw,
+ par1Entity.rotationPitch);
+
+ if (par1Entity.isEntityAlive()) {
+ par3WorldServer.updateEntityWithOptionalForce(par1Entity, false);
+ }
+ } else if (par1Entity.dimension == 0) {
+ var5 *= var9;
+ var7 *= var9;
+ par1Entity.setLocationAndAngles(var5, par1Entity.posY, var7, par1Entity.rotationYaw,
+ par1Entity.rotationPitch);
+
+ if (par1Entity.isEntityAlive()) {
+ par3WorldServer.updateEntityWithOptionalForce(par1Entity, false);
+ }
+ } else {
+ ChunkCoordinates var18;
+
+ if (par2 == 1) {
+ var18 = par4WorldServer.getSpawnPoint();
+ } else {
+ var18 = par4WorldServer.getEntrancePortalLocation();
+ }
+
+ var5 = (double) var18.posX;
+ par1Entity.posY = (double) var18.posY;
+ var7 = (double) var18.posZ;
+ par1Entity.setLocationAndAngles(var5, par1Entity.posY, var7, 90.0F, 0.0F);
+
+ if (par1Entity.isEntityAlive()) {
+ par3WorldServer.updateEntityWithOptionalForce(par1Entity, false);
+ }
+ }
+
+ if (par2 != 1) {
+ var5 = (double) MathHelper.clamp_int((int) var5, -29999872, 29999872);
+ var7 = (double) MathHelper.clamp_int((int) var7, -29999872, 29999872);
+
+ if (par1Entity.isEntityAlive()) {
+ par4WorldServer.spawnEntityInWorld(par1Entity);
+ par1Entity.setLocationAndAngles(var5, par1Entity.posY, var7, par1Entity.rotationYaw,
+ par1Entity.rotationPitch);
+ par4WorldServer.updateEntityWithOptionalForce(par1Entity, false);
+ par4WorldServer.getDefaultTeleporter().placeInPortal(par1Entity, var11, var13, var15, var17);
+ }
+ }
+
+ par1Entity.setWorld(par4WorldServer);
+ }
+
+ /**
+ * self explanitory
+ */
+ public void onTick() {
+ if (++this.playerPingIndex > 600) {
+ this.playerPingIndex = 0;
+ }
+
+ if (this.playerPingIndex < this.playerEntityList.size()) {
+ EntityPlayerMP var1 = (EntityPlayerMP) this.playerEntityList.get(this.playerPingIndex);
+ this.sendPacketToAllPlayers(new Packet201PlayerInfo(var1.username, true, var1.ping));
+ }
+ }
+
+ /**
+ * sends a packet to all players
+ */
+ public void sendPacketToAllPlayers(Packet par1Packet) {
+ for (int var2 = 0; var2 < this.playerEntityList.size(); ++var2) {
+ ((EntityPlayerMP) this.playerEntityList.get(var2)).playerNetServerHandler.sendPacket(par1Packet);
+ }
+ }
+
+ /**
+ * Sends a packet to all players in the specified Dimension
+ */
+ public void sendPacketToAllPlayersInDimension(Packet par1Packet, int par2) {
+ for (int var3 = 0; var3 < this.playerEntityList.size(); ++var3) {
+ EntityPlayerMP var4 = (EntityPlayerMP) this.playerEntityList.get(var3);
+
+ if (var4.dimension == par2) {
+ var4.playerNetServerHandler.sendPacket(par1Packet);
+ }
+ }
+ }
+
+ /**
+ * returns a string containing a comma-seperated list of player names
+ */
+ public String getPlayerListAsString() {
+ String var1 = "";
+
+ for (int var2 = 0; var2 < this.playerEntityList.size(); ++var2) {
+ if (var2 > 0) {
+ var1 = var1 + ", ";
+ }
+
+ var1 = var1 + ((EntityPlayerMP) this.playerEntityList.get(var2)).username;
+ }
+
+ return var1;
+ }
+
+ /**
+ * Returns an array of the usernames of all the connected players.
+ */
+ public String[] getAllUsernames() {
+ String[] var1 = new String[this.playerEntityList.size()];
+
+ for (int var2 = 0; var2 < this.playerEntityList.size(); ++var2) {
+ var1[var2] = ((EntityPlayerMP) this.playerEntityList.get(var2)).username;
+ }
+
+ return var1;
+ }
+
+ /**
+ * This adds a username to the ops list, then saves the op list
+ */
+ public void addOp(String par1Str) {
+ this.ops.add(par1Str.toLowerCase());
+ }
+
+ /**
+ * This removes a username from the ops list, then saves the op list
+ */
+ public void removeOp(String par1Str) {
+ this.ops.remove(par1Str.toLowerCase());
+ }
+
+ /**
+ * Determine if the player is allowed to connect based on current server
+ * settings.
+ */
+ public boolean isAllowedToLogin(String par1Str) {
+ par1Str = par1Str.trim().toLowerCase();
+ return !this.whiteListEnforced || this.ops.contains(par1Str) || this.whiteListedPlayers.contains(par1Str);
+ }
+
+ /**
+ * Returns true if the specific player is allowed to use commands.
+ */
+ public boolean areCommandsAllowed(String par1Str) {
+ return lanCheats || this.ops.contains(par1Str.trim().toLowerCase())
+ || this.mcServer.isSinglePlayer() && this.mcServer.worldServers[0].getWorldInfo().areCommandsAllowed()
+ && this.mcServer.getServerOwner().equalsIgnoreCase(par1Str)
+ || this.commandsAllowedForAll;
+ }
+
+ /**
+ * gets the player entity for the player with the name specified
+ */
+ public EntityPlayerMP getPlayerEntity(String par1Str) {
+ Iterator var2 = this.playerEntityList.iterator();
+ EntityPlayerMP var3;
+
+ do {
+ if (!var2.hasNext()) {
+ return null;
+ }
+
+ var3 = (EntityPlayerMP) var2.next();
+ } while (!var3.username.equalsIgnoreCase(par1Str));
+
+ return var3;
+ }
+
+ /**
+ * Find all players in a specified range and narrowing down by other parameters
+ */
+ public List findPlayers(ChunkCoordinates par1ChunkCoordinates, int par2, int par3, int par4, int par5, int par6,
+ int par7, Map par8Map, String par9Str, String par10Str) {
+ if (this.playerEntityList.isEmpty()) {
+ return null;
+ } else {
+ Object var11 = new ArrayList();
+ boolean var12 = par4 < 0;
+ int var13 = par2 * par2;
+ int var14 = par3 * par3;
+ par4 = MathHelper.abs_int(par4);
+
+ for (int var15 = 0; var15 < this.playerEntityList.size(); ++var15) {
+ EntityPlayerMP var16 = (EntityPlayerMP) this.playerEntityList.get(var15);
+ boolean var17;
+
+ if (par9Str != null) {
+ var17 = par9Str.startsWith("!");
+
+ if (var17) {
+ par9Str = par9Str.substring(1);
+ }
+
+ if (var17 == par9Str.equalsIgnoreCase(var16.getEntityName())) {
+ continue;
+ }
+ }
+
+ if (par10Str != null) {
+ var17 = par10Str.startsWith("!");
+
+ if (var17) {
+ par10Str = par10Str.substring(1);
+ }
+
+ ScorePlayerTeam var18 = var16.getTeam();
+ String var19 = var18 == null ? "" : var18.func_96661_b();
+
+ if (var17 == par10Str.equalsIgnoreCase(var19)) {
+ continue;
+ }
+ }
+
+ if (par1ChunkCoordinates != null && (par2 > 0 || par3 > 0)) {
+ float var20 = par1ChunkCoordinates
+ .getDistanceSquaredToChunkCoordinates(var16.getCommandSenderPosition());
+
+ if (par2 > 0 && var20 < (float) var13 || par3 > 0 && var20 > (float) var14) {
+ continue;
+ }
+ }
+
+ if (this.func_96457_a(var16, par8Map)
+ && (par5 == EnumGameType.NOT_SET.getID()
+ || par5 == var16.theItemInWorldManager.getGameType().getID())
+ && (par6 <= 0 || var16.experienceLevel >= par6) && var16.experienceLevel <= par7) {
+ ((List) var11).add(var16);
+ }
+ }
+
+ if (par1ChunkCoordinates != null) {
+ Collections.sort((List) var11, new PlayerPositionComparator(par1ChunkCoordinates));
+ }
+
+ if (var12) {
+ Collections.reverse((List) var11);
+ }
+
+ if (par4 > 0) {
+ var11 = ((List) var11).subList(0, Math.min(par4, ((List) var11).size()));
+ }
+
+ return (List) var11;
+ }
+ }
+
+ private boolean func_96457_a(EntityPlayer par1EntityPlayer, Map par2Map) {
+ if (par2Map != null && par2Map.size() != 0) {
+ Iterator var3 = par2Map.entrySet().iterator();
+ Entry var4;
+ boolean var6;
+ int var10;
+
+ do {
+ if (!var3.hasNext()) {
+ return true;
+ }
+
+ var4 = (Entry) var3.next();
+ String var5 = (String) var4.getKey();
+ var6 = false;
+
+ if (var5.endsWith("_min") && var5.length() > 4) {
+ var6 = true;
+ var5 = var5.substring(0, var5.length() - 4);
+ }
+
+ Scoreboard var7 = par1EntityPlayer.getWorldScoreboard();
+ ScoreObjective var8 = var7.getObjective(var5);
+
+ if (var8 == null) {
+ return false;
+ }
+
+ Score var9 = par1EntityPlayer.getWorldScoreboard().func_96529_a(par1EntityPlayer.getEntityName(), var8);
+ var10 = var9.func_96652_c();
+
+ if (var10 < ((Integer) var4.getValue()).intValue() && var6) {
+ return false;
+ }
+ } while (var10 <= ((Integer) var4.getValue()).intValue() || var6);
+
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * sends a packet to players within d3 of point (x,y,z)
+ */
+ public void sendPacketToPlayersAroundPoint(double par1, double par3, double par5, double par7, int par9,
+ Packet par10Packet) {
+ this.sendToAllNearExcept((EntityPlayer) null, par1, par3, par5, par7, par9, par10Packet);
+ }
+
+ /**
+ * params: srcPlayer,x,y,z,d,dimension. The packet is not sent to the srcPlayer,
+ * but all other players where dx*dx+dy*dy+dz*dz iceServers) {
+ lanGamemode = EnumGameType.getByID(gamemode);
+ lanCheats = cheats;
+ VoiceChatPlugin.activate(iceServers);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ServerScoreboard.java b/sp-server/src/main/java/net/minecraft/src/ServerScoreboard.java
new file mode 100644
index 0000000..3b08049
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ServerScoreboard.java
@@ -0,0 +1,215 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import net.minecraft.server.MinecraftServer;
+
+public class ServerScoreboard extends Scoreboard {
+ private final MinecraftServer field_96555_a;
+ private final Set field_96553_b = new HashSet();
+ private ScoreboardSaveData field_96554_c;
+
+ public ServerScoreboard(MinecraftServer par1MinecraftServer) {
+ this.field_96555_a = par1MinecraftServer;
+ }
+
+ public void func_96536_a(Score par1Score) {
+ super.func_96536_a(par1Score);
+
+ if (this.field_96553_b.contains(par1Score.func_96645_d())) {
+ this.field_96555_a.getConfigurationManager().sendPacketToAllPlayers(new Packet207SetScore(par1Score, 0));
+ }
+
+ this.func_96551_b();
+ }
+
+ public void func_96516_a(String par1Str) {
+ super.func_96516_a(par1Str);
+ this.field_96555_a.getConfigurationManager().sendPacketToAllPlayers(new Packet207SetScore(par1Str));
+ this.func_96551_b();
+ }
+
+ public void func_96530_a(int par1, ScoreObjective par2ScoreObjective) {
+ ScoreObjective var3 = this.func_96539_a(par1);
+ super.func_96530_a(par1, par2ScoreObjective);
+
+ if (var3 != par2ScoreObjective && var3 != null) {
+ if (this.func_96552_h(var3) > 0) {
+ this.field_96555_a.getConfigurationManager()
+ .sendPacketToAllPlayers(new Packet208SetDisplayObjective(par1, par2ScoreObjective));
+ } else {
+ this.func_96546_g(var3);
+ }
+ }
+
+ if (par2ScoreObjective != null) {
+ if (this.field_96553_b.contains(par2ScoreObjective)) {
+ this.field_96555_a.getConfigurationManager()
+ .sendPacketToAllPlayers(new Packet208SetDisplayObjective(par1, par2ScoreObjective));
+ } else {
+ this.func_96549_e(par2ScoreObjective);
+ }
+ }
+
+ this.func_96551_b();
+ }
+
+ public void func_96521_a(String par1Str, ScorePlayerTeam par2ScorePlayerTeam) {
+ super.func_96521_a(par1Str, par2ScorePlayerTeam);
+ this.field_96555_a.getConfigurationManager().sendPacketToAllPlayers(
+ new Packet209SetPlayerTeam(par2ScorePlayerTeam, Arrays.asList(new String[] { par1Str }), 3));
+ this.func_96551_b();
+ }
+
+ /**
+ * Removes the given username from the given ScorePlayerTeam. If the player is
+ * not on the team then an IllegalStateException is thrown.
+ */
+ public void removePlayerFromTeam(String par1Str, ScorePlayerTeam par2ScorePlayerTeam) {
+ super.removePlayerFromTeam(par1Str, par2ScorePlayerTeam);
+ this.field_96555_a.getConfigurationManager().sendPacketToAllPlayers(
+ new Packet209SetPlayerTeam(par2ScorePlayerTeam, Arrays.asList(new String[] { par1Str }), 4));
+ this.func_96551_b();
+ }
+
+ public void func_96522_a(ScoreObjective par1ScoreObjective) {
+ super.func_96522_a(par1ScoreObjective);
+ this.func_96551_b();
+ }
+
+ public void func_96532_b(ScoreObjective par1ScoreObjective) {
+ super.func_96532_b(par1ScoreObjective);
+
+ if (this.field_96553_b.contains(par1ScoreObjective)) {
+ this.field_96555_a.getConfigurationManager()
+ .sendPacketToAllPlayers(new Packet206SetObjective(par1ScoreObjective, 2));
+ }
+
+ this.func_96551_b();
+ }
+
+ public void func_96533_c(ScoreObjective par1ScoreObjective) {
+ super.func_96533_c(par1ScoreObjective);
+
+ if (this.field_96553_b.contains(par1ScoreObjective)) {
+ this.func_96546_g(par1ScoreObjective);
+ }
+
+ this.func_96551_b();
+ }
+
+ public void func_96523_a(ScorePlayerTeam par1ScorePlayerTeam) {
+ super.func_96523_a(par1ScorePlayerTeam);
+ this.field_96555_a.getConfigurationManager()
+ .sendPacketToAllPlayers(new Packet209SetPlayerTeam(par1ScorePlayerTeam, 0));
+ this.func_96551_b();
+ }
+
+ public void func_96538_b(ScorePlayerTeam par1ScorePlayerTeam) {
+ super.func_96538_b(par1ScorePlayerTeam);
+ this.field_96555_a.getConfigurationManager()
+ .sendPacketToAllPlayers(new Packet209SetPlayerTeam(par1ScorePlayerTeam, 2));
+ this.func_96551_b();
+ }
+
+ public void func_96513_c(ScorePlayerTeam par1ScorePlayerTeam) {
+ super.func_96513_c(par1ScorePlayerTeam);
+ this.field_96555_a.getConfigurationManager()
+ .sendPacketToAllPlayers(new Packet209SetPlayerTeam(par1ScorePlayerTeam, 1));
+ this.func_96551_b();
+ }
+
+ public void func_96547_a(ScoreboardSaveData par1ScoreboardSaveData) {
+ this.field_96554_c = par1ScoreboardSaveData;
+ }
+
+ protected void func_96551_b() {
+ if (this.field_96554_c != null) {
+ this.field_96554_c.markDirty();
+ }
+ }
+
+ public List func_96550_d(ScoreObjective par1ScoreObjective) {
+ ArrayList var2 = new ArrayList();
+ var2.add(new Packet206SetObjective(par1ScoreObjective, 0));
+
+ for (int var3 = 0; var3 < 3; ++var3) {
+ if (this.func_96539_a(var3) == par1ScoreObjective) {
+ var2.add(new Packet208SetDisplayObjective(var3, par1ScoreObjective));
+ }
+ }
+
+ Iterator var5 = this.func_96534_i(par1ScoreObjective).iterator();
+
+ while (var5.hasNext()) {
+ Score var4 = (Score) var5.next();
+ var2.add(new Packet207SetScore(var4, 0));
+ }
+
+ return var2;
+ }
+
+ public void func_96549_e(ScoreObjective par1ScoreObjective) {
+ List var2 = this.func_96550_d(par1ScoreObjective);
+ Iterator var3 = this.field_96555_a.getConfigurationManager().playerEntityList.iterator();
+
+ while (var3.hasNext()) {
+ EntityPlayerMP var4 = (EntityPlayerMP) var3.next();
+ Iterator var5 = var2.iterator();
+
+ while (var5.hasNext()) {
+ Packet var6 = (Packet) var5.next();
+ var4.playerNetServerHandler.sendPacket(var6);
+ }
+ }
+
+ this.field_96553_b.add(par1ScoreObjective);
+ }
+
+ public List func_96548_f(ScoreObjective par1ScoreObjective) {
+ ArrayList var2 = new ArrayList();
+ var2.add(new Packet206SetObjective(par1ScoreObjective, 1));
+
+ for (int var3 = 0; var3 < 3; ++var3) {
+ if (this.func_96539_a(var3) == par1ScoreObjective) {
+ var2.add(new Packet208SetDisplayObjective(var3, par1ScoreObjective));
+ }
+ }
+
+ return var2;
+ }
+
+ public void func_96546_g(ScoreObjective par1ScoreObjective) {
+ List var2 = this.func_96548_f(par1ScoreObjective);
+ Iterator var3 = this.field_96555_a.getConfigurationManager().playerEntityList.iterator();
+
+ while (var3.hasNext()) {
+ EntityPlayerMP var4 = (EntityPlayerMP) var3.next();
+ Iterator var5 = var2.iterator();
+
+ while (var5.hasNext()) {
+ Packet var6 = (Packet) var5.next();
+ var4.playerNetServerHandler.sendPacket(var6);
+ }
+ }
+
+ this.field_96553_b.remove(par1ScoreObjective);
+ }
+
+ public int func_96552_h(ScoreObjective par1ScoreObjective) {
+ int var2 = 0;
+
+ for (int var3 = 0; var3 < 3; ++var3) {
+ if (this.func_96539_a(var3) == par1ScoreObjective) {
+ ++var2;
+ }
+ }
+
+ return var2;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ShapedRecipes.java b/sp-server/src/main/java/net/minecraft/src/ShapedRecipes.java
new file mode 100644
index 0000000..a13d21a
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ShapedRecipes.java
@@ -0,0 +1,120 @@
+package net.minecraft.src;
+
+public class ShapedRecipes implements IRecipe {
+ /** How many horizontal slots this recipe is wide. */
+ private int recipeWidth;
+
+ /** How many vertical slots this recipe uses. */
+ private int recipeHeight;
+
+ /** Is a array of ItemStack that composes the recipe. */
+ private ItemStack[] recipeItems;
+
+ /** Is the ItemStack that you get when craft the recipe. */
+ private ItemStack recipeOutput;
+
+ /** Is the itemID of the output item that you get when craft the recipe. */
+ public final int recipeOutputItemID;
+ private boolean field_92101_f = false;
+
+ public ShapedRecipes(int par1, int par2, ItemStack[] par3ArrayOfItemStack, ItemStack par4ItemStack) {
+ this.recipeOutputItemID = par4ItemStack.itemID;
+ this.recipeWidth = par1;
+ this.recipeHeight = par2;
+ this.recipeItems = par3ArrayOfItemStack;
+ this.recipeOutput = par4ItemStack;
+ }
+
+ public ItemStack getRecipeOutput() {
+ return this.recipeOutput;
+ }
+
+ /**
+ * Used to check if a recipe matches current crafting inventory
+ */
+ public boolean matches(InventoryCrafting par1InventoryCrafting, World par2World) {
+ for (int var3 = 0; var3 <= 3 - this.recipeWidth; ++var3) {
+ for (int var4 = 0; var4 <= 3 - this.recipeHeight; ++var4) {
+ if (this.checkMatch(par1InventoryCrafting, var3, var4, true)) {
+ return true;
+ }
+
+ if (this.checkMatch(par1InventoryCrafting, var3, var4, false)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Checks if the region of a crafting inventory is match for the recipe.
+ */
+ private boolean checkMatch(InventoryCrafting par1InventoryCrafting, int par2, int par3, boolean par4) {
+ for (int var5 = 0; var5 < 3; ++var5) {
+ for (int var6 = 0; var6 < 3; ++var6) {
+ int var7 = var5 - par2;
+ int var8 = var6 - par3;
+ ItemStack var9 = null;
+
+ if (var7 >= 0 && var8 >= 0 && var7 < this.recipeWidth && var8 < this.recipeHeight) {
+ if (par4) {
+ var9 = this.recipeItems[this.recipeWidth - var7 - 1 + var8 * this.recipeWidth];
+ } else {
+ var9 = this.recipeItems[var7 + var8 * this.recipeWidth];
+ }
+ }
+
+ ItemStack var10 = par1InventoryCrafting.getStackInRowAndColumn(var5, var6);
+
+ if (var10 != null || var9 != null) {
+ if (var10 == null && var9 != null || var10 != null && var9 == null) {
+ return false;
+ }
+
+ if (var9.itemID != var10.itemID) {
+ return false;
+ }
+
+ if (var9.getItemDamage() != 32767 && var9.getItemDamage() != var10.getItemDamage()) {
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns an Item that is the result of this recipe
+ */
+ public ItemStack getCraftingResult(InventoryCrafting par1InventoryCrafting) {
+ ItemStack var2 = this.getRecipeOutput().copy();
+
+ if (this.field_92101_f) {
+ for (int var3 = 0; var3 < par1InventoryCrafting.getSizeInventory(); ++var3) {
+ ItemStack var4 = par1InventoryCrafting.getStackInSlot(var3);
+
+ if (var4 != null && var4.hasTagCompound()) {
+ var2.setTagCompound((NBTTagCompound) var4.stackTagCompound.copy());
+ }
+ }
+ }
+
+ return var2;
+ }
+
+ /**
+ * Returns the size of the recipe area
+ */
+ public int getRecipeSize() {
+ return this.recipeWidth * this.recipeHeight;
+ }
+
+ public ShapedRecipes func_92100_c() {
+ this.field_92101_f = true;
+ return this;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/ShapelessRecipes.java b/sp-server/src/main/java/net/minecraft/src/ShapelessRecipes.java
new file mode 100644
index 0000000..1017f2b
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/ShapelessRecipes.java
@@ -0,0 +1,71 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+public class ShapelessRecipes implements IRecipe {
+ /** Is the ItemStack that you get when craft the recipe. */
+ private final ItemStack recipeOutput;
+
+ /** Is a List of ItemStack that composes the recipe. */
+ private final List recipeItems;
+
+ public ShapelessRecipes(ItemStack par1ItemStack, List par2List) {
+ this.recipeOutput = par1ItemStack;
+ this.recipeItems = par2List;
+ }
+
+ public ItemStack getRecipeOutput() {
+ return this.recipeOutput;
+ }
+
+ /**
+ * Used to check if a recipe matches current crafting inventory
+ */
+ public boolean matches(InventoryCrafting par1InventoryCrafting, World par2World) {
+ ArrayList var3 = new ArrayList(this.recipeItems);
+
+ for (int var4 = 0; var4 < 3; ++var4) {
+ for (int var5 = 0; var5 < 3; ++var5) {
+ ItemStack var6 = par1InventoryCrafting.getStackInRowAndColumn(var5, var4);
+
+ if (var6 != null) {
+ boolean var7 = false;
+ Iterator var8 = var3.iterator();
+
+ while (var8.hasNext()) {
+ ItemStack var9 = (ItemStack) var8.next();
+
+ if (var6.itemID == var9.itemID
+ && (var9.getItemDamage() == 32767 || var6.getItemDamage() == var9.getItemDamage())) {
+ var7 = true;
+ var3.remove(var9);
+ break;
+ }
+ }
+
+ if (!var7) {
+ return false;
+ }
+ }
+ }
+ }
+
+ return var3.isEmpty();
+ }
+
+ /**
+ * Returns an Item that is the result of this recipe
+ */
+ public ItemStack getCraftingResult(InventoryCrafting par1InventoryCrafting) {
+ return this.recipeOutput.copy();
+ }
+
+ /**
+ * Returns the size of the recipe area
+ */
+ public int getRecipeSize() {
+ return this.recipeItems.size();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Slot.java b/sp-server/src/main/java/net/minecraft/src/Slot.java
new file mode 100644
index 0000000..fde55ca
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Slot.java
@@ -0,0 +1,126 @@
+package net.minecraft.src;
+
+public class Slot {
+ /** The index of the slot in the inventory. */
+ private final int slotIndex;
+
+ /** The inventory we want to extract a slot from. */
+ public final IInventory inventory;
+
+ /** the id of the slot(also the index in the inventory arraylist) */
+ public int slotNumber;
+
+ /** display position of the inventory slot on the screen x axis */
+ public int xDisplayPosition;
+
+ /** display position of the inventory slot on the screen y axis */
+ public int yDisplayPosition;
+
+ public Slot(IInventory par1IInventory, int par2, int par3, int par4) {
+ this.inventory = par1IInventory;
+ this.slotIndex = par2;
+ this.xDisplayPosition = par3;
+ this.yDisplayPosition = par4;
+ }
+
+ /**
+ * if par2 has more items than par1, onCrafting(item,countIncrease) is called
+ */
+ public void onSlotChange(ItemStack par1ItemStack, ItemStack par2ItemStack) {
+ if (par1ItemStack != null && par2ItemStack != null) {
+ if (par1ItemStack.itemID == par2ItemStack.itemID) {
+ int var3 = par2ItemStack.stackSize - par1ItemStack.stackSize;
+
+ if (var3 > 0) {
+ this.onCrafting(par1ItemStack, var3);
+ }
+ }
+ }
+ }
+
+ /**
+ * the itemStack passed in is the output - ie, iron ingots, and pickaxes, not
+ * ore and wood. Typically increases an internal count then calls
+ * onCrafting(item).
+ */
+ protected void onCrafting(ItemStack par1ItemStack, int par2) {
+ }
+
+ /**
+ * the itemStack passed in is the output - ie, iron ingots, and pickaxes, not
+ * ore and wood.
+ */
+ protected void onCrafting(ItemStack par1ItemStack) {
+ }
+
+ public void onPickupFromSlot(EntityPlayer par1EntityPlayer, ItemStack par2ItemStack) {
+ this.onSlotChanged();
+ }
+
+ /**
+ * Check if the stack is a valid item for this slot. Always true beside for the
+ * armor slots.
+ */
+ public boolean isItemValid(ItemStack par1ItemStack) {
+ return true;
+ }
+
+ /**
+ * Helper fnct to get the stack in the slot.
+ */
+ public ItemStack getStack() {
+ return this.inventory.getStackInSlot(this.slotIndex);
+ }
+
+ /**
+ * Returns if this slot contains a stack.
+ */
+ public boolean getHasStack() {
+ return this.getStack() != null;
+ }
+
+ /**
+ * Helper method to put a stack in the slot.
+ */
+ public void putStack(ItemStack par1ItemStack) {
+ this.inventory.setInventorySlotContents(this.slotIndex, par1ItemStack);
+ this.onSlotChanged();
+ }
+
+ /**
+ * Called when the stack in a Slot changes
+ */
+ public void onSlotChanged() {
+ this.inventory.onInventoryChanged();
+ }
+
+ /**
+ * Returns the maximum stack size for a given slot (usually the same as
+ * getInventoryStackLimit(), but 1 in the case of armor slots)
+ */
+ public int getSlotStackLimit() {
+ return this.inventory.getInventoryStackLimit();
+ }
+
+ /**
+ * Decrease the size of the stack in slot (first int arg) by the amount of the
+ * second int arg. Returns the new stack.
+ */
+ public ItemStack decrStackSize(int par1) {
+ return this.inventory.decrStackSize(this.slotIndex, par1);
+ }
+
+ /**
+ * returns true if the slot exists in the given inventory and location
+ */
+ public boolean isHere(IInventory par1IInventory, int par2) {
+ return par1IInventory == this.inventory && par2 == this.slotIndex;
+ }
+
+ /**
+ * Return whether this slot's stack can be taken from this slot.
+ */
+ public boolean canTakeStack(EntityPlayer par1EntityPlayer) {
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/SlotArmor.java b/sp-server/src/main/java/net/minecraft/src/SlotArmor.java
new file mode 100644
index 0000000..faf6b43
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/SlotArmor.java
@@ -0,0 +1,43 @@
+package net.minecraft.src;
+
+class SlotArmor extends Slot {
+ /**
+ * The armor type that can be placed on that slot, it uses the same values of
+ * armorType field on ItemArmor.
+ */
+ final int armorType;
+
+ /**
+ * The parent class of this clot, ContainerPlayer, SlotArmor is a Anon inner
+ * class.
+ */
+ final ContainerPlayer parent;
+
+ SlotArmor(ContainerPlayer par1ContainerPlayer, IInventory par2IInventory, int par3, int par4, int par5, int par6) {
+ super(par2IInventory, par3, par4, par5);
+ this.parent = par1ContainerPlayer;
+ this.armorType = par6;
+ }
+
+ /**
+ * Returns the maximum stack size for a given slot (usually the same as
+ * getInventoryStackLimit(), but 1 in the case of armor slots)
+ */
+ public int getSlotStackLimit() {
+ return 1;
+ }
+
+ /**
+ * Check if the stack is a valid item for this slot. Always true beside for the
+ * armor slots.
+ */
+ public boolean isItemValid(ItemStack par1ItemStack) {
+ return par1ItemStack == null ? false
+ : (par1ItemStack
+ .getItem() instanceof ItemArmor
+ ? ((ItemArmor) par1ItemStack.getItem()).armorType == this.armorType
+ : (par1ItemStack.getItem().itemID != Block.pumpkin.blockID
+ && par1ItemStack.getItem().itemID != Item.skull.itemID ? false
+ : this.armorType == 0));
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/SlotBeacon.java b/sp-server/src/main/java/net/minecraft/src/SlotBeacon.java
new file mode 100644
index 0000000..96c2ff2
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/SlotBeacon.java
@@ -0,0 +1,30 @@
+package net.minecraft.src;
+
+class SlotBeacon extends Slot {
+ /** The beacon this slot belongs to. */
+ final ContainerBeacon beacon;
+
+ public SlotBeacon(ContainerBeacon par1ContainerBeacon, IInventory par2IInventory, int par3, int par4, int par5) {
+ super(par2IInventory, par3, par4, par5);
+ this.beacon = par1ContainerBeacon;
+ }
+
+ /**
+ * Check if the stack is a valid item for this slot. Always true beside for the
+ * armor slots.
+ */
+ public boolean isItemValid(ItemStack par1ItemStack) {
+ return par1ItemStack == null ? false
+ : par1ItemStack.itemID == Item.emerald.itemID || par1ItemStack.itemID == Item.diamond.itemID
+ || par1ItemStack.itemID == Item.ingotGold.itemID
+ || par1ItemStack.itemID == Item.ingotIron.itemID;
+ }
+
+ /**
+ * Returns the maximum stack size for a given slot (usually the same as
+ * getInventoryStackLimit(), but 1 in the case of armor slots)
+ */
+ public int getSlotStackLimit() {
+ return 1;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/SlotBrewingStandIngredient.java b/sp-server/src/main/java/net/minecraft/src/SlotBrewingStandIngredient.java
new file mode 100644
index 0000000..9912352
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/SlotBrewingStandIngredient.java
@@ -0,0 +1,28 @@
+package net.minecraft.src;
+
+class SlotBrewingStandIngredient extends Slot {
+ /** The brewing stand this slot belongs to. */
+ final ContainerBrewingStand brewingStand;
+
+ public SlotBrewingStandIngredient(ContainerBrewingStand par1ContainerBrewingStand, IInventory par2IInventory,
+ int par3, int par4, int par5) {
+ super(par2IInventory, par3, par4, par5);
+ this.brewingStand = par1ContainerBrewingStand;
+ }
+
+ /**
+ * Check if the stack is a valid item for this slot. Always true beside for the
+ * armor slots.
+ */
+ public boolean isItemValid(ItemStack par1ItemStack) {
+ return par1ItemStack != null ? Item.itemsList[par1ItemStack.itemID].isPotionIngredient() : false;
+ }
+
+ /**
+ * Returns the maximum stack size for a given slot (usually the same as
+ * getInventoryStackLimit(), but 1 in the case of armor slots)
+ */
+ public int getSlotStackLimit() {
+ return 64;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/SlotBrewingStandPotion.java b/sp-server/src/main/java/net/minecraft/src/SlotBrewingStandPotion.java
new file mode 100644
index 0000000..4482f25
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/SlotBrewingStandPotion.java
@@ -0,0 +1,44 @@
+package net.minecraft.src;
+
+class SlotBrewingStandPotion extends Slot {
+ /** The player that has this container open. */
+ private EntityPlayer player;
+
+ public SlotBrewingStandPotion(EntityPlayer par1EntityPlayer, IInventory par2IInventory, int par3, int par4,
+ int par5) {
+ super(par2IInventory, par3, par4, par5);
+ this.player = par1EntityPlayer;
+ }
+
+ /**
+ * Check if the stack is a valid item for this slot. Always true beside for the
+ * armor slots.
+ */
+ public boolean isItemValid(ItemStack par1ItemStack) {
+ return canHoldPotion(par1ItemStack);
+ }
+
+ /**
+ * Returns the maximum stack size for a given slot (usually the same as
+ * getInventoryStackLimit(), but 1 in the case of armor slots)
+ */
+ public int getSlotStackLimit() {
+ return 1;
+ }
+
+ public void onPickupFromSlot(EntityPlayer par1EntityPlayer, ItemStack par2ItemStack) {
+ if (par2ItemStack.itemID == Item.potion.itemID && par2ItemStack.getItemDamage() > 0) {
+ this.player.addStat(AchievementList.potion, 1);
+ }
+
+ super.onPickupFromSlot(par1EntityPlayer, par2ItemStack);
+ }
+
+ /**
+ * Returns true if this itemstack can be filled with a potion
+ */
+ public static boolean canHoldPotion(ItemStack par0ItemStack) {
+ return par0ItemStack != null
+ && (par0ItemStack.itemID == Item.potion.itemID || par0ItemStack.itemID == Item.glassBottle.itemID);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/SlotCrafting.java b/sp-server/src/main/java/net/minecraft/src/SlotCrafting.java
new file mode 100644
index 0000000..3ec544a
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/SlotCrafting.java
@@ -0,0 +1,108 @@
+package net.minecraft.src;
+
+public class SlotCrafting extends Slot {
+ /** The craft matrix inventory linked to this result slot. */
+ private final IInventory craftMatrix;
+
+ /** The player that is using the GUI where this slot resides. */
+ private EntityPlayer thePlayer;
+
+ /**
+ * The number of items that have been crafted so far. Gets passed to
+ * ItemStack.onCrafting before being reset.
+ */
+ private int amountCrafted;
+
+ public SlotCrafting(EntityPlayer par1EntityPlayer, IInventory par2IInventory, IInventory par3IInventory, int par4,
+ int par5, int par6) {
+ super(par3IInventory, par4, par5, par6);
+ this.thePlayer = par1EntityPlayer;
+ this.craftMatrix = par2IInventory;
+ }
+
+ /**
+ * Check if the stack is a valid item for this slot. Always true beside for the
+ * armor slots.
+ */
+ public boolean isItemValid(ItemStack par1ItemStack) {
+ return false;
+ }
+
+ /**
+ * Decrease the size of the stack in slot (first int arg) by the amount of the
+ * second int arg. Returns the new stack.
+ */
+ public ItemStack decrStackSize(int par1) {
+ if (this.getHasStack()) {
+ this.amountCrafted += Math.min(par1, this.getStack().stackSize);
+ }
+
+ return super.decrStackSize(par1);
+ }
+
+ /**
+ * the itemStack passed in is the output - ie, iron ingots, and pickaxes, not
+ * ore and wood. Typically increases an internal count then calls
+ * onCrafting(item).
+ */
+ protected void onCrafting(ItemStack par1ItemStack, int par2) {
+ this.amountCrafted += par2;
+ this.onCrafting(par1ItemStack);
+ }
+
+ /**
+ * the itemStack passed in is the output - ie, iron ingots, and pickaxes, not
+ * ore and wood.
+ */
+ protected void onCrafting(ItemStack par1ItemStack) {
+ par1ItemStack.onCrafting(this.thePlayer.worldObj, this.thePlayer, this.amountCrafted);
+ this.amountCrafted = 0;
+
+ if (par1ItemStack.itemID == Block.workbench.blockID) {
+ this.thePlayer.addStat(AchievementList.buildWorkBench, 1);
+ } else if (par1ItemStack.itemID == Item.pickaxeWood.itemID) {
+ this.thePlayer.addStat(AchievementList.buildPickaxe, 1);
+ } else if (par1ItemStack.itemID == Block.furnaceIdle.blockID) {
+ this.thePlayer.addStat(AchievementList.buildFurnace, 1);
+ } else if (par1ItemStack.itemID == Item.hoeWood.itemID) {
+ this.thePlayer.addStat(AchievementList.buildHoe, 1);
+ } else if (par1ItemStack.itemID == Item.bread.itemID) {
+ this.thePlayer.addStat(AchievementList.makeBread, 1);
+ } else if (par1ItemStack.itemID == Item.cake.itemID) {
+ this.thePlayer.addStat(AchievementList.bakeCake, 1);
+ } else if (par1ItemStack.itemID == Item.pickaxeStone.itemID) {
+ this.thePlayer.addStat(AchievementList.buildBetterPickaxe, 1);
+ } else if (par1ItemStack.itemID == Item.swordWood.itemID) {
+ this.thePlayer.addStat(AchievementList.buildSword, 1);
+ } else if (par1ItemStack.itemID == Block.enchantmentTable.blockID) {
+ this.thePlayer.addStat(AchievementList.enchantments, 1);
+ } else if (par1ItemStack.itemID == Block.bookShelf.blockID) {
+ this.thePlayer.addStat(AchievementList.bookcase, 1);
+ }
+ }
+
+ public void onPickupFromSlot(EntityPlayer par1EntityPlayer, ItemStack par2ItemStack) {
+ this.onCrafting(par2ItemStack);
+
+ for (int var3 = 0; var3 < this.craftMatrix.getSizeInventory(); ++var3) {
+ ItemStack var4 = this.craftMatrix.getStackInSlot(var3);
+
+ if (var4 != null) {
+ this.craftMatrix.decrStackSize(var3, 1);
+
+ if (var4.getItem().hasContainerItem()) {
+ ItemStack var5 = new ItemStack(var4.getItem().getContainerItem());
+
+ if (!var4.getItem().doesContainerItemLeaveCraftingGrid(var4)
+ || !this.thePlayer.inventory.addItemStackToInventory(var5)) {
+ if (this.craftMatrix.getStackInSlot(var3) == null) {
+ this.craftMatrix.setInventorySlotContents(var3, var5);
+ } else {
+ this.thePlayer.dropPlayerItem(var5);
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/SlotEnchantment.java b/sp-server/src/main/java/net/minecraft/src/SlotEnchantment.java
new file mode 100644
index 0000000..9433b46
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/SlotEnchantment.java
@@ -0,0 +1,20 @@
+package net.minecraft.src;
+
+class SlotEnchantment extends Slot {
+ /** The brewing stand this slot belongs to. */
+ final ContainerEnchantment container;
+
+ SlotEnchantment(ContainerEnchantment par1ContainerEnchantment, IInventory par2IInventory, int par3, int par4,
+ int par5) {
+ super(par2IInventory, par3, par4, par5);
+ this.container = par1ContainerEnchantment;
+ }
+
+ /**
+ * Check if the stack is a valid item for this slot. Always true beside for the
+ * armor slots.
+ */
+ public boolean isItemValid(ItemStack par1ItemStack) {
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/SlotEnchantmentTable.java b/sp-server/src/main/java/net/minecraft/src/SlotEnchantmentTable.java
new file mode 100644
index 0000000..fa40751
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/SlotEnchantmentTable.java
@@ -0,0 +1,35 @@
+package net.minecraft.src;
+
+class SlotEnchantmentTable extends InventoryBasic {
+ /** The brewing stand this slot belongs to. */
+ final ContainerEnchantment container;
+
+ SlotEnchantmentTable(ContainerEnchantment par1ContainerEnchantment, String par2Str, boolean par3, int par4) {
+ super(par2Str, par3, par4);
+ this.container = par1ContainerEnchantment;
+ }
+
+ /**
+ * Returns the maximum stack size for a inventory slot. Seems to always be 64,
+ * possibly will be extended. *Isn't this more of a set than a get?*
+ */
+ public int getInventoryStackLimit() {
+ return 1;
+ }
+
+ /**
+ * Called when an the contents of an Inventory change, usually
+ */
+ public void onInventoryChanged() {
+ super.onInventoryChanged();
+ this.container.onCraftMatrixChanged(this);
+ }
+
+ /**
+ * Returns true if automation is allowed to insert the given stack (ignoring
+ * stack size) into the given slot.
+ */
+ public boolean isStackValidForSlot(int par1, ItemStack par2ItemStack) {
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/SlotFurnace.java b/sp-server/src/main/java/net/minecraft/src/SlotFurnace.java
new file mode 100644
index 0000000..1d6a184
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/SlotFurnace.java
@@ -0,0 +1,91 @@
+package net.minecraft.src;
+
+public class SlotFurnace extends Slot {
+ /** The player that is using the GUI where this slot resides. */
+ private EntityPlayer thePlayer;
+ private int field_75228_b;
+
+ public SlotFurnace(EntityPlayer par1EntityPlayer, IInventory par2IInventory, int par3, int par4, int par5) {
+ super(par2IInventory, par3, par4, par5);
+ this.thePlayer = par1EntityPlayer;
+ }
+
+ /**
+ * Check if the stack is a valid item for this slot. Always true beside for the
+ * armor slots.
+ */
+ public boolean isItemValid(ItemStack par1ItemStack) {
+ return false;
+ }
+
+ /**
+ * Decrease the size of the stack in slot (first int arg) by the amount of the
+ * second int arg. Returns the new stack.
+ */
+ public ItemStack decrStackSize(int par1) {
+ if (this.getHasStack()) {
+ this.field_75228_b += Math.min(par1, this.getStack().stackSize);
+ }
+
+ return super.decrStackSize(par1);
+ }
+
+ public void onPickupFromSlot(EntityPlayer par1EntityPlayer, ItemStack par2ItemStack) {
+ this.onCrafting(par2ItemStack);
+ super.onPickupFromSlot(par1EntityPlayer, par2ItemStack);
+ }
+
+ /**
+ * the itemStack passed in is the output - ie, iron ingots, and pickaxes, not
+ * ore and wood. Typically increases an internal count then calls
+ * onCrafting(item).
+ */
+ protected void onCrafting(ItemStack par1ItemStack, int par2) {
+ this.field_75228_b += par2;
+ this.onCrafting(par1ItemStack);
+ }
+
+ /**
+ * the itemStack passed in is the output - ie, iron ingots, and pickaxes, not
+ * ore and wood.
+ */
+ protected void onCrafting(ItemStack par1ItemStack) {
+ par1ItemStack.onCrafting(this.thePlayer.worldObj, this.thePlayer, this.field_75228_b);
+
+ if (!this.thePlayer.worldObj.isRemote) {
+ int var2 = this.field_75228_b;
+ float var3 = FurnaceRecipes.smelting().getExperience(par1ItemStack.itemID);
+ int var4;
+
+ if (var3 == 0.0F) {
+ var2 = 0;
+ } else if (var3 < 1.0F) {
+ var4 = MathHelper.floor_float((float) var2 * var3);
+
+ if (var4 < MathHelper.ceiling_float_int((float) var2 * var3)
+ && (float) Math.random() < (float) var2 * var3 - (float) var4) {
+ ++var4;
+ }
+
+ var2 = var4;
+ }
+
+ while (var2 > 0) {
+ var4 = EntityXPOrb.getXPSplit(var2);
+ var2 -= var4;
+ this.thePlayer.worldObj.spawnEntityInWorld(new EntityXPOrb(this.thePlayer.worldObj, this.thePlayer.posX,
+ this.thePlayer.posY + 0.5D, this.thePlayer.posZ + 0.5D, var4));
+ }
+ }
+
+ this.field_75228_b = 0;
+
+ if (par1ItemStack.itemID == Item.ingotIron.itemID) {
+ this.thePlayer.addStat(AchievementList.acquireIron, 1);
+ }
+
+ if (par1ItemStack.itemID == Item.fishCooked.itemID) {
+ this.thePlayer.addStat(AchievementList.cookFish, 1);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/SlotMerchantResult.java b/sp-server/src/main/java/net/minecraft/src/SlotMerchantResult.java
new file mode 100644
index 0000000..99d2543
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/SlotMerchantResult.java
@@ -0,0 +1,104 @@
+package net.minecraft.src;
+
+public class SlotMerchantResult extends Slot {
+ /** Merchant's inventory. */
+ private final InventoryMerchant theMerchantInventory;
+
+ /** The Player whos trying to buy/sell stuff. */
+ private EntityPlayer thePlayer;
+ private int field_75231_g;
+
+ /** "Instance" of the Merchant. */
+ private final IMerchant theMerchant;
+
+ public SlotMerchantResult(EntityPlayer par1EntityPlayer, IMerchant par2IMerchant,
+ InventoryMerchant par3InventoryMerchant, int par4, int par5, int par6) {
+ super(par3InventoryMerchant, par4, par5, par6);
+ this.thePlayer = par1EntityPlayer;
+ this.theMerchant = par2IMerchant;
+ this.theMerchantInventory = par3InventoryMerchant;
+ }
+
+ /**
+ * Check if the stack is a valid item for this slot. Always true beside for the
+ * armor slots.
+ */
+ public boolean isItemValid(ItemStack par1ItemStack) {
+ return false;
+ }
+
+ /**
+ * Decrease the size of the stack in slot (first int arg) by the amount of the
+ * second int arg. Returns the new stack.
+ */
+ public ItemStack decrStackSize(int par1) {
+ if (this.getHasStack()) {
+ this.field_75231_g += Math.min(par1, this.getStack().stackSize);
+ }
+
+ return super.decrStackSize(par1);
+ }
+
+ /**
+ * the itemStack passed in is the output - ie, iron ingots, and pickaxes, not
+ * ore and wood. Typically increases an internal count then calls
+ * onCrafting(item).
+ */
+ protected void onCrafting(ItemStack par1ItemStack, int par2) {
+ this.field_75231_g += par2;
+ this.onCrafting(par1ItemStack);
+ }
+
+ /**
+ * the itemStack passed in is the output - ie, iron ingots, and pickaxes, not
+ * ore and wood.
+ */
+ protected void onCrafting(ItemStack par1ItemStack) {
+ par1ItemStack.onCrafting(this.thePlayer.worldObj, this.thePlayer, this.field_75231_g);
+ this.field_75231_g = 0;
+ }
+
+ public void onPickupFromSlot(EntityPlayer par1EntityPlayer, ItemStack par2ItemStack) {
+ this.onCrafting(par2ItemStack);
+ MerchantRecipe var3 = this.theMerchantInventory.getCurrentRecipe();
+
+ if (var3 != null) {
+ ItemStack var4 = this.theMerchantInventory.getStackInSlot(0);
+ ItemStack var5 = this.theMerchantInventory.getStackInSlot(1);
+
+ if (this.func_75230_a(var3, var4, var5) || this.func_75230_a(var3, var5, var4)) {
+ if (var4 != null && var4.stackSize <= 0) {
+ var4 = null;
+ }
+
+ if (var5 != null && var5.stackSize <= 0) {
+ var5 = null;
+ }
+
+ this.theMerchantInventory.setInventorySlotContents(0, var4);
+ this.theMerchantInventory.setInventorySlotContents(1, var5);
+ this.theMerchant.useRecipe(var3);
+ }
+ }
+ }
+
+ private boolean func_75230_a(MerchantRecipe par1MerchantRecipe, ItemStack par2ItemStack, ItemStack par3ItemStack) {
+ ItemStack var4 = par1MerchantRecipe.getItemToBuy();
+ ItemStack var5 = par1MerchantRecipe.getSecondItemToBuy();
+
+ if (par2ItemStack != null && par2ItemStack.itemID == var4.itemID) {
+ if (var5 != null && par3ItemStack != null && var5.itemID == par3ItemStack.itemID) {
+ par2ItemStack.stackSize -= var4.stackSize;
+ par3ItemStack.stackSize -= var5.stackSize;
+ return true;
+ }
+
+ if (var5 == null && par3ItemStack == null) {
+ par2ItemStack.stackSize -= var4.stackSize;
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/SlotRepair.java b/sp-server/src/main/java/net/minecraft/src/SlotRepair.java
new file mode 100644
index 0000000..49c5669
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/SlotRepair.java
@@ -0,0 +1,83 @@
+package net.minecraft.src;
+
+class SlotRepair extends Slot {
+ final World theWorld;
+
+ final int blockPosX;
+
+ final int blockPosY;
+
+ final int blockPosZ;
+
+ /** The anvil this slot belongs to. */
+ final ContainerRepair anvil;
+
+ SlotRepair(ContainerRepair par1ContainerRepair, IInventory par2IInventory, int par3, int par4, int par5,
+ World par6World, int par7, int par8, int par9) {
+ super(par2IInventory, par3, par4, par5);
+ this.anvil = par1ContainerRepair;
+ this.theWorld = par6World;
+ this.blockPosX = par7;
+ this.blockPosY = par8;
+ this.blockPosZ = par9;
+ }
+
+ /**
+ * Check if the stack is a valid item for this slot. Always true beside for the
+ * armor slots.
+ */
+ public boolean isItemValid(ItemStack par1ItemStack) {
+ return false;
+ }
+
+ /**
+ * Return whether this slot's stack can be taken from this slot.
+ */
+ public boolean canTakeStack(EntityPlayer par1EntityPlayer) {
+ return (par1EntityPlayer.capabilities.isCreativeMode
+ || par1EntityPlayer.experienceLevel >= this.anvil.maximumCost) && this.anvil.maximumCost > 0
+ && this.getHasStack();
+ }
+
+ public void onPickupFromSlot(EntityPlayer par1EntityPlayer, ItemStack par2ItemStack) {
+ if (!par1EntityPlayer.capabilities.isCreativeMode) {
+ par1EntityPlayer.addExperienceLevel(-this.anvil.maximumCost);
+ }
+
+ ContainerRepair.getRepairInputInventory(this.anvil).setInventorySlotContents(0, (ItemStack) null);
+
+ if (ContainerRepair.getStackSizeUsedInRepair(this.anvil) > 0) {
+ ItemStack var3 = ContainerRepair.getRepairInputInventory(this.anvil).getStackInSlot(1);
+
+ if (var3 != null && var3.stackSize > ContainerRepair.getStackSizeUsedInRepair(this.anvil)) {
+ var3.stackSize -= ContainerRepair.getStackSizeUsedInRepair(this.anvil);
+ ContainerRepair.getRepairInputInventory(this.anvil).setInventorySlotContents(1, var3);
+ } else {
+ ContainerRepair.getRepairInputInventory(this.anvil).setInventorySlotContents(1, (ItemStack) null);
+ }
+ } else {
+ ContainerRepair.getRepairInputInventory(this.anvil).setInventorySlotContents(1, (ItemStack) null);
+ }
+
+ this.anvil.maximumCost = 0;
+
+ if (!par1EntityPlayer.capabilities.isCreativeMode && !this.theWorld.isRemote
+ && this.theWorld.getBlockId(this.blockPosX, this.blockPosY, this.blockPosZ) == Block.anvil.blockID
+ && par1EntityPlayer.getRNG().nextFloat() < 0.12F) {
+ int var6 = this.theWorld.getBlockMetadata(this.blockPosX, this.blockPosY, this.blockPosZ);
+ int var4 = var6 & 3;
+ int var5 = var6 >> 2;
+ ++var5;
+
+ if (var5 > 2) {
+ this.theWorld.setBlockToAir(this.blockPosX, this.blockPosY, this.blockPosZ);
+ this.theWorld.playAuxSFX(1020, this.blockPosX, this.blockPosY, this.blockPosZ, 0);
+ } else {
+ this.theWorld.setBlockMetadata(this.blockPosX, this.blockPosY, this.blockPosZ, var4 | var5 << 2, 2);
+ this.theWorld.playAuxSFX(1021, this.blockPosX, this.blockPosY, this.blockPosZ, 0);
+ }
+ } else if (!this.theWorld.isRemote) {
+ this.theWorld.playAuxSFX(1021, this.blockPosX, this.blockPosY, this.blockPosZ, 0);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/SpawnListEntry.java b/sp-server/src/main/java/net/minecraft/src/SpawnListEntry.java
new file mode 100644
index 0000000..dd8c96f
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/SpawnListEntry.java
@@ -0,0 +1,17 @@
+package net.minecraft.src;
+
+import java.util.function.Function;
+
+public class SpawnListEntry extends WeightedRandomItem {
+ /** Holds the class of the entity to be spawned. */
+ public Function entityConstructor;
+ public int minGroupCount;
+ public int maxGroupCount;
+
+ public SpawnListEntry(Function par1Class, int par2, int par3, int par4) {
+ super(par2);
+ this.entityConstructor = par1Class;
+ this.minGroupCount = par3;
+ this.maxGroupCount = par4;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/SpawnerAnimals.java b/sp-server/src/main/java/net/minecraft/src/SpawnerAnimals.java
new file mode 100644
index 0000000..c8aec03
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/SpawnerAnimals.java
@@ -0,0 +1,272 @@
+package net.minecraft.src;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public final class SpawnerAnimals {
+ /** The 17x17 area around the player where mobs can spawn */
+ private static HashMap eligibleChunksForSpawning = new HashMap();
+
+ /** An array of entity classes that spawn at night. */
+ protected static final Class[] nightSpawnEntities = new Class[] { EntitySpider.class, EntityZombie.class,
+ EntitySkeleton.class };
+
+ /**
+ * Given a chunk, find a random position in it.
+ */
+ protected static ChunkPosition getRandomSpawningPointInChunk(World par0World, int par1, int par2) {
+ Chunk var3 = par0World.getChunkFromChunkCoords(par1, par2);
+ int var4 = par1 * 16 + par0World.rand.nextInt(16);
+ int var5 = par2 * 16 + par0World.rand.nextInt(16);
+ int var6 = par0World.rand
+ .nextInt(var3 == null ? par0World.getActualHeight() : var3.getTopFilledSegment() + 16 - 1);
+ return new ChunkPosition(var4, var6, var5);
+ }
+
+ /**
+ * adds all chunks within the spawn radius of the players to
+ * eligibleChunksForSpawning. pars: the world, hostileCreatures,
+ * passiveCreatures. returns number of eligible chunks.
+ */
+ public static final int findChunksForSpawning(WorldServer par0WorldServer, boolean par1, boolean par2,
+ boolean par3) {
+ if (!par1 && !par2) {
+ return 0;
+ } else {
+ eligibleChunksForSpawning.clear();
+ int var4;
+ int var7;
+
+ for (var4 = 0; var4 < par0WorldServer.playerEntities.size(); ++var4) {
+ EntityPlayerMP var5 = (EntityPlayerMP) par0WorldServer.playerEntities.get(var4);
+ int var6 = MathHelper.floor_double(var5.posX / 16.0D);
+ var7 = MathHelper.floor_double(var5.posZ / 16.0D);
+ int var8 = 8;
+
+ if(var5.renderDistance < var8) {
+ var8 = var5.renderDistance;
+ if(var8 < 4) {
+ var8 = 4;
+ } // TODO
+ }
+
+ for (int var9 = -var8; var9 <= var8; ++var9) {
+ for (int var10 = -var8; var10 <= var8; ++var10) {
+ boolean var11 = var8 >= 8 && (var9 == -var8 || var9 == var8 || var10 == -var8 || var10 == var8);
+ ChunkCoordIntPair var12 = new ChunkCoordIntPair(var9 + var6, var10 + var7);
+
+ if (!var11) {
+ eligibleChunksForSpawning.put(var12, Boolean.valueOf(false));
+ } else if (!eligibleChunksForSpawning.containsKey(var12)) {
+ eligibleChunksForSpawning.put(var12, Boolean.valueOf(true));
+ }
+ }
+ }
+ }
+
+ var4 = 0;
+ ChunkCoordinates var32 = par0WorldServer.getSpawnPoint();
+ EnumCreatureType[] var33 = EnumCreatureType.values();
+ var7 = var33.length;
+
+ for (int var34 = 0; var34 < var7; ++var34) {
+ EnumCreatureType var35 = var33[var34];
+
+ if ((!var35.getPeacefulCreature() || par2) && (var35.getPeacefulCreature() || par1)
+ && (!var35.getAnimal() || par3)
+ && par0WorldServer.countEntities(var35.getCreatureClass()) <= var35.getMaxNumberOfCreature()
+ * eligibleChunksForSpawning.size() / 256) {
+ Iterator var36 = eligibleChunksForSpawning.keySet().iterator();
+ label110:
+
+ while (var36.hasNext()) {
+ ChunkCoordIntPair var37 = (ChunkCoordIntPair) var36.next();
+
+ if (!((Boolean) eligibleChunksForSpawning.get(var37)).booleanValue()) {
+ ChunkPosition var38 = getRandomSpawningPointInChunk(par0WorldServer, var37.chunkXPos,
+ var37.chunkZPos);
+ int var13 = var38.x;
+ int var14 = var38.y;
+ int var15 = var38.z;
+
+ if (!par0WorldServer.isBlockNormalCube(var13, var14, var15) && par0WorldServer
+ .getBlockMaterial(var13, var14, var15) == var35.getCreatureMaterial()) {
+ int var16 = 0;
+ int var17 = 0;
+
+ while (var17 < 3) {
+ int var18 = var13;
+ int var19 = var14;
+ int var20 = var15;
+ byte var21 = 6;
+ SpawnListEntry var22 = null;
+ int var23 = 0;
+
+ while (true) {
+ if (var23 < 4) {
+ label103: {
+ var18 += par0WorldServer.rand.nextInt(var21)
+ - par0WorldServer.rand.nextInt(var21);
+ var19 += par0WorldServer.rand.nextInt(1)
+ - par0WorldServer.rand.nextInt(1);
+ var20 += par0WorldServer.rand.nextInt(var21)
+ - par0WorldServer.rand.nextInt(var21);
+
+ if (canCreatureTypeSpawnAtLocation(var35, par0WorldServer, var18, var19,
+ var20)) {
+ float var24 = (float) var18 + 0.5F;
+ float var25 = (float) var19;
+ float var26 = (float) var20 + 0.5F;
+
+ if (par0WorldServer.getClosestPlayerForSpawning((double) var24,
+ (double) var25, (double) var26) == null) {
+ float var27 = var24 - (float) var32.posX;
+ float var28 = var25 - (float) var32.posY;
+ float var29 = var26 - (float) var32.posZ;
+ float var30 = var27 * var27 + var28 * var28 + var29 * var29;
+
+ if (var30 >= 576.0F) {
+ if (var22 == null) {
+ var22 = par0WorldServer.spawnRandomCreature(var35,
+ var18, var19, var20);
+
+ if (var22 == null) {
+ break label103;
+ }
+ }
+
+ EntityLiving var39;
+
+ try {
+ var39 = (EntityLiving) var22.entityConstructor.apply(par0WorldServer);
+ } catch (Exception var31) {
+ var31.printStackTrace();
+ return var4;
+ }
+
+ var39.setLocationAndAngles((double) var24, (double) var25,
+ (double) var26,
+ par0WorldServer.rand.nextFloat() * 360.0F, 0.0F);
+
+ if (var39.getCanSpawnHere()) {
+ ++var16;
+ par0WorldServer.spawnEntityInWorld(var39);
+ creatureSpecificInit(var39, par0WorldServer, var24,
+ var25, var26);
+
+ if (var16 >= var39.getMaxSpawnedInChunk()) {
+ continue label110;
+ }
+ }
+
+ var4 += var16;
+ }
+ }
+ }
+
+ ++var23;
+ continue;
+ }
+ }
+
+ ++var17;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return var4;
+ }
+ }
+
+ /**
+ * Returns whether or not the specified creature type can spawn at the specified
+ * location.
+ */
+ public static boolean canCreatureTypeSpawnAtLocation(EnumCreatureType par0EnumCreatureType, World par1World,
+ int par2, int par3, int par4) {
+ if (par0EnumCreatureType.getCreatureMaterial() == Material.water) {
+ return par1World.getBlockMaterial(par2, par3, par4).isLiquid()
+ && par1World.getBlockMaterial(par2, par3 - 1, par4).isLiquid()
+ && !par1World.isBlockNormalCube(par2, par3 + 1, par4);
+ } else if (!par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4)) {
+ return false;
+ } else {
+ int var5 = par1World.getBlockId(par2, par3 - 1, par4);
+ return var5 != Block.bedrock.blockID && !par1World.isBlockNormalCube(par2, par3, par4)
+ && !par1World.getBlockMaterial(par2, par3, par4).isLiquid()
+ && !par1World.isBlockNormalCube(par2, par3 + 1, par4);
+ }
+ }
+
+ /**
+ * determines if a skeleton spawns on a spider, and if a sheep is a different
+ * color
+ */
+ private static void creatureSpecificInit(EntityLiving par0EntityLiving, World par1World, float par2, float par3,
+ float par4) {
+ par0EntityLiving.initCreature();
+ }
+
+ /**
+ * Called during chunk generation to spawn initial creatures.
+ */
+ public static void performWorldGenSpawning(World par0World, BiomeGenBase par1BiomeGenBase, int par2, int par3,
+ int par4, int par5, EaglercraftRandom par6Random) {
+ List var7 = par1BiomeGenBase.getSpawnableList(EnumCreatureType.creature);
+
+ if (!var7.isEmpty()) {
+ while (par6Random.nextFloat() < par1BiomeGenBase.getSpawningChance()) {
+ SpawnListEntry var8 = (SpawnListEntry) WeightedRandom.getRandomItem(par0World.rand, var7);
+ int var9 = var8.minGroupCount + par6Random.nextInt(1 + var8.maxGroupCount - var8.minGroupCount);
+ int var10 = par2 + par6Random.nextInt(par4);
+ int var11 = par3 + par6Random.nextInt(par5);
+ int var12 = var10;
+ int var13 = var11;
+
+ for (int var14 = 0; var14 < var9; ++var14) {
+ boolean var15 = false;
+
+ for (int var16 = 0; !var15 && var16 < 4; ++var16) {
+ int var17 = par0World.getTopSolidOrLiquidBlock(var10, var11);
+
+ if (canCreatureTypeSpawnAtLocation(EnumCreatureType.creature, par0World, var10, var17, var11)) {
+ float var18 = (float) var10 + 0.5F;
+ float var19 = (float) var17;
+ float var20 = (float) var11 + 0.5F;
+ EntityLiving var21;
+
+ try {
+ var21 = (EntityLiving) var8.entityConstructor.apply(par0World);
+ } catch (Exception var23) {
+ var23.printStackTrace();
+ continue;
+ }
+
+ var21.setLocationAndAngles((double) var18, (double) var19, (double) var20,
+ par6Random.nextFloat() * 360.0F, 0.0F);
+ par0World.spawnEntityInWorld(var21);
+ creatureSpecificInit(var21, par0World, var18, var19, var20);
+ var15 = true;
+ }
+
+ var10 += par6Random.nextInt(5) - par6Random.nextInt(5);
+
+ for (var11 += par6Random.nextInt(5) - par6Random.nextInt(5); var10 < par2
+ || var10 >= par2 + par4 || var11 < par3 || var11 >= par3 + par4; var11 = var13
+ + par6Random.nextInt(5) - par6Random.nextInt(5)) {
+ var10 = var12 + par6Random.nextInt(5) - par6Random.nextInt(5);
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/StatBase.java b/sp-server/src/main/java/net/minecraft/src/StatBase.java
new file mode 100644
index 0000000..33be609
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/StatBase.java
@@ -0,0 +1,63 @@
+package net.minecraft.src;
+
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+import java.util.Locale;
+
+public class StatBase {
+ /** The Stat ID */
+ public final int statId;
+
+ /** The Stat name */
+ private final String statName;
+ public boolean isIndependent;
+
+ /** Holds the GUID of the stat. */
+ public String statGuid;
+ private final IStatType type;
+ private static NumberFormat numberFormat = NumberFormat.getIntegerInstance(Locale.US);
+ public static IStatType simpleStatType = new StatTypeSimple();
+ private static DecimalFormat decimalFormat = new DecimalFormat("########0.00");
+ public static IStatType timeStatType = new StatTypeTime();
+ public static IStatType distanceStatType = new StatTypeDistance();
+
+ public StatBase(int par1, String par2Str, IStatType par3IStatType) {
+ this.isIndependent = false;
+ this.statId = par1;
+ this.statName = par2Str;
+ this.type = par3IStatType;
+ }
+
+ public StatBase(int par1, String par2Str) {
+ this(par1, par2Str, simpleStatType);
+ }
+
+ /**
+ * Initializes the current stat as independent (i.e., lacking prerequisites for
+ * being updated) and returns the current instance.
+ */
+ public StatBase initIndependentStat() {
+ this.isIndependent = true;
+ return this;
+ }
+
+ /**
+ * Register the stat into StatList.
+ */
+ public StatBase registerStat() {
+ if (StatList.oneShotStats.containsKey(Integer.valueOf(this.statId))) {
+ throw new RuntimeException("Duplicate stat id: \""
+ + ((StatBase) StatList.oneShotStats.get(Integer.valueOf(this.statId))).statName + "\" and \""
+ + this.statName + "\" at id " + this.statId);
+ } else {
+ StatList.allStats.add(this);
+ StatList.oneShotStats.put(Integer.valueOf(this.statId), this);
+ this.statGuid = AchievementMap.getGuid(this.statId);
+ return this;
+ }
+ }
+
+ public String toString() {
+ return StatCollector.translateToLocal(this.statName);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/StatBasic.java b/sp-server/src/main/java/net/minecraft/src/StatBasic.java
new file mode 100644
index 0000000..a060c5f
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/StatBasic.java
@@ -0,0 +1,20 @@
+package net.minecraft.src;
+
+public class StatBasic extends StatBase {
+ public StatBasic(int par1, String par2Str, IStatType par3IStatType) {
+ super(par1, par2Str, par3IStatType);
+ }
+
+ public StatBasic(int par1, String par2Str) {
+ super(par1, par2Str);
+ }
+
+ /**
+ * Register the stat into StatList.
+ */
+ public StatBase registerStat() {
+ super.registerStat();
+ StatList.generalStats.add(this);
+ return this;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/StatCollector.java b/sp-server/src/main/java/net/minecraft/src/StatCollector.java
new file mode 100644
index 0000000..0e4cc52
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/StatCollector.java
@@ -0,0 +1,23 @@
+package net.minecraft.src;
+
+public class StatCollector {
+ private static StringTranslate localizedName = StringTranslate.getInstance();
+
+ /**
+ * Translates a Stat name
+ */
+ public static String translateToLocal(String par0Str) {
+ return localizedName.translateKey(par0Str);
+ }
+
+ /**
+ * Translates a Stat name with format args
+ */
+ public static String translateToLocalFormatted(String par0Str, Object... par1ArrayOfObj) {
+ return localizedName.translateKeyFormat(par0Str, par1ArrayOfObj);
+ }
+
+ public static boolean func_94522_b(String par0Str) {
+ return localizedName.isKeyTranslated(par0Str);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/StatCrafting.java b/sp-server/src/main/java/net/minecraft/src/StatCrafting.java
new file mode 100644
index 0000000..a6145c3
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/StatCrafting.java
@@ -0,0 +1,10 @@
+package net.minecraft.src;
+
+public class StatCrafting extends StatBase {
+ private final int itemID;
+
+ public StatCrafting(int par1, String par2Str, int par3) {
+ super(par1, par2Str);
+ this.itemID = par3;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/StatList.java b/sp-server/src/main/java/net/minecraft/src/StatList.java
new file mode 100644
index 0000000..38029c0
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/StatList.java
@@ -0,0 +1,273 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+public class StatList {
+ /** Tracks one-off stats. */
+ protected static Map oneShotStats = new HashMap();
+ public static List allStats = new ArrayList();
+ public static List generalStats = new ArrayList();
+ public static List itemStats = new ArrayList();
+
+ /** Tracks the number of times a given block or item has been mined. */
+ public static List objectMineStats = new ArrayList();
+
+ /** times the game has been started */
+ public static StatBase startGameStat = (new StatBasic(1000, "stat.startGame")).initIndependentStat().registerStat();
+
+ /** times a world has been created */
+ public static StatBase createWorldStat = (new StatBasic(1001, "stat.createWorld")).initIndependentStat()
+ .registerStat();
+
+ /** the number of times you have loaded a world */
+ public static StatBase loadWorldStat = (new StatBasic(1002, "stat.loadWorld")).initIndependentStat().registerStat();
+
+ /** number of times you've joined a multiplayer world */
+ public static StatBase joinMultiplayerStat = (new StatBasic(1003, "stat.joinMultiplayer")).initIndependentStat()
+ .registerStat();
+
+ /** number of times you've left a game */
+ public static StatBase leaveGameStat = (new StatBasic(1004, "stat.leaveGame")).initIndependentStat().registerStat();
+
+ /** number of minutes you have played */
+ public static StatBase minutesPlayedStat = (new StatBasic(1100, "stat.playOneMinute", StatBase.timeStatType))
+ .initIndependentStat().registerStat();
+
+ /** distance you've walked */
+ public static StatBase distanceWalkedStat = (new StatBasic(2000, "stat.walkOneCm", StatBase.distanceStatType))
+ .initIndependentStat().registerStat();
+
+ /** distance you have swam */
+ public static StatBase distanceSwumStat = (new StatBasic(2001, "stat.swimOneCm", StatBase.distanceStatType))
+ .initIndependentStat().registerStat();
+
+ /** the distance you have fallen */
+ public static StatBase distanceFallenStat = (new StatBasic(2002, "stat.fallOneCm", StatBase.distanceStatType))
+ .initIndependentStat().registerStat();
+
+ /** the distance you've climbed */
+ public static StatBase distanceClimbedStat = (new StatBasic(2003, "stat.climbOneCm", StatBase.distanceStatType))
+ .initIndependentStat().registerStat();
+
+ /** the distance you've flown */
+ public static StatBase distanceFlownStat = (new StatBasic(2004, "stat.flyOneCm", StatBase.distanceStatType))
+ .initIndependentStat().registerStat();
+
+ /** the distance you've dived */
+ public static StatBase distanceDoveStat = (new StatBasic(2005, "stat.diveOneCm", StatBase.distanceStatType))
+ .initIndependentStat().registerStat();
+
+ /** the distance you've traveled by minecart */
+ public static StatBase distanceByMinecartStat = (new StatBasic(2006, "stat.minecartOneCm",
+ StatBase.distanceStatType)).initIndependentStat().registerStat();
+
+ /** the distance you've traveled by boat */
+ public static StatBase distanceByBoatStat = (new StatBasic(2007, "stat.boatOneCm", StatBase.distanceStatType))
+ .initIndependentStat().registerStat();
+
+ /** the distance you've traveled by pig */
+ public static StatBase distanceByPigStat = (new StatBasic(2008, "stat.pigOneCm", StatBase.distanceStatType))
+ .initIndependentStat().registerStat();
+
+ /** the times you've jumped */
+ public static StatBase jumpStat = (new StatBasic(2010, "stat.jump")).initIndependentStat().registerStat();
+
+ /** the distance you've dropped (or times you've fallen?) */
+ public static StatBase dropStat = (new StatBasic(2011, "stat.drop")).initIndependentStat().registerStat();
+
+ /** the amount of damage you've dealt */
+ public static StatBase damageDealtStat = (new StatBasic(2020, "stat.damageDealt")).registerStat();
+
+ /** the amount of damage you have taken */
+ public static StatBase damageTakenStat = (new StatBasic(2021, "stat.damageTaken")).registerStat();
+
+ /** the number of times you have died */
+ public static StatBase deathsStat = (new StatBasic(2022, "stat.deaths")).registerStat();
+
+ /** the number of mobs you have killed */
+ public static StatBase mobKillsStat = (new StatBasic(2023, "stat.mobKills")).registerStat();
+
+ /** counts the number of times you've killed a player */
+ public static StatBase playerKillsStat = (new StatBasic(2024, "stat.playerKills")).registerStat();
+ public static StatBase fishCaughtStat = (new StatBasic(2025, "stat.fishCaught")).registerStat();
+ public static StatBase[] mineBlockStatArray = initMinableStats("stat.mineBlock", 16777216);
+
+ /** Tracks the number of items a given block or item has been crafted. */
+ public static StatBase[] objectCraftStats;
+
+ /** Tracks the number of times a given block or item has been used. */
+ public static StatBase[] objectUseStats;
+
+ /** Tracks the number of times a given block or item has been broken. */
+ public static StatBase[] objectBreakStats;
+ private static boolean blockStatsInitialized = false;
+ private static boolean itemStatsInitialized = false;
+
+
+ /**
+ * Initializes statistic fields related to breakable items and blocks.
+ */
+ public static void initBreakableStats() {
+ objectUseStats = initUsableStats(objectUseStats, "stat.useItem", 16908288, 0, 256);
+ objectBreakStats = initBreakStats(objectBreakStats, "stat.breakItem", 16973824, 0, 256);
+ blockStatsInitialized = true;
+ initCraftableStats();
+ }
+
+ public static void initStats() {
+ objectUseStats = initUsableStats(objectUseStats, "stat.useItem", 16908288, 256, 32000);
+ objectBreakStats = initBreakStats(objectBreakStats, "stat.breakItem", 16973824, 256, 32000);
+ itemStatsInitialized = true;
+ initCraftableStats();
+ }
+
+ public static void initAll() {
+ initStats();
+ initBreakableStats();
+ }
+
+ /**
+ * Initializes statistics related to craftable items. Is only called after both
+ * block and item stats have been initialized.
+ */
+ public static void initCraftableStats() {
+ if (blockStatsInitialized && itemStatsInitialized) {
+ HashSet var0 = new HashSet();
+ Iterator var1 = CraftingManager.getInstance().getRecipeList().iterator();
+
+ while (var1.hasNext()) {
+ IRecipe var2 = (IRecipe) var1.next();
+
+ if (var2.getRecipeOutput() != null) {
+ var0.add(Integer.valueOf(var2.getRecipeOutput().itemID));
+ }
+ }
+
+ var1 = FurnaceRecipes.smelting().getSmeltingList().values().iterator();
+
+ while (var1.hasNext()) {
+ ItemStack var4 = (ItemStack) var1.next();
+ var0.add(Integer.valueOf(var4.itemID));
+ }
+
+ objectCraftStats = new StatBase[32000];
+ var1 = var0.iterator();
+
+ while (var1.hasNext()) {
+ Integer var5 = (Integer) var1.next();
+
+ if (Item.itemsList[var5.intValue()] != null) {
+ String var3 = StatCollector.translateToLocalFormatted("stat.craftItem",
+ new Object[] { Item.itemsList[var5.intValue()].getStatName() });
+ objectCraftStats[var5
+ .intValue()] = (new StatCrafting(16842752 + var5.intValue(), var3, var5.intValue()))
+ .registerStat();
+ }
+ }
+
+ replaceAllSimilarBlocks(objectCraftStats);
+ }
+ }
+
+ /**
+ * Initializes statistic fields related to minable items and blocks.
+ */
+ private static StatBase[] initMinableStats(String par0Str, int par1) {
+ StatBase[] var2 = new StatBase[256];
+
+ for (int var3 = 0; var3 < 256; ++var3) {
+ if (Block.blocksList[var3] != null && Block.blocksList[var3].getEnableStats()) {
+ String var4 = StatCollector.translateToLocalFormatted(par0Str,
+ new Object[] { Block.blocksList[var3].getLocalizedName() });
+ var2[var3] = (new StatCrafting(par1 + var3, var4, var3)).registerStat();
+ objectMineStats.add((StatCrafting) var2[var3]);
+ }
+ }
+
+ replaceAllSimilarBlocks(var2);
+ return var2;
+ }
+
+ /**
+ * Initializes statistic fields related to usable items and blocks.
+ */
+ private static StatBase[] initUsableStats(StatBase[] par0ArrayOfStatBase, String par1Str, int par2, int par3,
+ int par4) {
+ if (par0ArrayOfStatBase == null) {
+ par0ArrayOfStatBase = new StatBase[32000];
+ }
+
+ for (int var5 = par3; var5 < par4; ++var5) {
+ if (Item.itemsList[var5] != null) {
+ String var6 = StatCollector.translateToLocalFormatted(par1Str,
+ new Object[] { Item.itemsList[var5].getStatName() });
+ par0ArrayOfStatBase[var5] = (new StatCrafting(par2 + var5, var6, var5)).registerStat();
+
+ if (var5 >= 256) {
+ itemStats.add((StatCrafting) par0ArrayOfStatBase[var5]);
+ }
+ }
+ }
+
+ replaceAllSimilarBlocks(par0ArrayOfStatBase);
+ return par0ArrayOfStatBase;
+ }
+
+ private static StatBase[] initBreakStats(StatBase[] par0ArrayOfStatBase, String par1Str, int par2, int par3,
+ int par4) {
+ if (par0ArrayOfStatBase == null) {
+ par0ArrayOfStatBase = new StatBase[32000];
+ }
+
+ for (int var5 = par3; var5 < par4; ++var5) {
+ if (Item.itemsList[var5] != null && Item.itemsList[var5].isDamageable()) {
+ String var6 = StatCollector.translateToLocalFormatted(par1Str,
+ new Object[] { Item.itemsList[var5].getStatName() });
+ par0ArrayOfStatBase[var5] = (new StatCrafting(par2 + var5, var6, var5)).registerStat();
+ }
+ }
+
+ replaceAllSimilarBlocks(par0ArrayOfStatBase);
+ return par0ArrayOfStatBase;
+ }
+
+ /**
+ * Forces all dual blocks to count for each other on the stats list
+ */
+ private static void replaceAllSimilarBlocks(StatBase[] par0ArrayOfStatBase) {
+ replaceSimilarBlocks(par0ArrayOfStatBase, Block.waterStill.blockID, Block.waterMoving.blockID);
+ replaceSimilarBlocks(par0ArrayOfStatBase, Block.lavaStill.blockID, Block.lavaStill.blockID);
+ replaceSimilarBlocks(par0ArrayOfStatBase, Block.pumpkinLantern.blockID, Block.pumpkin.blockID);
+ replaceSimilarBlocks(par0ArrayOfStatBase, Block.furnaceBurning.blockID, Block.furnaceIdle.blockID);
+ replaceSimilarBlocks(par0ArrayOfStatBase, Block.oreRedstoneGlowing.blockID, Block.oreRedstone.blockID);
+ replaceSimilarBlocks(par0ArrayOfStatBase, Block.redstoneRepeaterActive.blockID,
+ Block.redstoneRepeaterIdle.blockID);
+ replaceSimilarBlocks(par0ArrayOfStatBase, Block.torchRedstoneActive.blockID, Block.torchRedstoneIdle.blockID);
+ replaceSimilarBlocks(par0ArrayOfStatBase, Block.mushroomRed.blockID, Block.mushroomBrown.blockID);
+ replaceSimilarBlocks(par0ArrayOfStatBase, Block.stoneDoubleSlab.blockID, Block.stoneSingleSlab.blockID);
+ replaceSimilarBlocks(par0ArrayOfStatBase, Block.woodDoubleSlab.blockID, Block.woodSingleSlab.blockID);
+ replaceSimilarBlocks(par0ArrayOfStatBase, Block.grass.blockID, Block.dirt.blockID);
+ replaceSimilarBlocks(par0ArrayOfStatBase, Block.tilledField.blockID, Block.dirt.blockID);
+ }
+
+ /**
+ * Forces stats for one block to add to another block, such as idle and active
+ * furnaces
+ */
+ private static void replaceSimilarBlocks(StatBase[] par0ArrayOfStatBase, int par1, int par2) {
+ if (par0ArrayOfStatBase[par1] != null && par0ArrayOfStatBase[par2] == null) {
+ par0ArrayOfStatBase[par2] = par0ArrayOfStatBase[par1];
+ } else {
+ allStats.remove(par0ArrayOfStatBase[par1]);
+ objectMineStats.remove(par0ArrayOfStatBase[par1]);
+ generalStats.remove(par0ArrayOfStatBase[par1]);
+ par0ArrayOfStatBase[par1] = par0ArrayOfStatBase[par2];
+ }
+ }
+
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/StatTypeDistance.java b/sp-server/src/main/java/net/minecraft/src/StatTypeDistance.java
new file mode 100644
index 0000000..358662f
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/StatTypeDistance.java
@@ -0,0 +1,4 @@
+package net.minecraft.src;
+
+final class StatTypeDistance implements IStatType {
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/StatTypeSimple.java b/sp-server/src/main/java/net/minecraft/src/StatTypeSimple.java
new file mode 100644
index 0000000..af05cbe
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/StatTypeSimple.java
@@ -0,0 +1,4 @@
+package net.minecraft.src;
+
+final class StatTypeSimple implements IStatType {
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/StatTypeTime.java b/sp-server/src/main/java/net/minecraft/src/StatTypeTime.java
new file mode 100644
index 0000000..7d3c315
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/StatTypeTime.java
@@ -0,0 +1,4 @@
+package net.minecraft.src;
+
+final class StatTypeTime implements IStatType {
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/StepSound.java b/sp-server/src/main/java/net/minecraft/src/StepSound.java
new file mode 100644
index 0000000..04de7b9
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/StepSound.java
@@ -0,0 +1,42 @@
+package net.minecraft.src;
+
+public class StepSound {
+ public final String stepSoundName;
+ public final float stepSoundVolume;
+ public final float stepSoundPitch;
+
+ public StepSound(String par1Str, float par2, float par3) {
+ this.stepSoundName = par1Str;
+ this.stepSoundVolume = par2;
+ this.stepSoundPitch = par3;
+ }
+
+ public float getVolume() {
+ return this.stepSoundVolume;
+ }
+
+ public float getPitch() {
+ return this.stepSoundPitch;
+ }
+
+ /**
+ * Used when a block breaks, EXA: Player break, Shep eating grass, etc..
+ */
+ public String getBreakSound() {
+ return "dig." + this.stepSoundName;
+ }
+
+ /**
+ * Used when a entity walks over, or otherwise interacts with the block.
+ */
+ public String getStepSound() {
+ return "step." + this.stepSoundName;
+ }
+
+ /**
+ * Used when a player places a block.
+ */
+ public String getPlaceSound() {
+ return this.getBreakSound();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/StepSoundAnvil.java b/sp-server/src/main/java/net/minecraft/src/StepSoundAnvil.java
new file mode 100644
index 0000000..21a4858
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/StepSoundAnvil.java
@@ -0,0 +1,21 @@
+package net.minecraft.src;
+
+final class StepSoundAnvil extends StepSound {
+ StepSoundAnvil(String par1Str, float par2, float par3) {
+ super(par1Str, par2, par3);
+ }
+
+ /**
+ * Used when a block breaks, EXA: Player break, Shep eating grass, etc..
+ */
+ public String getBreakSound() {
+ return "dig.stone";
+ }
+
+ /**
+ * Used when a player places a block.
+ */
+ public String getPlaceSound() {
+ return "random.anvil_land";
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/StepSoundSand.java b/sp-server/src/main/java/net/minecraft/src/StepSoundSand.java
new file mode 100644
index 0000000..fa7bab6
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/StepSoundSand.java
@@ -0,0 +1,14 @@
+package net.minecraft.src;
+
+final class StepSoundSand extends StepSound {
+ StepSoundSand(String par1Str, float par2, float par3) {
+ super(par1Str, par2, par3);
+ }
+
+ /**
+ * Used when a block breaks, EXA: Player break, Shep eating grass, etc..
+ */
+ public String getBreakSound() {
+ return "dig.wood";
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/StepSoundStone.java b/sp-server/src/main/java/net/minecraft/src/StepSoundStone.java
new file mode 100644
index 0000000..cdbb8dc
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/StepSoundStone.java
@@ -0,0 +1,21 @@
+package net.minecraft.src;
+
+final class StepSoundStone extends StepSound {
+ StepSoundStone(String par1Str, float par2, float par3) {
+ super(par1Str, par2, par3);
+ }
+
+ /**
+ * Used when a block breaks, EXA: Player break, Shep eating grass, etc..
+ */
+ public String getBreakSound() {
+ return "random.glass";
+ }
+
+ /**
+ * Used when a player places a block.
+ */
+ public String getPlaceSound() {
+ return "step.stone";
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/StringTranslate.java b/sp-server/src/main/java/net/minecraft/src/StringTranslate.java
new file mode 100644
index 0000000..144d079
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/StringTranslate.java
@@ -0,0 +1,94 @@
+package net.minecraft.src;
+
+import java.util.IllegalFormatException;
+import java.util.List;
+import java.util.Properties;
+import java.util.TreeMap;
+
+public class StringTranslate {
+ /** Is the private singleton instance of StringTranslate. */
+ private static StringTranslate instance = new StringTranslate(null);
+
+ /**
+ * Contains all key/value pairs to be translated - is loaded from
+ * '/lang/en_US.lang' when the StringTranslate is created.
+ */
+ private Properties translateTable = new Properties();
+ private TreeMap languageList;
+
+ private StringTranslate(List en_us) {
+ loadLanguageList(en_us);
+ }
+
+ public static void init(List en_us) {
+ instance.loadLanguageList(en_us);
+ }
+
+ /**
+ * Return the StringTranslate singleton instance
+ */
+ public static StringTranslate getInstance() {
+ return instance;
+ }
+
+ private void loadLanguageList(List en_us) {
+ this.languageList = new TreeMap();
+ this.languageList.put("en_US", "English (US)");
+ if(en_us != null) {
+ loadLanguage(en_us);
+ }
+ }
+
+ public TreeMap getLanguageList() {
+ return this.languageList;
+ }
+
+ private void loadLanguage(List en_us) {
+ for (String var4 : en_us) {
+ var4 = var4.trim();
+
+ if (!var4.startsWith("#")) {
+ String[] var5 = var4.split("=");
+
+ if (var5 != null && var5.length == 2) {
+ translateTable.setProperty(var5[0], var5[1]);
+ }
+ }
+ }
+ }
+
+ /**
+ * Translate a key to current language.
+ */
+ public synchronized String translateKey(String par1Str) {
+ return this.translateTable.getProperty(par1Str, par1Str);
+ }
+
+ /**
+ * Translate a key to current language applying String.format()
+ */
+ public synchronized String translateKeyFormat(String par1Str, Object... par2ArrayOfObj) {
+ String var3 = this.translateTable.getProperty(par1Str, par1Str);
+
+ try {
+ return String.format(var3, par2ArrayOfObj);
+ } catch (IllegalFormatException var5) {
+ return "Format error: " + var3;
+ }
+ }
+
+ /**
+ * Returns true if the passed key is in the translation table.
+ */
+ public synchronized boolean isKeyTranslated(String par1Str) {
+ return this.translateTable.containsKey(par1Str);
+ }
+
+ /**
+ * Translate a key with a extra '.name' at end added, is used by blocks and
+ * items.
+ */
+ public synchronized String translateNamedKey(String par1Str) {
+ return this.translateTable.getProperty(par1Str + ".name", "");
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/StringUtils.java b/sp-server/src/main/java/net/minecraft/src/StringUtils.java
new file mode 100644
index 0000000..ece549e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/StringUtils.java
@@ -0,0 +1,11 @@
+package net.minecraft.src;
+
+import java.util.regex.Pattern;
+
+public class StringUtils {
+ private static final Pattern patternControlCode = Pattern.compile("(?i)\\u00A7[0-9A-FK-OR]");
+
+ public static String stripControlCodes(String par0Str) {
+ return patternControlCode.matcher(par0Str).replaceAll("");
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/StructureBoundingBox.java b/sp-server/src/main/java/net/minecraft/src/StructureBoundingBox.java
new file mode 100644
index 0000000..bfdef33
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/StructureBoundingBox.java
@@ -0,0 +1,174 @@
+package net.minecraft.src;
+
+public class StructureBoundingBox {
+ /** The first x coordinate of a bounding box. */
+ public int minX;
+
+ /** The first y coordinate of a bounding box. */
+ public int minY;
+
+ /** The first z coordinate of a bounding box. */
+ public int minZ;
+
+ /** The second x coordinate of a bounding box. */
+ public int maxX;
+
+ /** The second y coordinate of a bounding box. */
+ public int maxY;
+
+ /** The second z coordinate of a bounding box. */
+ public int maxZ;
+
+ public StructureBoundingBox() {
+ }
+
+ /**
+ * returns a new StructureBoundingBox with MAX values
+ */
+ public static StructureBoundingBox getNewBoundingBox() {
+ return new StructureBoundingBox(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE,
+ Integer.MIN_VALUE, Integer.MIN_VALUE);
+ }
+
+ /**
+ * used to project a possible new component Bounding Box - to check if it would
+ * cut anything already spawned
+ */
+ public static StructureBoundingBox getComponentToAddBoundingBox(int par0, int par1, int par2, int par3, int par4,
+ int par5, int par6, int par7, int par8, int par9) {
+ switch (par9) {
+ case 0:
+ return new StructureBoundingBox(par0 + par3, par1 + par4, par2 + par5, par0 + par6 - 1 + par3,
+ par1 + par7 - 1 + par4, par2 + par8 - 1 + par5);
+
+ case 1:
+ return new StructureBoundingBox(par0 - par8 + 1 + par5, par1 + par4, par2 + par3, par0 + par5,
+ par1 + par7 - 1 + par4, par2 + par6 - 1 + par3);
+
+ case 2:
+ return new StructureBoundingBox(par0 + par3, par1 + par4, par2 - par8 + 1 + par5, par0 + par6 - 1 + par3,
+ par1 + par7 - 1 + par4, par2 + par5);
+
+ case 3:
+ return new StructureBoundingBox(par0 + par5, par1 + par4, par2 + par3, par0 + par8 - 1 + par5,
+ par1 + par7 - 1 + par4, par2 + par6 - 1 + par3);
+
+ default:
+ return new StructureBoundingBox(par0 + par3, par1 + par4, par2 + par5, par0 + par6 - 1 + par3,
+ par1 + par7 - 1 + par4, par2 + par8 - 1 + par5);
+ }
+ }
+
+ public StructureBoundingBox(StructureBoundingBox par1StructureBoundingBox) {
+ this.minX = par1StructureBoundingBox.minX;
+ this.minY = par1StructureBoundingBox.minY;
+ this.minZ = par1StructureBoundingBox.minZ;
+ this.maxX = par1StructureBoundingBox.maxX;
+ this.maxY = par1StructureBoundingBox.maxY;
+ this.maxZ = par1StructureBoundingBox.maxZ;
+ }
+
+ public StructureBoundingBox(int par1, int par2, int par3, int par4, int par5, int par6) {
+ this.minX = par1;
+ this.minY = par2;
+ this.minZ = par3;
+ this.maxX = par4;
+ this.maxY = par5;
+ this.maxZ = par6;
+ }
+
+ public StructureBoundingBox(int par1, int par2, int par3, int par4) {
+ this.minX = par1;
+ this.minZ = par2;
+ this.maxX = par3;
+ this.maxZ = par4;
+ this.minY = 1;
+ this.maxY = 512;
+ }
+
+ /**
+ * Discover if bounding box can fit within the current bounding box object.
+ */
+ public boolean intersectsWith(StructureBoundingBox par1StructureBoundingBox) {
+ return this.maxX >= par1StructureBoundingBox.minX && this.minX <= par1StructureBoundingBox.maxX
+ && this.maxZ >= par1StructureBoundingBox.minZ && this.minZ <= par1StructureBoundingBox.maxZ
+ && this.maxY >= par1StructureBoundingBox.minY && this.minY <= par1StructureBoundingBox.maxY;
+ }
+
+ /**
+ * Discover if a coordinate is inside the bounding box area.
+ */
+ public boolean intersectsWith(int par1, int par2, int par3, int par4) {
+ return this.maxX >= par1 && this.minX <= par3 && this.maxZ >= par2 && this.minZ <= par4;
+ }
+
+ /**
+ * Expands a bounding box's dimensions to include the supplied bounding box.
+ */
+ public void expandTo(StructureBoundingBox par1StructureBoundingBox) {
+ this.minX = Math.min(this.minX, par1StructureBoundingBox.minX);
+ this.minY = Math.min(this.minY, par1StructureBoundingBox.minY);
+ this.minZ = Math.min(this.minZ, par1StructureBoundingBox.minZ);
+ this.maxX = Math.max(this.maxX, par1StructureBoundingBox.maxX);
+ this.maxY = Math.max(this.maxY, par1StructureBoundingBox.maxY);
+ this.maxZ = Math.max(this.maxZ, par1StructureBoundingBox.maxZ);
+ }
+
+ /**
+ * Offsets the current bounding box by the specified coordinates. Args: x, y, z
+ */
+ public void offset(int par1, int par2, int par3) {
+ this.minX += par1;
+ this.minY += par2;
+ this.minZ += par3;
+ this.maxX += par1;
+ this.maxY += par2;
+ this.maxZ += par3;
+ }
+
+ /**
+ * Discover if a coordinate is inside the bounding box volume.
+ */
+ public boolean isVecInside(int par1, int par2, int par3) {
+ return par1 >= this.minX && par1 <= this.maxX && par3 >= this.minZ && par3 <= this.maxZ && par2 >= this.minY
+ && par2 <= this.maxY;
+ }
+
+ /**
+ * Get dimension of the bounding box in the x direction.
+ */
+ public int getXSize() {
+ return this.maxX - this.minX + 1;
+ }
+
+ /**
+ * Get dimension of the bounding box in the y direction.
+ */
+ public int getYSize() {
+ return this.maxY - this.minY + 1;
+ }
+
+ /**
+ * Get dimension of the bounding box in the z direction.
+ */
+ public int getZSize() {
+ return this.maxZ - this.minZ + 1;
+ }
+
+ public int getCenterX() {
+ return this.minX + (this.maxX - this.minX + 1) / 2;
+ }
+
+ public int getCenterY() {
+ return this.minY + (this.maxY - this.minY + 1) / 2;
+ }
+
+ public int getCenterZ() {
+ return this.minZ + (this.maxZ - this.minZ + 1) / 2;
+ }
+
+ public String toString() {
+ return "(" + this.minX + ", " + this.minY + ", " + this.minZ + "; " + this.maxX + ", " + this.maxY + ", "
+ + this.maxZ + ")";
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/StructureComponent.java b/sp-server/src/main/java/net/minecraft/src/StructureComponent.java
new file mode 100644
index 0000000..5fb0838
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/StructureComponent.java
@@ -0,0 +1,705 @@
+package net.minecraft.src;
+
+import java.util.Iterator;
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public abstract class StructureComponent {
+ protected StructureBoundingBox boundingBox;
+
+ /** switches the Coordinate System base off the Bounding Box */
+ protected int coordBaseMode;
+
+ /** The type ID of this component. */
+ protected int componentType;
+
+ protected StructureComponent(int par1) {
+ this.componentType = par1;
+ this.coordBaseMode = -1;
+ }
+
+ /**
+ * Initiates construction of the Structure Component picked, at the current
+ * Location of StructGen
+ */
+ public void buildComponent(StructureComponent par1StructureComponent, List par2List, EaglercraftRandom par3Random) {
+ }
+
+ /**
+ * second Part of Structure generating, this for example places Spiderwebs, Mob
+ * Spawners, it closes Mineshafts at the end, it adds Fences...
+ */
+ public abstract boolean addComponentParts(World var1, EaglercraftRandom var2, StructureBoundingBox var3);
+
+ public StructureBoundingBox getBoundingBox() {
+ return this.boundingBox;
+ }
+
+ /**
+ * Returns the component type ID of this component.
+ */
+ public int getComponentType() {
+ return this.componentType;
+ }
+
+ /**
+ * Discover if bounding box can fit within the current bounding box object.
+ */
+ public static StructureComponent findIntersecting(List par0List, StructureBoundingBox par1StructureBoundingBox) {
+ Iterator var2 = par0List.iterator();
+ StructureComponent var3;
+
+ do {
+ if (!var2.hasNext()) {
+ return null;
+ }
+
+ var3 = (StructureComponent) var2.next();
+ } while (var3.getBoundingBox() == null || !var3.getBoundingBox().intersectsWith(par1StructureBoundingBox));
+
+ return var3;
+ }
+
+ public ChunkPosition getCenter() {
+ return new ChunkPosition(this.boundingBox.getCenterX(), this.boundingBox.getCenterY(),
+ this.boundingBox.getCenterZ());
+ }
+
+ /**
+ * checks the entire StructureBoundingBox for Liquids
+ */
+ protected boolean isLiquidInStructureBoundingBox(World par1World, StructureBoundingBox par2StructureBoundingBox) {
+ int var3 = Math.max(this.boundingBox.minX - 1, par2StructureBoundingBox.minX);
+ int var4 = Math.max(this.boundingBox.minY - 1, par2StructureBoundingBox.minY);
+ int var5 = Math.max(this.boundingBox.minZ - 1, par2StructureBoundingBox.minZ);
+ int var6 = Math.min(this.boundingBox.maxX + 1, par2StructureBoundingBox.maxX);
+ int var7 = Math.min(this.boundingBox.maxY + 1, par2StructureBoundingBox.maxY);
+ int var8 = Math.min(this.boundingBox.maxZ + 1, par2StructureBoundingBox.maxZ);
+ int var9;
+ int var10;
+ int var11;
+
+ for (var9 = var3; var9 <= var6; ++var9) {
+ for (var10 = var5; var10 <= var8; ++var10) {
+ var11 = par1World.getBlockId(var9, var4, var10);
+
+ if (var11 > 0 && Block.blocksList[var11].blockMaterial.isLiquid()) {
+ return true;
+ }
+
+ var11 = par1World.getBlockId(var9, var7, var10);
+
+ if (var11 > 0 && Block.blocksList[var11].blockMaterial.isLiquid()) {
+ return true;
+ }
+ }
+ }
+
+ for (var9 = var3; var9 <= var6; ++var9) {
+ for (var10 = var4; var10 <= var7; ++var10) {
+ var11 = par1World.getBlockId(var9, var10, var5);
+
+ if (var11 > 0 && Block.blocksList[var11].blockMaterial.isLiquid()) {
+ return true;
+ }
+
+ var11 = par1World.getBlockId(var9, var10, var8);
+
+ if (var11 > 0 && Block.blocksList[var11].blockMaterial.isLiquid()) {
+ return true;
+ }
+ }
+ }
+
+ for (var9 = var5; var9 <= var8; ++var9) {
+ for (var10 = var4; var10 <= var7; ++var10) {
+ var11 = par1World.getBlockId(var3, var10, var9);
+
+ if (var11 > 0 && Block.blocksList[var11].blockMaterial.isLiquid()) {
+ return true;
+ }
+
+ var11 = par1World.getBlockId(var6, var10, var9);
+
+ if (var11 > 0 && Block.blocksList[var11].blockMaterial.isLiquid()) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ protected int getXWithOffset(int par1, int par2) {
+ switch (this.coordBaseMode) {
+ case 0:
+ case 2:
+ return this.boundingBox.minX + par1;
+
+ case 1:
+ return this.boundingBox.maxX - par2;
+
+ case 3:
+ return this.boundingBox.minX + par2;
+
+ default:
+ return par1;
+ }
+ }
+
+ protected int getYWithOffset(int par1) {
+ return this.coordBaseMode == -1 ? par1 : par1 + this.boundingBox.minY;
+ }
+
+ protected int getZWithOffset(int par1, int par2) {
+ switch (this.coordBaseMode) {
+ case 0:
+ return this.boundingBox.minZ + par2;
+
+ case 1:
+ case 3:
+ return this.boundingBox.minZ + par1;
+
+ case 2:
+ return this.boundingBox.maxZ - par2;
+
+ default:
+ return par2;
+ }
+ }
+
+ /**
+ * Returns the direction-shifted metadata for blocks that require orientation,
+ * e.g. doors, stairs, ladders. Parameters: block ID, original metadata
+ */
+ protected int getMetadataWithOffset(int par1, int par2) {
+ if (par1 == Block.rail.blockID) {
+ if (this.coordBaseMode == 1 || this.coordBaseMode == 3) {
+ if (par2 == 1) {
+ return 0;
+ }
+
+ return 1;
+ }
+ } else if (par1 != Block.doorWood.blockID && par1 != Block.doorIron.blockID) {
+ if (par1 != Block.stairsCobblestone.blockID && par1 != Block.stairsWoodOak.blockID
+ && par1 != Block.stairsNetherBrick.blockID && par1 != Block.stairsStoneBrick.blockID
+ && par1 != Block.stairsSandStone.blockID) {
+ if (par1 == Block.ladder.blockID) {
+ if (this.coordBaseMode == 0) {
+ if (par2 == 2) {
+ return 3;
+ }
+
+ if (par2 == 3) {
+ return 2;
+ }
+ } else if (this.coordBaseMode == 1) {
+ if (par2 == 2) {
+ return 4;
+ }
+
+ if (par2 == 3) {
+ return 5;
+ }
+
+ if (par2 == 4) {
+ return 2;
+ }
+
+ if (par2 == 5) {
+ return 3;
+ }
+ } else if (this.coordBaseMode == 3) {
+ if (par2 == 2) {
+ return 5;
+ }
+
+ if (par2 == 3) {
+ return 4;
+ }
+
+ if (par2 == 4) {
+ return 2;
+ }
+
+ if (par2 == 5) {
+ return 3;
+ }
+ }
+ } else if (par1 == Block.stoneButton.blockID) {
+ if (this.coordBaseMode == 0) {
+ if (par2 == 3) {
+ return 4;
+ }
+
+ if (par2 == 4) {
+ return 3;
+ }
+ } else if (this.coordBaseMode == 1) {
+ if (par2 == 3) {
+ return 1;
+ }
+
+ if (par2 == 4) {
+ return 2;
+ }
+
+ if (par2 == 2) {
+ return 3;
+ }
+
+ if (par2 == 1) {
+ return 4;
+ }
+ } else if (this.coordBaseMode == 3) {
+ if (par2 == 3) {
+ return 2;
+ }
+
+ if (par2 == 4) {
+ return 1;
+ }
+
+ if (par2 == 2) {
+ return 3;
+ }
+
+ if (par2 == 1) {
+ return 4;
+ }
+ }
+ } else if (par1 != Block.tripWireSource.blockID
+ && (Block.blocksList[par1] == null || !(Block.blocksList[par1] instanceof BlockDirectional))) {
+ if (par1 == Block.pistonBase.blockID || par1 == Block.pistonStickyBase.blockID
+ || par1 == Block.lever.blockID || par1 == Block.dispenser.blockID) {
+ if (this.coordBaseMode == 0) {
+ if (par2 == 2 || par2 == 3) {
+ return Facing.oppositeSide[par2];
+ }
+ } else if (this.coordBaseMode == 1) {
+ if (par2 == 2) {
+ return 4;
+ }
+
+ if (par2 == 3) {
+ return 5;
+ }
+
+ if (par2 == 4) {
+ return 2;
+ }
+
+ if (par2 == 5) {
+ return 3;
+ }
+ } else if (this.coordBaseMode == 3) {
+ if (par2 == 2) {
+ return 5;
+ }
+
+ if (par2 == 3) {
+ return 4;
+ }
+
+ if (par2 == 4) {
+ return 2;
+ }
+
+ if (par2 == 5) {
+ return 3;
+ }
+ }
+ }
+ } else if (this.coordBaseMode == 0) {
+ if (par2 == 0 || par2 == 2) {
+ return Direction.footInvisibleFaceRemap[par2];
+ }
+ } else if (this.coordBaseMode == 1) {
+ if (par2 == 2) {
+ return 1;
+ }
+
+ if (par2 == 0) {
+ return 3;
+ }
+
+ if (par2 == 1) {
+ return 2;
+ }
+
+ if (par2 == 3) {
+ return 0;
+ }
+ } else if (this.coordBaseMode == 3) {
+ if (par2 == 2) {
+ return 3;
+ }
+
+ if (par2 == 0) {
+ return 1;
+ }
+
+ if (par2 == 1) {
+ return 2;
+ }
+
+ if (par2 == 3) {
+ return 0;
+ }
+ }
+ } else if (this.coordBaseMode == 0) {
+ if (par2 == 2) {
+ return 3;
+ }
+
+ if (par2 == 3) {
+ return 2;
+ }
+ } else if (this.coordBaseMode == 1) {
+ if (par2 == 0) {
+ return 2;
+ }
+
+ if (par2 == 1) {
+ return 3;
+ }
+
+ if (par2 == 2) {
+ return 0;
+ }
+
+ if (par2 == 3) {
+ return 1;
+ }
+ } else if (this.coordBaseMode == 3) {
+ if (par2 == 0) {
+ return 2;
+ }
+
+ if (par2 == 1) {
+ return 3;
+ }
+
+ if (par2 == 2) {
+ return 1;
+ }
+
+ if (par2 == 3) {
+ return 0;
+ }
+ }
+ } else if (this.coordBaseMode == 0) {
+ if (par2 == 0) {
+ return 2;
+ }
+
+ if (par2 == 2) {
+ return 0;
+ }
+ } else {
+ if (this.coordBaseMode == 1) {
+ return par2 + 1 & 3;
+ }
+
+ if (this.coordBaseMode == 3) {
+ return par2 + 3 & 3;
+ }
+ }
+
+ return par2;
+ }
+
+ /**
+ * current Position depends on currently set Coordinates mode, is computed here
+ */
+ protected void placeBlockAtCurrentPosition(World par1World, int par2, int par3, int par4, int par5, int par6,
+ StructureBoundingBox par7StructureBoundingBox) {
+ int var8 = this.getXWithOffset(par4, par6);
+ int var9 = this.getYWithOffset(par5);
+ int var10 = this.getZWithOffset(par4, par6);
+
+ if (par7StructureBoundingBox.isVecInside(var8, var9, var10)) {
+ par1World.setBlock(var8, var9, var10, par2, par3, 2);
+ }
+ }
+
+ protected int getBlockIdAtCurrentPosition(World par1World, int par2, int par3, int par4,
+ StructureBoundingBox par5StructureBoundingBox) {
+ int var6 = this.getXWithOffset(par2, par4);
+ int var7 = this.getYWithOffset(par3);
+ int var8 = this.getZWithOffset(par2, par4);
+ return !par5StructureBoundingBox.isVecInside(var6, var7, var8) ? 0 : par1World.getBlockId(var6, var7, var8);
+ }
+
+ /**
+ * arguments: (World worldObj, StructureBoundingBox structBB, int minX, int
+ * minY, int minZ, int maxX, int maxY, int maxZ)
+ */
+ protected void fillWithAir(World par1World, StructureBoundingBox par2StructureBoundingBox, int par3, int par4,
+ int par5, int par6, int par7, int par8) {
+ for (int var9 = par4; var9 <= par7; ++var9) {
+ for (int var10 = par3; var10 <= par6; ++var10) {
+ for (int var11 = par5; var11 <= par8; ++var11) {
+ this.placeBlockAtCurrentPosition(par1World, 0, 0, var10, var9, var11, par2StructureBoundingBox);
+ }
+ }
+ }
+ }
+
+ /**
+ * arguments: (World worldObj, StructureBoundingBox structBB, int minX, int
+ * minY, int minZ, int maxX, int maxY, int maxZ, int placeBlockId, int
+ * replaceBlockId, boolean alwaysreplace)
+ */
+ protected void fillWithBlocks(World par1World, StructureBoundingBox par2StructureBoundingBox, int par3, int par4,
+ int par5, int par6, int par7, int par8, int par9, int par10, boolean par11) {
+ for (int var12 = par4; var12 <= par7; ++var12) {
+ for (int var13 = par3; var13 <= par6; ++var13) {
+ for (int var14 = par5; var14 <= par8; ++var14) {
+ if (!par11 || this.getBlockIdAtCurrentPosition(par1World, var13, var12, var14,
+ par2StructureBoundingBox) != 0) {
+ if (var12 != par4 && var12 != par7 && var13 != par3 && var13 != par6 && var14 != par5
+ && var14 != par8) {
+ this.placeBlockAtCurrentPosition(par1World, par10, 0, var13, var12, var14,
+ par2StructureBoundingBox);
+ } else {
+ this.placeBlockAtCurrentPosition(par1World, par9, 0, var13, var12, var14,
+ par2StructureBoundingBox);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * arguments: (World worldObj, StructureBoundingBox structBB, int minX, int
+ * minY, int minZ, int maxX, int maxY, int maxZ, int placeBlockId, int
+ * placeBlockMetadata, int replaceBlockId, int replaceBlockMetadata, boolean
+ * alwaysreplace)
+ */
+ protected void fillWithMetadataBlocks(World par1World, StructureBoundingBox par2StructureBoundingBox, int par3,
+ int par4, int par5, int par6, int par7, int par8, int par9, int par10, int par11, int par12,
+ boolean par13) {
+ for (int var14 = par4; var14 <= par7; ++var14) {
+ for (int var15 = par3; var15 <= par6; ++var15) {
+ for (int var16 = par5; var16 <= par8; ++var16) {
+ if (!par13 || this.getBlockIdAtCurrentPosition(par1World, var15, var14, var16,
+ par2StructureBoundingBox) != 0) {
+ if (var14 != par4 && var14 != par7 && var15 != par3 && var15 != par6 && var16 != par5
+ && var16 != par8) {
+ this.placeBlockAtCurrentPosition(par1World, par11, par12, var15, var14, var16,
+ par2StructureBoundingBox);
+ } else {
+ this.placeBlockAtCurrentPosition(par1World, par9, par10, var15, var14, var16,
+ par2StructureBoundingBox);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * arguments: World worldObj, StructureBoundingBox structBB, int minX, int minY,
+ * int minZ, int maxX, int maxY, int maxZ, boolean alwaysreplace, Random rand,
+ * StructurePieceBlockSelector blockselector
+ */
+ protected void fillWithRandomizedBlocks(World par1World, StructureBoundingBox par2StructureBoundingBox, int par3,
+ int par4, int par5, int par6, int par7, int par8, boolean par9, EaglercraftRandom par10Random,
+ StructurePieceBlockSelector par11StructurePieceBlockSelector) {
+ for (int var12 = par4; var12 <= par7; ++var12) {
+ for (int var13 = par3; var13 <= par6; ++var13) {
+ for (int var14 = par5; var14 <= par8; ++var14) {
+ if (!par9 || this.getBlockIdAtCurrentPosition(par1World, var13, var12, var14,
+ par2StructureBoundingBox) != 0) {
+ par11StructurePieceBlockSelector.selectBlocks(par10Random, var13, var12, var14, var12 == par4
+ || var12 == par7 || var13 == par3 || var13 == par6 || var14 == par5 || var14 == par8);
+ this.placeBlockAtCurrentPosition(par1World,
+ par11StructurePieceBlockSelector.getSelectedBlockId(),
+ par11StructurePieceBlockSelector.getSelectedBlockMetaData(), var13, var12, var14,
+ par2StructureBoundingBox);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * arguments: World worldObj, StructureBoundingBox structBB, Random rand, float
+ * randLimit, int minX, int minY, int minZ, int maxX, int maxY, int maxZ, int
+ * olaceBlockId, int replaceBlockId, boolean alwaysreplace
+ */
+ protected void randomlyFillWithBlocks(World par1World, StructureBoundingBox par2StructureBoundingBox,
+ EaglercraftRandom par3Random, float par4, int par5, int par6, int par7, int par8, int par9, int par10, int par11,
+ int par12, boolean par13) {
+ for (int var14 = par6; var14 <= par9; ++var14) {
+ for (int var15 = par5; var15 <= par8; ++var15) {
+ for (int var16 = par7; var16 <= par10; ++var16) {
+ if (par3Random.nextFloat() <= par4 && (!par13 || this.getBlockIdAtCurrentPosition(par1World, var15,
+ var14, var16, par2StructureBoundingBox) != 0)) {
+ if (var14 != par6 && var14 != par9 && var15 != par5 && var15 != par8 && var16 != par7
+ && var16 != par10) {
+ this.placeBlockAtCurrentPosition(par1World, par12, 0, var15, var14, var16,
+ par2StructureBoundingBox);
+ } else {
+ this.placeBlockAtCurrentPosition(par1World, par11, 0, var15, var14, var16,
+ par2StructureBoundingBox);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Randomly decides if placing or not. Used for Decoration such as Torches and
+ * Spiderwebs
+ */
+ protected void randomlyPlaceBlock(World par1World, StructureBoundingBox par2StructureBoundingBox, EaglercraftRandom par3Random,
+ float par4, int par5, int par6, int par7, int par8, int par9) {
+ if (par3Random.nextFloat() < par4) {
+ this.placeBlockAtCurrentPosition(par1World, par8, par9, par5, par6, par7, par2StructureBoundingBox);
+ }
+ }
+
+ /**
+ * arguments: World worldObj, StructureBoundingBox structBB, int minX, int minY,
+ * int minZ, int maxX, int maxY, int maxZ, int placeBlockId, boolean
+ * alwaysreplace
+ */
+ protected void randomlyRareFillWithBlocks(World par1World, StructureBoundingBox par2StructureBoundingBox, int par3,
+ int par4, int par5, int par6, int par7, int par8, int par9, boolean par10) {
+ float var11 = (float) (par6 - par3 + 1);
+ float var12 = (float) (par7 - par4 + 1);
+ float var13 = (float) (par8 - par5 + 1);
+ float var14 = (float) par3 + var11 / 2.0F;
+ float var15 = (float) par5 + var13 / 2.0F;
+
+ for (int var16 = par4; var16 <= par7; ++var16) {
+ float var17 = (float) (var16 - par4) / var12;
+
+ for (int var18 = par3; var18 <= par6; ++var18) {
+ float var19 = ((float) var18 - var14) / (var11 * 0.5F);
+
+ for (int var20 = par5; var20 <= par8; ++var20) {
+ float var21 = ((float) var20 - var15) / (var13 * 0.5F);
+
+ if (!par10 || this.getBlockIdAtCurrentPosition(par1World, var18, var16, var20,
+ par2StructureBoundingBox) != 0) {
+ float var22 = var19 * var19 + var17 * var17 + var21 * var21;
+
+ if (var22 <= 1.05F) {
+ this.placeBlockAtCurrentPosition(par1World, par9, 0, var18, var16, var20,
+ par2StructureBoundingBox);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Deletes all continuous blocks from selected position upwards. Stops at
+ * hitting air.
+ */
+ protected void clearCurrentPositionBlocksUpwards(World par1World, int par2, int par3, int par4,
+ StructureBoundingBox par5StructureBoundingBox) {
+ int var6 = this.getXWithOffset(par2, par4);
+ int var7 = this.getYWithOffset(par3);
+ int var8 = this.getZWithOffset(par2, par4);
+
+ if (par5StructureBoundingBox.isVecInside(var6, var7, var8)) {
+ while (!par1World.isAirBlock(var6, var7, var8) && var7 < 255) {
+ par1World.setBlock(var6, var7, var8, 0, 0, 2);
+ ++var7;
+ }
+ }
+ }
+
+ /**
+ * Overwrites air and liquids from selected position downwards, stops at hitting
+ * anything else.
+ */
+ protected void fillCurrentPositionBlocksDownwards(World par1World, int par2, int par3, int par4, int par5, int par6,
+ StructureBoundingBox par7StructureBoundingBox) {
+ int var8 = this.getXWithOffset(par4, par6);
+ int var9 = this.getYWithOffset(par5);
+ int var10 = this.getZWithOffset(par4, par6);
+
+ if (par7StructureBoundingBox.isVecInside(var8, var9, var10)) {
+ while ((par1World.isAirBlock(var8, var9, var10) || par1World.getBlockMaterial(var8, var9, var10).isLiquid())
+ && var9 > 1) {
+ par1World.setBlock(var8, var9, var10, par2, par3, 2);
+ --var9;
+ }
+ }
+ }
+
+ /**
+ * Used to generate chests with items in it. ex: Temple Chests, Village
+ * Blacksmith Chests, Mineshaft Chests.
+ */
+ protected boolean generateStructureChestContents(World par1World, StructureBoundingBox par2StructureBoundingBox,
+ EaglercraftRandom par3Random, int par4, int par5, int par6,
+ WeightedRandomChestContent[] par7ArrayOfWeightedRandomChestContent, int par8) {
+ int var9 = this.getXWithOffset(par4, par6);
+ int var10 = this.getYWithOffset(par5);
+ int var11 = this.getZWithOffset(par4, par6);
+
+ if (par2StructureBoundingBox.isVecInside(var9, var10, var11)
+ && par1World.getBlockId(var9, var10, var11) != Block.chest.blockID) {
+ par1World.setBlock(var9, var10, var11, Block.chest.blockID, 0, 2);
+ TileEntityChest var12 = (TileEntityChest) par1World.getBlockTileEntity(var9, var10, var11);
+
+ if (var12 != null) {
+ WeightedRandomChestContent.generateChestContents(par3Random, par7ArrayOfWeightedRandomChestContent,
+ var12, par8);
+ }
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Used to generate dispenser contents for structures. ex: Jungle Temples.
+ */
+ protected boolean generateStructureDispenserContents(World par1World, StructureBoundingBox par2StructureBoundingBox,
+ EaglercraftRandom par3Random, int par4, int par5, int par6, int par7,
+ WeightedRandomChestContent[] par8ArrayOfWeightedRandomChestContent, int par9) {
+ int var10 = this.getXWithOffset(par4, par6);
+ int var11 = this.getYWithOffset(par5);
+ int var12 = this.getZWithOffset(par4, par6);
+
+ if (par2StructureBoundingBox.isVecInside(var10, var11, var12)
+ && par1World.getBlockId(var10, var11, var12) != Block.dispenser.blockID) {
+ par1World.setBlock(var10, var11, var12, Block.dispenser.blockID,
+ this.getMetadataWithOffset(Block.dispenser.blockID, par7), 2);
+ TileEntityDispenser var13 = (TileEntityDispenser) par1World.getBlockTileEntity(var10, var11, var12);
+
+ if (var13 != null) {
+ WeightedRandomChestContent.generateDispenserContents(par3Random, par8ArrayOfWeightedRandomChestContent,
+ var13, par9);
+ }
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ protected void placeDoorAtCurrentPosition(World par1World, StructureBoundingBox par2StructureBoundingBox,
+ EaglercraftRandom par3Random, int par4, int par5, int par6, int par7) {
+ int var8 = this.getXWithOffset(par4, par6);
+ int var9 = this.getYWithOffset(par5);
+ int var10 = this.getZWithOffset(par4, par6);
+
+ if (par2StructureBoundingBox.isVecInside(var8, var9, var10)) {
+ ItemDoor.placeDoorBlock(par1World, var8, var9, var10, par7, Block.doorWood);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/StructureMineshaftPieces.java b/sp-server/src/main/java/net/minecraft/src/StructureMineshaftPieces.java
new file mode 100644
index 0000000..ea1a3cb
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/StructureMineshaftPieces.java
@@ -0,0 +1,77 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class StructureMineshaftPieces {
+ /** List of contents that can generate in Mineshafts. */
+ private static final WeightedRandomChestContent[] mineshaftChestContents = new WeightedRandomChestContent[] {
+ new WeightedRandomChestContent(Item.ingotIron.itemID, 0, 1, 5, 10),
+ new WeightedRandomChestContent(Item.ingotGold.itemID, 0, 1, 3, 5),
+ new WeightedRandomChestContent(Item.redstone.itemID, 0, 4, 9, 5),
+ new WeightedRandomChestContent(Item.dyePowder.itemID, 4, 4, 9, 5),
+ new WeightedRandomChestContent(Item.diamond.itemID, 0, 1, 2, 3),
+ new WeightedRandomChestContent(Item.coal.itemID, 0, 3, 8, 10),
+ new WeightedRandomChestContent(Item.bread.itemID, 0, 1, 3, 15),
+ new WeightedRandomChestContent(Item.pickaxeIron.itemID, 0, 1, 1, 1),
+ new WeightedRandomChestContent(Block.rail.blockID, 0, 4, 8, 1),
+ new WeightedRandomChestContent(Item.melonSeeds.itemID, 0, 2, 4, 10),
+ new WeightedRandomChestContent(Item.pumpkinSeeds.itemID, 0, 2, 4, 10) };
+
+ private static StructureComponent getRandomComponent(List par0List, EaglercraftRandom par1Random, int par2, int par3, int par4,
+ int par5, int par6) {
+ int var7 = par1Random.nextInt(100);
+ StructureBoundingBox var8;
+
+ if (var7 >= 80) {
+ var8 = ComponentMineshaftCross.findValidPlacement(par0List, par1Random, par2, par3, par4, par5);
+
+ if (var8 != null) {
+ return new ComponentMineshaftCross(par6, par1Random, var8, par5);
+ }
+ } else if (var7 >= 70) {
+ var8 = ComponentMineshaftStairs.findValidPlacement(par0List, par1Random, par2, par3, par4, par5);
+
+ if (var8 != null) {
+ return new ComponentMineshaftStairs(par6, par1Random, var8, par5);
+ }
+ } else {
+ var8 = ComponentMineshaftCorridor.findValidPlacement(par0List, par1Random, par2, par3, par4, par5);
+
+ if (var8 != null) {
+ return new ComponentMineshaftCorridor(par6, par1Random, var8, par5);
+ }
+ }
+
+ return null;
+ }
+
+ private static StructureComponent getNextMineShaftComponent(StructureComponent par0StructureComponent,
+ List par1List, EaglercraftRandom par2Random, int par3, int par4, int par5, int par6, int par7) {
+ if (par7 > 8) {
+ return null;
+ } else if (Math.abs(par3 - par0StructureComponent.getBoundingBox().minX) <= 80
+ && Math.abs(par5 - par0StructureComponent.getBoundingBox().minZ) <= 80) {
+ StructureComponent var8 = getRandomComponent(par1List, par2Random, par3, par4, par5, par6, par7 + 1);
+
+ if (var8 != null) {
+ par1List.add(var8);
+ var8.buildComponent(par0StructureComponent, par1List, par2Random);
+ }
+
+ return var8;
+ } else {
+ return null;
+ }
+ }
+
+ static StructureComponent getNextComponent(StructureComponent par0StructureComponent, List par1List,
+ EaglercraftRandom par2Random, int par3, int par4, int par5, int par6, int par7) {
+ return getNextMineShaftComponent(par0StructureComponent, par1List, par2Random, par3, par4, par5, par6, par7);
+ }
+
+ static WeightedRandomChestContent[] func_78816_a() {
+ return mineshaftChestContents;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/StructureMineshaftStart.java b/sp-server/src/main/java/net/minecraft/src/StructureMineshaftStart.java
new file mode 100644
index 0000000..422548e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/StructureMineshaftStart.java
@@ -0,0 +1,13 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class StructureMineshaftStart extends StructureStart {
+ public StructureMineshaftStart(World par1World, EaglercraftRandom par2Random, int par3, int par4) {
+ ComponentMineshaftRoom var5 = new ComponentMineshaftRoom(0, par2Random, (par3 << 4) + 2, (par4 << 4) + 2);
+ this.components.add(var5);
+ var5.buildComponent(var5, this.components, par2Random);
+ this.updateBoundingBox();
+ this.markAvailableHeight(par1World, par2Random, 10);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/StructureNetherBridgePieceWeight.java b/sp-server/src/main/java/net/minecraft/src/StructureNetherBridgePieceWeight.java
new file mode 100644
index 0000000..1f541d1
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/StructureNetherBridgePieceWeight.java
@@ -0,0 +1,29 @@
+package net.minecraft.src;
+
+class StructureNetherBridgePieceWeight {
+ /** The class of the StructureComponent to which this weight corresponds. */
+ public Class weightClass;
+ public final int field_78826_b;
+ public int field_78827_c;
+ public int field_78824_d;
+ public boolean field_78825_e;
+
+ public StructureNetherBridgePieceWeight(Class par1Class, int par2, int par3, boolean par4) {
+ this.weightClass = par1Class;
+ this.field_78826_b = par2;
+ this.field_78824_d = par3;
+ this.field_78825_e = par4;
+ }
+
+ public StructureNetherBridgePieceWeight(Class par1Class, int par2, int par3) {
+ this(par1Class, par2, par3, false);
+ }
+
+ public boolean func_78822_a(int par1) {
+ return this.field_78824_d == 0 || this.field_78827_c < this.field_78824_d;
+ }
+
+ public boolean func_78823_a() {
+ return this.field_78824_d == 0 || this.field_78827_c < this.field_78824_d;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/StructureNetherBridgePieces.java b/sp-server/src/main/java/net/minecraft/src/StructureNetherBridgePieces.java
new file mode 100644
index 0000000..a16e8db
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/StructureNetherBridgePieces.java
@@ -0,0 +1,86 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class StructureNetherBridgePieces {
+ private static final StructureNetherBridgePieceWeight[] primaryComponents = new StructureNetherBridgePieceWeight[] {
+ new StructureNetherBridgePieceWeight(ComponentNetherBridgeStraight.class, 30, 0, true),
+ new StructureNetherBridgePieceWeight(ComponentNetherBridgeCrossing3.class, 10, 4),
+ new StructureNetherBridgePieceWeight(ComponentNetherBridgeCrossing.class, 10, 4),
+ new StructureNetherBridgePieceWeight(ComponentNetherBridgeStairs.class, 10, 3),
+ new StructureNetherBridgePieceWeight(ComponentNetherBridgeThrone.class, 5, 2),
+ new StructureNetherBridgePieceWeight(ComponentNetherBridgeEntrance.class, 5, 1) };
+ private static final StructureNetherBridgePieceWeight[] secondaryComponents = new StructureNetherBridgePieceWeight[] {
+ new StructureNetherBridgePieceWeight(ComponentNetherBridgeCorridor5.class, 25, 0, true),
+ new StructureNetherBridgePieceWeight(ComponentNetherBridgeCrossing2.class, 15, 5),
+ new StructureNetherBridgePieceWeight(ComponentNetherBridgeCorridor2.class, 5, 10),
+ new StructureNetherBridgePieceWeight(ComponentNetherBridgeCorridor.class, 5, 10),
+ new StructureNetherBridgePieceWeight(ComponentNetherBridgeCorridor3.class, 10, 3, true),
+ new StructureNetherBridgePieceWeight(ComponentNetherBridgeCorridor4.class, 7, 2),
+ new StructureNetherBridgePieceWeight(ComponentNetherBridgeNetherStalkRoom.class, 5, 2) };
+
+ private static ComponentNetherBridgePiece createNextComponentRandom(
+ StructureNetherBridgePieceWeight par0StructureNetherBridgePieceWeight, List par1List, EaglercraftRandom par2Random,
+ int par3, int par4, int par5, int par6, int par7) {
+ Class var8 = par0StructureNetherBridgePieceWeight.weightClass;
+ Object var9 = null;
+
+ if (var8 == ComponentNetherBridgeStraight.class) {
+ var9 = ComponentNetherBridgeStraight.createValidComponent(par1List, par2Random, par3, par4, par5, par6,
+ par7);
+ } else if (var8 == ComponentNetherBridgeCrossing3.class) {
+ var9 = ComponentNetherBridgeCrossing3.createValidComponent(par1List, par2Random, par3, par4, par5, par6,
+ par7);
+ } else if (var8 == ComponentNetherBridgeCrossing.class) {
+ var9 = ComponentNetherBridgeCrossing.createValidComponent(par1List, par2Random, par3, par4, par5, par6,
+ par7);
+ } else if (var8 == ComponentNetherBridgeStairs.class) {
+ var9 = ComponentNetherBridgeStairs.createValidComponent(par1List, par2Random, par3, par4, par5, par6, par7);
+ } else if (var8 == ComponentNetherBridgeThrone.class) {
+ var9 = ComponentNetherBridgeThrone.createValidComponent(par1List, par2Random, par3, par4, par5, par6, par7);
+ } else if (var8 == ComponentNetherBridgeEntrance.class) {
+ var9 = ComponentNetherBridgeEntrance.createValidComponent(par1List, par2Random, par3, par4, par5, par6,
+ par7);
+ } else if (var8 == ComponentNetherBridgeCorridor5.class) {
+ var9 = ComponentNetherBridgeCorridor5.createValidComponent(par1List, par2Random, par3, par4, par5, par6,
+ par7);
+ } else if (var8 == ComponentNetherBridgeCorridor2.class) {
+ var9 = ComponentNetherBridgeCorridor2.createValidComponent(par1List, par2Random, par3, par4, par5, par6,
+ par7);
+ } else if (var8 == ComponentNetherBridgeCorridor.class) {
+ var9 = ComponentNetherBridgeCorridor.createValidComponent(par1List, par2Random, par3, par4, par5, par6,
+ par7);
+ } else if (var8 == ComponentNetherBridgeCorridor3.class) {
+ var9 = ComponentNetherBridgeCorridor3.createValidComponent(par1List, par2Random, par3, par4, par5, par6,
+ par7);
+ } else if (var8 == ComponentNetherBridgeCorridor4.class) {
+ var9 = ComponentNetherBridgeCorridor4.createValidComponent(par1List, par2Random, par3, par4, par5, par6,
+ par7);
+ } else if (var8 == ComponentNetherBridgeCrossing2.class) {
+ var9 = ComponentNetherBridgeCrossing2.createValidComponent(par1List, par2Random, par3, par4, par5, par6,
+ par7);
+ } else if (var8 == ComponentNetherBridgeNetherStalkRoom.class) {
+ var9 = ComponentNetherBridgeNetherStalkRoom.createValidComponent(par1List, par2Random, par3, par4, par5,
+ par6, par7);
+ }
+
+ return (ComponentNetherBridgePiece) var9;
+ }
+
+ static ComponentNetherBridgePiece createNextComponent(
+ StructureNetherBridgePieceWeight par0StructureNetherBridgePieceWeight, List par1List, EaglercraftRandom par2Random,
+ int par3, int par4, int par5, int par6, int par7) {
+ return createNextComponentRandom(par0StructureNetherBridgePieceWeight, par1List, par2Random, par3, par4, par5,
+ par6, par7);
+ }
+
+ static StructureNetherBridgePieceWeight[] getPrimaryComponents() {
+ return primaryComponents;
+ }
+
+ static StructureNetherBridgePieceWeight[] getSecondaryComponents() {
+ return secondaryComponents;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/StructureNetherBridgeStart.java b/sp-server/src/main/java/net/minecraft/src/StructureNetherBridgeStart.java
new file mode 100644
index 0000000..e1f034a
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/StructureNetherBridgeStart.java
@@ -0,0 +1,24 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+class StructureNetherBridgeStart extends StructureStart {
+ public StructureNetherBridgeStart(World par1World, EaglercraftRandom par2Random, int par3, int par4) {
+ ComponentNetherBridgeStartPiece var5 = new ComponentNetherBridgeStartPiece(par2Random, (par3 << 4) + 2,
+ (par4 << 4) + 2);
+ this.components.add(var5);
+ var5.buildComponent(var5, this.components, par2Random);
+ ArrayList var6 = var5.field_74967_d;
+
+ while (!var6.isEmpty()) {
+ int var7 = par2Random.nextInt(var6.size());
+ StructureComponent var8 = (StructureComponent) var6.remove(var7);
+ var8.buildComponent(var5, this.components, par2Random);
+ }
+
+ this.updateBoundingBox();
+ this.setRandomHeight(par1World, par2Random, 48, 70);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/StructurePieceBlockSelector.java b/sp-server/src/main/java/net/minecraft/src/StructurePieceBlockSelector.java
new file mode 100644
index 0000000..536083b
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/StructurePieceBlockSelector.java
@@ -0,0 +1,21 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public abstract class StructurePieceBlockSelector {
+ protected int selectedBlockId;
+ protected int selectedBlockMetaData;
+
+ /**
+ * picks Block Ids and Metadata (Silverfish)
+ */
+ public abstract void selectBlocks(EaglercraftRandom var1, int var2, int var3, int var4, boolean var5);
+
+ public int getSelectedBlockId() {
+ return this.selectedBlockId;
+ }
+
+ public int getSelectedBlockMetaData() {
+ return this.selectedBlockMetaData;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/StructureScatteredFeatureStart.java b/sp-server/src/main/java/net/minecraft/src/StructureScatteredFeatureStart.java
new file mode 100644
index 0000000..ed21c3b
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/StructureScatteredFeatureStart.java
@@ -0,0 +1,27 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class StructureScatteredFeatureStart extends StructureStart {
+ public StructureScatteredFeatureStart(World par1World, EaglercraftRandom par2Random, int par3, int par4) {
+ BiomeGenBase var5 = par1World.getBiomeGenForCoords(par3 * 16 + 8, par4 * 16 + 8);
+
+ if (var5 != BiomeGenBase.jungle && var5 != BiomeGenBase.jungleHills) {
+ if (var5 == BiomeGenBase.swampland) {
+ ComponentScatteredFeatureSwampHut var7 = new ComponentScatteredFeatureSwampHut(par2Random, par3 * 16,
+ par4 * 16);
+ this.components.add(var7);
+ } else {
+ ComponentScatteredFeatureDesertPyramid var8 = new ComponentScatteredFeatureDesertPyramid(par2Random,
+ par3 * 16, par4 * 16);
+ this.components.add(var8);
+ }
+ } else {
+ ComponentScatteredFeatureJunglePyramid var6 = new ComponentScatteredFeatureJunglePyramid(par2Random,
+ par3 * 16, par4 * 16);
+ this.components.add(var6);
+ }
+
+ this.updateBoundingBox();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/StructureScatteredFeatureStones.java b/sp-server/src/main/java/net/minecraft/src/StructureScatteredFeatureStones.java
new file mode 100644
index 0000000..4caa6d8
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/StructureScatteredFeatureStones.java
@@ -0,0 +1,23 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+class StructureScatteredFeatureStones extends StructurePieceBlockSelector {
+ private StructureScatteredFeatureStones() {
+ }
+
+ /**
+ * picks Block Ids and Metadata (Silverfish)
+ */
+ public void selectBlocks(EaglercraftRandom par1Random, int par2, int par3, int par4, boolean par5) {
+ if (par1Random.nextFloat() < 0.4F) {
+ this.selectedBlockId = Block.cobblestone.blockID;
+ } else {
+ this.selectedBlockId = Block.cobblestoneMossy.blockID;
+ }
+ }
+
+ StructureScatteredFeatureStones(ComponentScatteredFeaturePieces2 par1ComponentScatteredFeaturePieces2) {
+ this();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/StructureStart.java b/sp-server/src/main/java/net/minecraft/src/StructureStart.java
new file mode 100644
index 0000000..b6ea99d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/StructureStart.java
@@ -0,0 +1,102 @@
+package net.minecraft.src;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public abstract class StructureStart {
+ /** List of all StructureComponents that are part of this structure */
+ protected LinkedList components = new LinkedList();
+ protected StructureBoundingBox boundingBox;
+
+ public StructureBoundingBox getBoundingBox() {
+ return this.boundingBox;
+ }
+
+ public LinkedList getComponents() {
+ return this.components;
+ }
+
+ /**
+ * Keeps iterating Structure Pieces and spawning them until the checks tell it
+ * to stop
+ */
+ public void generateStructure(World par1World, EaglercraftRandom par2Random, StructureBoundingBox par3StructureBoundingBox) {
+ Iterator var4 = this.components.iterator();
+
+ while (var4.hasNext()) {
+ StructureComponent var5 = (StructureComponent) var4.next();
+
+ if (var5.getBoundingBox().intersectsWith(par3StructureBoundingBox)
+ && !var5.addComponentParts(par1World, par2Random, par3StructureBoundingBox)) {
+ var4.remove();
+ }
+ }
+ }
+
+ /**
+ * Calculates total bounding box based on components' bounding boxes and saves
+ * it to boundingBox
+ */
+ protected void updateBoundingBox() {
+ this.boundingBox = StructureBoundingBox.getNewBoundingBox();
+ Iterator var1 = this.components.iterator();
+
+ while (var1.hasNext()) {
+ StructureComponent var2 = (StructureComponent) var1.next();
+ this.boundingBox.expandTo(var2.getBoundingBox());
+ }
+ }
+
+ /**
+ * offsets the structure Bounding Boxes up to a certain height, typically 63 -
+ * 10
+ */
+ protected void markAvailableHeight(World par1World, EaglercraftRandom par2Random, int par3) {
+ int var4 = 63 - par3;
+ int var5 = this.boundingBox.getYSize() + 1;
+
+ if (var5 < var4) {
+ var5 += par2Random.nextInt(var4 - var5);
+ }
+
+ int var6 = var5 - this.boundingBox.maxY;
+ this.boundingBox.offset(0, var6, 0);
+ Iterator var7 = this.components.iterator();
+
+ while (var7.hasNext()) {
+ StructureComponent var8 = (StructureComponent) var7.next();
+ var8.getBoundingBox().offset(0, var6, 0);
+ }
+ }
+
+ protected void setRandomHeight(World par1World, EaglercraftRandom par2Random, int par3, int par4) {
+ int var5 = par4 - par3 + 1 - this.boundingBox.getYSize();
+ boolean var6 = true;
+ int var10;
+
+ if (var5 > 1) {
+ var10 = par3 + par2Random.nextInt(var5);
+ } else {
+ var10 = par3;
+ }
+
+ int var7 = var10 - this.boundingBox.minY;
+ this.boundingBox.offset(0, var7, 0);
+ Iterator var8 = this.components.iterator();
+
+ while (var8.hasNext()) {
+ StructureComponent var9 = (StructureComponent) var8.next();
+ var9.getBoundingBox().offset(0, var7, 0);
+ }
+ }
+
+ /**
+ * currently only defined for Villages, returns true if Village has more than 2
+ * non-road components
+ */
+ public boolean isSizeableStructure() {
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/StructureStrongholdPieceWeight.java b/sp-server/src/main/java/net/minecraft/src/StructureStrongholdPieceWeight.java
new file mode 100644
index 0000000..409fdd7
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/StructureStrongholdPieceWeight.java
@@ -0,0 +1,30 @@
+package net.minecraft.src;
+
+class StructureStrongholdPieceWeight {
+ public Class pieceClass;
+
+ /**
+ * This basically keeps track of the 'epicness' of a structure. Epic structure
+ * components have a higher 'weight', and Structures may only grow up to a
+ * certain 'weight' before generation is stopped
+ */
+ public final int pieceWeight;
+ public int instancesSpawned;
+
+ /** How many Structure Pieces of this type may spawn in a structure */
+ public int instancesLimit;
+
+ public StructureStrongholdPieceWeight(Class par1Class, int par2, int par3) {
+ this.pieceClass = par1Class;
+ this.pieceWeight = par2;
+ this.instancesLimit = par3;
+ }
+
+ public boolean canSpawnMoreStructuresOfType(int par1) {
+ return this.instancesLimit == 0 || this.instancesSpawned < this.instancesLimit;
+ }
+
+ public boolean canSpawnMoreStructures() {
+ return this.instancesLimit == 0 || this.instancesSpawned < this.instancesLimit;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/StructureStrongholdPieceWeight2.java b/sp-server/src/main/java/net/minecraft/src/StructureStrongholdPieceWeight2.java
new file mode 100644
index 0000000..f37191f
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/StructureStrongholdPieceWeight2.java
@@ -0,0 +1,11 @@
+package net.minecraft.src;
+
+final class StructureStrongholdPieceWeight2 extends StructureStrongholdPieceWeight {
+ StructureStrongholdPieceWeight2(Class par1Class, int par2, int par3) {
+ super(par1Class, par2, par3);
+ }
+
+ public boolean canSpawnMoreStructuresOfType(int par1) {
+ return super.canSpawnMoreStructuresOfType(par1) && par1 > 4;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/StructureStrongholdPieceWeight3.java b/sp-server/src/main/java/net/minecraft/src/StructureStrongholdPieceWeight3.java
new file mode 100644
index 0000000..f245fca
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/StructureStrongholdPieceWeight3.java
@@ -0,0 +1,11 @@
+package net.minecraft.src;
+
+final class StructureStrongholdPieceWeight3 extends StructureStrongholdPieceWeight {
+ StructureStrongholdPieceWeight3(Class par1Class, int par2, int par3) {
+ super(par1Class, par2, par3);
+ }
+
+ public boolean canSpawnMoreStructuresOfType(int par1) {
+ return super.canSpawnMoreStructuresOfType(par1) && par1 > 5;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/StructureStrongholdPieces.java b/sp-server/src/main/java/net/minecraft/src/StructureStrongholdPieces.java
new file mode 100644
index 0000000..27dfc46
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/StructureStrongholdPieces.java
@@ -0,0 +1,193 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class StructureStrongholdPieces {
+ private static final StructureStrongholdPieceWeight[] pieceWeightArray = new StructureStrongholdPieceWeight[] {
+ new StructureStrongholdPieceWeight(ComponentStrongholdStraight.class, 40, 0),
+ new StructureStrongholdPieceWeight(ComponentStrongholdPrison.class, 5, 5),
+ new StructureStrongholdPieceWeight(ComponentStrongholdLeftTurn.class, 20, 0),
+ new StructureStrongholdPieceWeight(ComponentStrongholdRightTurn.class, 20, 0),
+ new StructureStrongholdPieceWeight(ComponentStrongholdRoomCrossing.class, 10, 6),
+ new StructureStrongholdPieceWeight(ComponentStrongholdStairsStraight.class, 5, 5),
+ new StructureStrongholdPieceWeight(ComponentStrongholdStairs.class, 5, 5),
+ new StructureStrongholdPieceWeight(ComponentStrongholdCrossing.class, 5, 4),
+ new StructureStrongholdPieceWeight(ComponentStrongholdChestCorridor.class, 5, 4),
+ new StructureStrongholdPieceWeight2(ComponentStrongholdLibrary.class, 10, 2),
+ new StructureStrongholdPieceWeight3(ComponentStrongholdPortalRoom.class, 20, 1) };
+ private static List structurePieceList;
+ private static Class strongComponentType;
+ static int totalWeight = 0;
+ private static final StructureStrongholdStones strongholdStones = new StructureStrongholdStones(
+ (StructureStrongholdPieceWeight2) null);
+
+ /**
+ * sets up Arrays with the Structure pieces and their weights
+ */
+ public static void prepareStructurePieces() {
+ structurePieceList = new ArrayList();
+ StructureStrongholdPieceWeight[] var0 = pieceWeightArray;
+ int var1 = var0.length;
+
+ for (int var2 = 0; var2 < var1; ++var2) {
+ StructureStrongholdPieceWeight var3 = var0[var2];
+ var3.instancesSpawned = 0;
+ structurePieceList.add(var3);
+ }
+
+ strongComponentType = null;
+ }
+
+ private static boolean canAddStructurePieces() {
+ boolean var0 = false;
+ totalWeight = 0;
+ StructureStrongholdPieceWeight var2;
+
+ for (Iterator var1 = structurePieceList.iterator(); var1.hasNext(); totalWeight += var2.pieceWeight) {
+ var2 = (StructureStrongholdPieceWeight) var1.next();
+
+ if (var2.instancesLimit > 0 && var2.instancesSpawned < var2.instancesLimit) {
+ var0 = true;
+ }
+ }
+
+ return var0;
+ }
+
+ /**
+ * translates the PieceWeight class to the Component class
+ */
+ private static ComponentStronghold getStrongholdComponentFromWeightedPiece(Class par0Class, List par1List,
+ EaglercraftRandom par2Random, int par3, int par4, int par5, int par6, int par7) {
+ Object var8 = null;
+
+ if (par0Class == ComponentStrongholdStraight.class) {
+ var8 = ComponentStrongholdStraight.findValidPlacement(par1List, par2Random, par3, par4, par5, par6, par7);
+ } else if (par0Class == ComponentStrongholdPrison.class) {
+ var8 = ComponentStrongholdPrison.findValidPlacement(par1List, par2Random, par3, par4, par5, par6, par7);
+ } else if (par0Class == ComponentStrongholdLeftTurn.class) {
+ var8 = ComponentStrongholdLeftTurn.findValidPlacement(par1List, par2Random, par3, par4, par5, par6, par7);
+ } else if (par0Class == ComponentStrongholdRightTurn.class) {
+ var8 = ComponentStrongholdRightTurn.findValidPlacement(par1List, par2Random, par3, par4, par5, par6, par7);
+ } else if (par0Class == ComponentStrongholdRoomCrossing.class) {
+ var8 = ComponentStrongholdRoomCrossing.findValidPlacement(par1List, par2Random, par3, par4, par5, par6,
+ par7);
+ } else if (par0Class == ComponentStrongholdStairsStraight.class) {
+ var8 = ComponentStrongholdStairsStraight.findValidPlacement(par1List, par2Random, par3, par4, par5, par6,
+ par7);
+ } else if (par0Class == ComponentStrongholdStairs.class) {
+ var8 = ComponentStrongholdStairs.getStrongholdStairsComponent(par1List, par2Random, par3, par4, par5, par6,
+ par7);
+ } else if (par0Class == ComponentStrongholdCrossing.class) {
+ var8 = ComponentStrongholdCrossing.findValidPlacement(par1List, par2Random, par3, par4, par5, par6, par7);
+ } else if (par0Class == ComponentStrongholdChestCorridor.class) {
+ var8 = ComponentStrongholdChestCorridor.findValidPlacement(par1List, par2Random, par3, par4, par5, par6,
+ par7);
+ } else if (par0Class == ComponentStrongholdLibrary.class) {
+ var8 = ComponentStrongholdLibrary.findValidPlacement(par1List, par2Random, par3, par4, par5, par6, par7);
+ } else if (par0Class == ComponentStrongholdPortalRoom.class) {
+ var8 = ComponentStrongholdPortalRoom.findValidPlacement(par1List, par2Random, par3, par4, par5, par6, par7);
+ }
+
+ return (ComponentStronghold) var8;
+ }
+
+ private static ComponentStronghold getNextComponent(ComponentStrongholdStairs2 par0ComponentStrongholdStairs2,
+ List par1List, EaglercraftRandom par2Random, int par3, int par4, int par5, int par6, int par7) {
+ if (!canAddStructurePieces()) {
+ return null;
+ } else {
+ if (strongComponentType != null) {
+ ComponentStronghold var8 = getStrongholdComponentFromWeightedPiece(strongComponentType, par1List,
+ par2Random, par3, par4, par5, par6, par7);
+ strongComponentType = null;
+
+ if (var8 != null) {
+ return var8;
+ }
+ }
+
+ int var13 = 0;
+
+ while (var13 < 5) {
+ ++var13;
+ int var9 = par2Random.nextInt(totalWeight);
+ Iterator var10 = structurePieceList.iterator();
+
+ while (var10.hasNext()) {
+ StructureStrongholdPieceWeight var11 = (StructureStrongholdPieceWeight) var10.next();
+ var9 -= var11.pieceWeight;
+
+ if (var9 < 0) {
+ if (!var11.canSpawnMoreStructuresOfType(par7)
+ || var11 == par0ComponentStrongholdStairs2.strongholdPieceWeight) {
+ break;
+ }
+
+ ComponentStronghold var12 = getStrongholdComponentFromWeightedPiece(var11.pieceClass, par1List,
+ par2Random, par3, par4, par5, par6, par7);
+
+ if (var12 != null) {
+ ++var11.instancesSpawned;
+ par0ComponentStrongholdStairs2.strongholdPieceWeight = var11;
+
+ if (!var11.canSpawnMoreStructures()) {
+ structurePieceList.remove(var11);
+ }
+
+ return var12;
+ }
+ }
+ }
+ }
+
+ StructureBoundingBox var14 = ComponentStrongholdCorridor.func_74992_a(par1List, par2Random, par3, par4,
+ par5, par6);
+
+ if (var14 != null && var14.minY > 1) {
+ return new ComponentStrongholdCorridor(par7, par2Random, var14, par6);
+ } else {
+ return null;
+ }
+ }
+ }
+
+ private static StructureComponent getNextValidComponent(ComponentStrongholdStairs2 par0ComponentStrongholdStairs2,
+ List par1List, EaglercraftRandom par2Random, int par3, int par4, int par5, int par6, int par7) {
+ if (par7 > 50) {
+ return null;
+ } else if (Math.abs(par3 - par0ComponentStrongholdStairs2.getBoundingBox().minX) <= 112
+ && Math.abs(par5 - par0ComponentStrongholdStairs2.getBoundingBox().minZ) <= 112) {
+ ComponentStronghold var8 = getNextComponent(par0ComponentStrongholdStairs2, par1List, par2Random, par3,
+ par4, par5, par6, par7 + 1);
+
+ if (var8 != null) {
+ par1List.add(var8);
+ par0ComponentStrongholdStairs2.field_75026_c.add(var8);
+ }
+
+ return var8;
+ } else {
+ return null;
+ }
+ }
+
+ static StructureComponent getNextValidComponentAccess(ComponentStrongholdStairs2 par0ComponentStrongholdStairs2,
+ List par1List, EaglercraftRandom par2Random, int par3, int par4, int par5, int par6, int par7) {
+ return getNextValidComponent(par0ComponentStrongholdStairs2, par1List, par2Random, par3, par4, par5, par6,
+ par7);
+ }
+
+ static Class setComponentType(Class par0Class) {
+ strongComponentType = par0Class;
+ return par0Class;
+ }
+
+ static StructureStrongholdStones getStrongholdStones() {
+ return strongholdStones;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/StructureStrongholdStart.java b/sp-server/src/main/java/net/minecraft/src/StructureStrongholdStart.java
new file mode 100644
index 0000000..ec78d32
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/StructureStrongholdStart.java
@@ -0,0 +1,25 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+class StructureStrongholdStart extends StructureStart {
+ public StructureStrongholdStart(World par1World, EaglercraftRandom par2Random, int par3, int par4) {
+ StructureStrongholdPieces.prepareStructurePieces();
+ ComponentStrongholdStairs2 var5 = new ComponentStrongholdStairs2(0, par2Random, (par3 << 4) + 2,
+ (par4 << 4) + 2);
+ this.components.add(var5);
+ var5.buildComponent(var5, this.components, par2Random);
+ ArrayList var6 = var5.field_75026_c;
+
+ while (!var6.isEmpty()) {
+ int var7 = par2Random.nextInt(var6.size());
+ StructureComponent var8 = (StructureComponent) var6.remove(var7);
+ var8.buildComponent(var5, this.components, par2Random);
+ }
+
+ this.updateBoundingBox();
+ this.markAvailableHeight(par1World, par2Random, 10);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/StructureStrongholdStones.java b/sp-server/src/main/java/net/minecraft/src/StructureStrongholdStones.java
new file mode 100644
index 0000000..abc0881
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/StructureStrongholdStones.java
@@ -0,0 +1,36 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+class StructureStrongholdStones extends StructurePieceBlockSelector {
+ private StructureStrongholdStones() {
+ }
+
+ /**
+ * picks Block Ids and Metadata (Silverfish)
+ */
+ public void selectBlocks(EaglercraftRandom par1Random, int par2, int par3, int par4, boolean par5) {
+ if (par5) {
+ this.selectedBlockId = Block.stoneBrick.blockID;
+ float var6 = par1Random.nextFloat();
+
+ if (var6 < 0.2F) {
+ this.selectedBlockMetaData = 2;
+ } else if (var6 < 0.5F) {
+ this.selectedBlockMetaData = 1;
+ } else if (var6 < 0.55F) {
+ this.selectedBlockId = Block.silverfish.blockID;
+ this.selectedBlockMetaData = 2;
+ } else {
+ this.selectedBlockMetaData = 0;
+ }
+ } else {
+ this.selectedBlockId = 0;
+ this.selectedBlockMetaData = 0;
+ }
+ }
+
+ StructureStrongholdStones(StructureStrongholdPieceWeight2 par1StructureStrongholdPieceWeight2) {
+ this();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/StructureVillagePieceWeight.java b/sp-server/src/main/java/net/minecraft/src/StructureVillagePieceWeight.java
new file mode 100644
index 0000000..589bdda
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/StructureVillagePieceWeight.java
@@ -0,0 +1,23 @@
+package net.minecraft.src;
+
+public class StructureVillagePieceWeight {
+ /** The Class object for the represantation of this village piece. */
+ public Class villagePieceClass;
+ public final int villagePieceWeight;
+ public int villagePiecesSpawned;
+ public int villagePiecesLimit;
+
+ public StructureVillagePieceWeight(Class par1Class, int par2, int par3) {
+ this.villagePieceClass = par1Class;
+ this.villagePieceWeight = par2;
+ this.villagePiecesLimit = par3;
+ }
+
+ public boolean canSpawnMoreVillagePiecesOfType(int par1) {
+ return this.villagePiecesLimit == 0 || this.villagePiecesSpawned < this.villagePiecesLimit;
+ }
+
+ public boolean canSpawnMoreVillagePieces() {
+ return this.villagePiecesLimit == 0 || this.villagePiecesSpawned < this.villagePiecesLimit;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/StructureVillagePieces.java b/sp-server/src/main/java/net/minecraft/src/StructureVillagePieces.java
new file mode 100644
index 0000000..0b97aa4
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/StructureVillagePieces.java
@@ -0,0 +1,235 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class StructureVillagePieces {
+ public static ArrayList getStructureVillageWeightedPieceList(EaglercraftRandom par0Random, int par1) {
+ ArrayList var2 = new ArrayList();
+ var2.add(new StructureVillagePieceWeight(ComponentVillageHouse4_Garden.class, 4,
+ MathHelper.getRandomIntegerInRange(par0Random, 2 + par1, 4 + par1 * 2)));
+ var2.add(new StructureVillagePieceWeight(ComponentVillageChurch.class, 20,
+ MathHelper.getRandomIntegerInRange(par0Random, 0 + par1, 1 + par1)));
+ var2.add(new StructureVillagePieceWeight(ComponentVillageHouse1.class, 20,
+ MathHelper.getRandomIntegerInRange(par0Random, 0 + par1, 2 + par1)));
+ var2.add(new StructureVillagePieceWeight(ComponentVillageWoodHut.class, 3,
+ MathHelper.getRandomIntegerInRange(par0Random, 2 + par1, 5 + par1 * 3)));
+ var2.add(new StructureVillagePieceWeight(ComponentVillageHall.class, 15,
+ MathHelper.getRandomIntegerInRange(par0Random, 0 + par1, 2 + par1)));
+ var2.add(new StructureVillagePieceWeight(ComponentVillageField.class, 3,
+ MathHelper.getRandomIntegerInRange(par0Random, 1 + par1, 4 + par1)));
+ var2.add(new StructureVillagePieceWeight(ComponentVillageField2.class, 3,
+ MathHelper.getRandomIntegerInRange(par0Random, 2 + par1, 4 + par1 * 2)));
+ var2.add(new StructureVillagePieceWeight(ComponentVillageHouse2.class, 15,
+ MathHelper.getRandomIntegerInRange(par0Random, 0, 1 + par1)));
+ var2.add(new StructureVillagePieceWeight(ComponentVillageHouse3.class, 8,
+ MathHelper.getRandomIntegerInRange(par0Random, 0 + par1, 3 + par1 * 2)));
+ Iterator var3 = var2.iterator();
+
+ while (var3.hasNext()) {
+ if (((StructureVillagePieceWeight) var3.next()).villagePiecesLimit == 0) {
+ var3.remove();
+ }
+ }
+
+ return var2;
+ }
+
+ private static int func_75079_a(List par0List) {
+ boolean var1 = false;
+ int var2 = 0;
+ StructureVillagePieceWeight var4;
+
+ for (Iterator var3 = par0List.iterator(); var3.hasNext(); var2 += var4.villagePieceWeight) {
+ var4 = (StructureVillagePieceWeight) var3.next();
+
+ if (var4.villagePiecesLimit > 0 && var4.villagePiecesSpawned < var4.villagePiecesLimit) {
+ var1 = true;
+ }
+ }
+
+ return var1 ? var2 : -1;
+ }
+
+ private static ComponentVillage func_75083_a(ComponentVillageStartPiece par0ComponentVillageStartPiece,
+ StructureVillagePieceWeight par1StructureVillagePieceWeight, List par2List, EaglercraftRandom par3Random, int par4,
+ int par5, int par6, int par7, int par8) {
+ Class var9 = par1StructureVillagePieceWeight.villagePieceClass;
+ Object var10 = null;
+
+ if (var9 == ComponentVillageHouse4_Garden.class) {
+ var10 = ComponentVillageHouse4_Garden.func_74912_a(par0ComponentVillageStartPiece, par2List, par3Random,
+ par4, par5, par6, par7, par8);
+ } else if (var9 == ComponentVillageChurch.class) {
+ var10 = ComponentVillageChurch.func_74919_a(par0ComponentVillageStartPiece, par2List, par3Random, par4,
+ par5, par6, par7, par8);
+ } else if (var9 == ComponentVillageHouse1.class) {
+ var10 = ComponentVillageHouse1.func_74898_a(par0ComponentVillageStartPiece, par2List, par3Random, par4,
+ par5, par6, par7, par8);
+ } else if (var9 == ComponentVillageWoodHut.class) {
+ var10 = ComponentVillageWoodHut.func_74908_a(par0ComponentVillageStartPiece, par2List, par3Random, par4,
+ par5, par6, par7, par8);
+ } else if (var9 == ComponentVillageHall.class) {
+ var10 = ComponentVillageHall.func_74906_a(par0ComponentVillageStartPiece, par2List, par3Random, par4, par5,
+ par6, par7, par8);
+ } else if (var9 == ComponentVillageField.class) {
+ var10 = ComponentVillageField.func_74900_a(par0ComponentVillageStartPiece, par2List, par3Random, par4, par5,
+ par6, par7, par8);
+ } else if (var9 == ComponentVillageField2.class) {
+ var10 = ComponentVillageField2.func_74902_a(par0ComponentVillageStartPiece, par2List, par3Random, par4,
+ par5, par6, par7, par8);
+ } else if (var9 == ComponentVillageHouse2.class) {
+ var10 = ComponentVillageHouse2.func_74915_a(par0ComponentVillageStartPiece, par2List, par3Random, par4,
+ par5, par6, par7, par8);
+ } else if (var9 == ComponentVillageHouse3.class) {
+ var10 = ComponentVillageHouse3.func_74921_a(par0ComponentVillageStartPiece, par2List, par3Random, par4,
+ par5, par6, par7, par8);
+ }
+
+ return (ComponentVillage) var10;
+ }
+
+ /**
+ * attempts to find a next Village Component to be spawned
+ */
+ private static ComponentVillage getNextVillageComponent(ComponentVillageStartPiece par0ComponentVillageStartPiece,
+ List par1List, EaglercraftRandom par2Random, int par3, int par4, int par5, int par6, int par7) {
+ int var8 = func_75079_a(par0ComponentVillageStartPiece.structureVillageWeightedPieceList);
+
+ if (var8 <= 0) {
+ return null;
+ } else {
+ int var9 = 0;
+
+ while (var9 < 5) {
+ ++var9;
+ int var10 = par2Random.nextInt(var8);
+ Iterator var11 = par0ComponentVillageStartPiece.structureVillageWeightedPieceList.iterator();
+
+ while (var11.hasNext()) {
+ StructureVillagePieceWeight var12 = (StructureVillagePieceWeight) var11.next();
+ var10 -= var12.villagePieceWeight;
+
+ if (var10 < 0) {
+ if (!var12.canSpawnMoreVillagePiecesOfType(par7)
+ || var12 == par0ComponentVillageStartPiece.structVillagePieceWeight
+ && par0ComponentVillageStartPiece.structureVillageWeightedPieceList
+ .size() > 1) {
+ break;
+ }
+
+ ComponentVillage var13 = func_75083_a(par0ComponentVillageStartPiece, var12, par1List,
+ par2Random, par3, par4, par5, par6, par7);
+
+ if (var13 != null) {
+ ++var12.villagePiecesSpawned;
+ par0ComponentVillageStartPiece.structVillagePieceWeight = var12;
+
+ if (!var12.canSpawnMoreVillagePieces()) {
+ par0ComponentVillageStartPiece.structureVillageWeightedPieceList.remove(var12);
+ }
+
+ return var13;
+ }
+ }
+ }
+ }
+
+ StructureBoundingBox var14 = ComponentVillageTorch.func_74904_a(par0ComponentVillageStartPiece, par1List,
+ par2Random, par3, par4, par5, par6);
+
+ if (var14 != null) {
+ return new ComponentVillageTorch(par0ComponentVillageStartPiece, par7, par2Random, var14, par6);
+ } else {
+ return null;
+ }
+ }
+ }
+
+ /**
+ * attempts to find a next Structure Component to be spawned, private Village
+ * function
+ */
+ private static StructureComponent getNextVillageStructureComponent(
+ ComponentVillageStartPiece par0ComponentVillageStartPiece, List par1List, EaglercraftRandom par2Random, int par3,
+ int par4, int par5, int par6, int par7) {
+ if (par7 > 50) {
+ return null;
+ } else if (Math.abs(par3 - par0ComponentVillageStartPiece.getBoundingBox().minX) <= 112
+ && Math.abs(par5 - par0ComponentVillageStartPiece.getBoundingBox().minZ) <= 112) {
+ ComponentVillage var8 = getNextVillageComponent(par0ComponentVillageStartPiece, par1List, par2Random, par3,
+ par4, par5, par6, par7 + 1);
+
+ if (var8 != null) {
+ int var9 = (var8.boundingBox.minX + var8.boundingBox.maxX) / 2;
+ int var10 = (var8.boundingBox.minZ + var8.boundingBox.maxZ) / 2;
+ int var11 = var8.boundingBox.maxX - var8.boundingBox.minX;
+ int var12 = var8.boundingBox.maxZ - var8.boundingBox.minZ;
+ int var13 = var11 > var12 ? var11 : var12;
+
+ if (par0ComponentVillageStartPiece.getWorldChunkManager().areBiomesViable(var9, var10, var13 / 2 + 4,
+ MapGenVillage.villageSpawnBiomes)) {
+ par1List.add(var8);
+ par0ComponentVillageStartPiece.field_74932_i.add(var8);
+ return var8;
+ }
+ }
+
+ return null;
+ } else {
+ return null;
+ }
+ }
+
+ private static StructureComponent getNextComponentVillagePath(
+ ComponentVillageStartPiece par0ComponentVillageStartPiece, List par1List, EaglercraftRandom par2Random, int par3,
+ int par4, int par5, int par6, int par7) {
+ if (par7 > 3 + par0ComponentVillageStartPiece.terrainType) {
+ return null;
+ } else if (Math.abs(par3 - par0ComponentVillageStartPiece.getBoundingBox().minX) <= 112
+ && Math.abs(par5 - par0ComponentVillageStartPiece.getBoundingBox().minZ) <= 112) {
+ StructureBoundingBox var8 = ComponentVillagePathGen.func_74933_a(par0ComponentVillageStartPiece, par1List,
+ par2Random, par3, par4, par5, par6);
+
+ if (var8 != null && var8.minY > 10) {
+ ComponentVillagePathGen var9 = new ComponentVillagePathGen(par0ComponentVillageStartPiece, par7,
+ par2Random, var8, par6);
+ int var10 = (var9.boundingBox.minX + var9.boundingBox.maxX) / 2;
+ int var11 = (var9.boundingBox.minZ + var9.boundingBox.maxZ) / 2;
+ int var12 = var9.boundingBox.maxX - var9.boundingBox.minX;
+ int var13 = var9.boundingBox.maxZ - var9.boundingBox.minZ;
+ int var14 = var12 > var13 ? var12 : var13;
+
+ if (par0ComponentVillageStartPiece.getWorldChunkManager().areBiomesViable(var10, var11, var14 / 2 + 4,
+ MapGenVillage.villageSpawnBiomes)) {
+ par1List.add(var9);
+ par0ComponentVillageStartPiece.field_74930_j.add(var9);
+ return var9;
+ }
+ }
+
+ return null;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * attempts to find a next Structure Component to be spawned
+ */
+ static StructureComponent getNextStructureComponent(ComponentVillageStartPiece par0ComponentVillageStartPiece,
+ List par1List, EaglercraftRandom par2Random, int par3, int par4, int par5, int par6, int par7) {
+ return getNextVillageStructureComponent(par0ComponentVillageStartPiece, par1List, par2Random, par3, par4, par5,
+ par6, par7);
+ }
+
+ static StructureComponent getNextStructureComponentVillagePath(
+ ComponentVillageStartPiece par0ComponentVillageStartPiece, List par1List, EaglercraftRandom par2Random, int par3,
+ int par4, int par5, int par6, int par7) {
+ return getNextComponentVillagePath(par0ComponentVillageStartPiece, par1List, par2Random, par3, par4, par5, par6,
+ par7);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/StructureVillageStart.java b/sp-server/src/main/java/net/minecraft/src/StructureVillageStart.java
new file mode 100644
index 0000000..035ba2a
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/StructureVillageStart.java
@@ -0,0 +1,58 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+class StructureVillageStart extends StructureStart {
+ /** well ... thats what it does */
+ private boolean hasMoreThanTwoComponents = false;
+
+ public StructureVillageStart(World par1World, EaglercraftRandom par2Random, int par3, int par4, int par5) {
+ ArrayList var6 = StructureVillagePieces.getStructureVillageWeightedPieceList(par2Random, par5);
+ ComponentVillageStartPiece var7 = new ComponentVillageStartPiece(par1World.getWorldChunkManager(), 0,
+ par2Random, (par3 << 4) + 2, (par4 << 4) + 2, var6, par5);
+ this.components.add(var7);
+ var7.buildComponent(var7, this.components, par2Random);
+ ArrayList var8 = var7.field_74930_j;
+ ArrayList var9 = var7.field_74932_i;
+ int var10;
+
+ while (!var8.isEmpty() || !var9.isEmpty()) {
+ StructureComponent var11;
+
+ if (var8.isEmpty()) {
+ var10 = par2Random.nextInt(var9.size());
+ var11 = (StructureComponent) var9.remove(var10);
+ var11.buildComponent(var7, this.components, par2Random);
+ } else {
+ var10 = par2Random.nextInt(var8.size());
+ var11 = (StructureComponent) var8.remove(var10);
+ var11.buildComponent(var7, this.components, par2Random);
+ }
+ }
+
+ this.updateBoundingBox();
+ var10 = 0;
+ Iterator var13 = this.components.iterator();
+
+ while (var13.hasNext()) {
+ StructureComponent var12 = (StructureComponent) var13.next();
+
+ if (!(var12 instanceof ComponentVillageRoadPiece)) {
+ ++var10;
+ }
+ }
+
+ this.hasMoreThanTwoComponents = var10 > 2;
+ }
+
+ /**
+ * currently only defined for Villages, returns true if Village has more than 2
+ * non-road components
+ */
+ public boolean isSizeableStructure() {
+ return this.hasMoreThanTwoComponents;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/SyntaxErrorException.java b/sp-server/src/main/java/net/minecraft/src/SyntaxErrorException.java
new file mode 100644
index 0000000..49f4734
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/SyntaxErrorException.java
@@ -0,0 +1,11 @@
+package net.minecraft.src;
+
+public class SyntaxErrorException extends CommandException {
+ public SyntaxErrorException() {
+ this("commands.generic.snytax", new Object[0]);
+ }
+
+ public SyntaxErrorException(String par1Str, Object... par2ArrayOfObj) {
+ super(par1Str, par2ArrayOfObj);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Teleporter.java b/sp-server/src/main/java/net/minecraft/src/Teleporter.java
new file mode 100644
index 0000000..fa3aee4
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Teleporter.java
@@ -0,0 +1,442 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class Teleporter {
+ private final WorldServer worldServerInstance;
+
+ /** A private Random() function in Teleporter */
+ private final EaglercraftRandom random;
+
+ /** Stores successful portal placement locations for rapid lookup. */
+ private final LongHashMap destinationCoordinateCache = new LongHashMap();
+
+ /**
+ * A list of valid keys for the destinationCoordainteCache. These are based on
+ * the X & Z of the players initial location.
+ */
+ private final List destinationCoordinateKeys = new ArrayList();
+
+ public Teleporter(WorldServer par1WorldServer) {
+ this.worldServerInstance = par1WorldServer;
+ this.random = new EaglercraftRandom(par1WorldServer.getSeed());
+ }
+
+ /**
+ * Place an entity in a nearby portal, creating one if necessary.
+ */
+ public void placeInPortal(Entity par1Entity, double par2, double par4, double par6, float par8) {
+ if (this.worldServerInstance.provider.dimensionId != 1) {
+ if (!this.placeInExistingPortal(par1Entity, par2, par4, par6, par8)) {
+ this.makePortal(par1Entity);
+ this.placeInExistingPortal(par1Entity, par2, par4, par6, par8);
+ }
+ } else {
+ int var9 = MathHelper.floor_double(par1Entity.posX);
+ int var10 = MathHelper.floor_double(par1Entity.posY) - 1;
+ int var11 = MathHelper.floor_double(par1Entity.posZ);
+ byte var12 = 1;
+ byte var13 = 0;
+
+ for (int var14 = -2; var14 <= 2; ++var14) {
+ for (int var15 = -2; var15 <= 2; ++var15) {
+ for (int var16 = -1; var16 < 3; ++var16) {
+ int var17 = var9 + var15 * var12 + var14 * var13;
+ int var18 = var10 + var16;
+ int var19 = var11 + var15 * var13 - var14 * var12;
+ boolean var20 = var16 < 0;
+ this.worldServerInstance.setBlock(var17, var18, var19, var20 ? Block.obsidian.blockID : 0);
+ }
+ }
+ }
+
+ par1Entity.setLocationAndAngles((double) var9, (double) var10, (double) var11, par1Entity.rotationYaw,
+ 0.0F);
+ par1Entity.motionX = par1Entity.motionY = par1Entity.motionZ = 0.0D;
+ }
+ }
+
+ /**
+ * Place an entity in a nearby portal which already exists.
+ */
+ public boolean placeInExistingPortal(Entity par1Entity, double par2, double par4, double par6, float par8) {
+ short var9 = 128;
+ double var10 = -1.0D;
+ int var12 = 0;
+ int var13 = 0;
+ int var14 = 0;
+ int var15 = MathHelper.floor_double(par1Entity.posX);
+ int var16 = MathHelper.floor_double(par1Entity.posZ);
+ long var17 = ChunkCoordIntPair.chunkXZ2Int(var15, var16);
+ boolean var19 = true;
+ double var27;
+ int var48;
+
+ if (this.destinationCoordinateCache.containsItem(var17)) {
+ PortalPosition var20 = (PortalPosition) this.destinationCoordinateCache.getValueByKey(var17);
+ var10 = 0.0D;
+ var12 = var20.posX;
+ var13 = var20.posY;
+ var14 = var20.posZ;
+ var20.lastUpdateTime = this.worldServerInstance.getTotalWorldTime();
+ var19 = false;
+ } else {
+ for (var48 = var15 - var9; var48 <= var15 + var9; ++var48) {
+ double var21 = (double) var48 + 0.5D - par1Entity.posX;
+
+ for (int var23 = var16 - var9; var23 <= var16 + var9; ++var23) {
+ double var24 = (double) var23 + 0.5D - par1Entity.posZ;
+
+ for (int var26 = this.worldServerInstance.getActualHeight() - 1; var26 >= 0; --var26) {
+ if (this.worldServerInstance.getBlockId(var48, var26, var23) == Block.portal.blockID) {
+ while (this.worldServerInstance.getBlockId(var48, var26 - 1,
+ var23) == Block.portal.blockID) {
+ --var26;
+ }
+
+ var27 = (double) var26 + 0.5D - par1Entity.posY;
+ double var29 = var21 * var21 + var27 * var27 + var24 * var24;
+
+ if (var10 < 0.0D || var29 < var10) {
+ var10 = var29;
+ var12 = var48;
+ var13 = var26;
+ var14 = var23;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (var10 >= 0.0D) {
+ if (var19) {
+ this.destinationCoordinateCache.add(var17,
+ new PortalPosition(this, var12, var13, var14, this.worldServerInstance.getTotalWorldTime()));
+ this.destinationCoordinateKeys.add(Long.valueOf(var17));
+ }
+
+ double var49 = (double) var12 + 0.5D;
+ double var25 = (double) var13 + 0.5D;
+ var27 = (double) var14 + 0.5D;
+ int var50 = -1;
+
+ if (this.worldServerInstance.getBlockId(var12 - 1, var13, var14) == Block.portal.blockID) {
+ var50 = 2;
+ }
+
+ if (this.worldServerInstance.getBlockId(var12 + 1, var13, var14) == Block.portal.blockID) {
+ var50 = 0;
+ }
+
+ if (this.worldServerInstance.getBlockId(var12, var13, var14 - 1) == Block.portal.blockID) {
+ var50 = 3;
+ }
+
+ if (this.worldServerInstance.getBlockId(var12, var13, var14 + 1) == Block.portal.blockID) {
+ var50 = 1;
+ }
+
+ int var30 = par1Entity.getTeleportDirection();
+
+ if (var50 > -1) {
+ int var31 = Direction.rotateLeft[var50];
+ int var32 = Direction.offsetX[var50];
+ int var33 = Direction.offsetZ[var50];
+ int var34 = Direction.offsetX[var31];
+ int var35 = Direction.offsetZ[var31];
+ boolean var36 = !this.worldServerInstance.isAirBlock(var12 + var32 + var34, var13,
+ var14 + var33 + var35)
+ || !this.worldServerInstance.isAirBlock(var12 + var32 + var34, var13 + 1,
+ var14 + var33 + var35);
+ boolean var37 = !this.worldServerInstance.isAirBlock(var12 + var32, var13, var14 + var33)
+ || !this.worldServerInstance.isAirBlock(var12 + var32, var13 + 1, var14 + var33);
+
+ if (var36 && var37) {
+ var50 = Direction.footInvisibleFaceRemap[var50];
+ var31 = Direction.footInvisibleFaceRemap[var31];
+ var32 = Direction.offsetX[var50];
+ var33 = Direction.offsetZ[var50];
+ var34 = Direction.offsetX[var31];
+ var35 = Direction.offsetZ[var31];
+ var48 = var12 - var34;
+ var49 -= (double) var34;
+ int var22 = var14 - var35;
+ var27 -= (double) var35;
+ var36 = !this.worldServerInstance.isAirBlock(var48 + var32 + var34, var13, var22 + var33 + var35)
+ || !this.worldServerInstance.isAirBlock(var48 + var32 + var34, var13 + 1,
+ var22 + var33 + var35);
+ var37 = !this.worldServerInstance.isAirBlock(var48 + var32, var13, var22 + var33)
+ || !this.worldServerInstance.isAirBlock(var48 + var32, var13 + 1, var22 + var33);
+ }
+
+ float var38 = 0.5F;
+ float var39 = 0.5F;
+
+ if (!var36 && var37) {
+ var38 = 1.0F;
+ } else if (var36 && !var37) {
+ var38 = 0.0F;
+ } else if (var36 && var37) {
+ var39 = 0.0F;
+ }
+
+ var49 += (double) ((float) var34 * var38 + var39 * (float) var32);
+ var27 += (double) ((float) var35 * var38 + var39 * (float) var33);
+ float var40 = 0.0F;
+ float var41 = 0.0F;
+ float var42 = 0.0F;
+ float var43 = 0.0F;
+
+ if (var50 == var30) {
+ var40 = 1.0F;
+ var41 = 1.0F;
+ } else if (var50 == Direction.footInvisibleFaceRemap[var30]) {
+ var40 = -1.0F;
+ var41 = -1.0F;
+ } else if (var50 == Direction.enderEyeMetaToDirection[var30]) {
+ var42 = 1.0F;
+ var43 = -1.0F;
+ } else {
+ var42 = -1.0F;
+ var43 = 1.0F;
+ }
+
+ double var44 = par1Entity.motionX;
+ double var46 = par1Entity.motionZ;
+ par1Entity.motionX = var44 * (double) var40 + var46 * (double) var43;
+ par1Entity.motionZ = var44 * (double) var42 + var46 * (double) var41;
+ par1Entity.rotationYaw = par8 - (float) (var30 * 90) + (float) (var50 * 90);
+ } else {
+ par1Entity.motionX = par1Entity.motionY = par1Entity.motionZ = 0.0D;
+ }
+
+ par1Entity.setLocationAndAngles(var49, var25, var27, par1Entity.rotationYaw, par1Entity.rotationPitch);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public boolean makePortal(Entity par1Entity) {
+ byte var2 = 16;
+ double var3 = -1.0D;
+ int var5 = MathHelper.floor_double(par1Entity.posX);
+ int var6 = MathHelper.floor_double(par1Entity.posY);
+ int var7 = MathHelper.floor_double(par1Entity.posZ);
+ int var8 = var5;
+ int var9 = var6;
+ int var10 = var7;
+ int var11 = 0;
+ int var12 = this.random.nextInt(4);
+ int var13;
+ double var14;
+ int var16;
+ double var17;
+ int var19;
+ int var20;
+ int var21;
+ int var22;
+ int var23;
+ int var24;
+ int var25;
+ int var26;
+ int var27;
+ double var31;
+ double var32;
+
+ for (var13 = var5 - var2; var13 <= var5 + var2; ++var13) {
+ var14 = (double) var13 + 0.5D - par1Entity.posX;
+
+ for (var16 = var7 - var2; var16 <= var7 + var2; ++var16) {
+ var17 = (double) var16 + 0.5D - par1Entity.posZ;
+ label274:
+
+ for (var19 = this.worldServerInstance.getActualHeight() - 1; var19 >= 0; --var19) {
+ if (this.worldServerInstance.isAirBlock(var13, var19, var16)) {
+ while (var19 > 0 && this.worldServerInstance.isAirBlock(var13, var19 - 1, var16)) {
+ --var19;
+ }
+
+ for (var20 = var12; var20 < var12 + 4; ++var20) {
+ var21 = var20 % 2;
+ var22 = 1 - var21;
+
+ if (var20 % 4 >= 2) {
+ var21 = -var21;
+ var22 = -var22;
+ }
+
+ for (var23 = 0; var23 < 3; ++var23) {
+ for (var24 = 0; var24 < 4; ++var24) {
+ for (var25 = -1; var25 < 4; ++var25) {
+ var26 = var13 + (var24 - 1) * var21 + var23 * var22;
+ var27 = var19 + var25;
+ int var28 = var16 + (var24 - 1) * var22 - var23 * var21;
+
+ if (var25 < 0
+ && !this.worldServerInstance.getBlockMaterial(var26, var27, var28)
+ .isSolid()
+ || var25 >= 0
+ && !this.worldServerInstance.isAirBlock(var26, var27, var28)) {
+ continue label274;
+ }
+ }
+ }
+ }
+
+ var31 = (double) var19 + 0.5D - par1Entity.posY;
+ var32 = var14 * var14 + var31 * var31 + var17 * var17;
+
+ if (var3 < 0.0D || var32 < var3) {
+ var3 = var32;
+ var8 = var13;
+ var9 = var19;
+ var10 = var16;
+ var11 = var20 % 4;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (var3 < 0.0D) {
+ for (var13 = var5 - var2; var13 <= var5 + var2; ++var13) {
+ var14 = (double) var13 + 0.5D - par1Entity.posX;
+
+ for (var16 = var7 - var2; var16 <= var7 + var2; ++var16) {
+ var17 = (double) var16 + 0.5D - par1Entity.posZ;
+ label222:
+
+ for (var19 = this.worldServerInstance.getActualHeight() - 1; var19 >= 0; --var19) {
+ if (this.worldServerInstance.isAirBlock(var13, var19, var16)) {
+ while (var19 > 0 && this.worldServerInstance.isAirBlock(var13, var19 - 1, var16)) {
+ --var19;
+ }
+
+ for (var20 = var12; var20 < var12 + 2; ++var20) {
+ var21 = var20 % 2;
+ var22 = 1 - var21;
+
+ for (var23 = 0; var23 < 4; ++var23) {
+ for (var24 = -1; var24 < 4; ++var24) {
+ var25 = var13 + (var23 - 1) * var21;
+ var26 = var19 + var24;
+ var27 = var16 + (var23 - 1) * var22;
+
+ if (var24 < 0
+ && !this.worldServerInstance.getBlockMaterial(var25, var26, var27)
+ .isSolid()
+ || var24 >= 0
+ && !this.worldServerInstance.isAirBlock(var25, var26, var27)) {
+ continue label222;
+ }
+ }
+ }
+
+ var31 = (double) var19 + 0.5D - par1Entity.posY;
+ var32 = var14 * var14 + var31 * var31 + var17 * var17;
+
+ if (var3 < 0.0D || var32 < var3) {
+ var3 = var32;
+ var8 = var13;
+ var9 = var19;
+ var10 = var16;
+ var11 = var20 % 2;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ int var29 = var8;
+ int var15 = var9;
+ var16 = var10;
+ int var30 = var11 % 2;
+ int var18 = 1 - var30;
+
+ if (var11 % 4 >= 2) {
+ var30 = -var30;
+ var18 = -var18;
+ }
+
+ boolean var33;
+
+ if (var3 < 0.0D) {
+ if (var9 < 70) {
+ var9 = 70;
+ }
+
+ if (var9 > this.worldServerInstance.getActualHeight() - 10) {
+ var9 = this.worldServerInstance.getActualHeight() - 10;
+ }
+
+ var15 = var9;
+
+ for (var19 = -1; var19 <= 1; ++var19) {
+ for (var20 = 1; var20 < 3; ++var20) {
+ for (var21 = -1; var21 < 3; ++var21) {
+ var22 = var29 + (var20 - 1) * var30 + var19 * var18;
+ var23 = var15 + var21;
+ var24 = var16 + (var20 - 1) * var18 - var19 * var30;
+ var33 = var21 < 0;
+ this.worldServerInstance.setBlock(var22, var23, var24, var33 ? Block.obsidian.blockID : 0);
+ }
+ }
+ }
+ }
+
+ for (var19 = 0; var19 < 4; ++var19) {
+ for (var20 = 0; var20 < 4; ++var20) {
+ for (var21 = -1; var21 < 4; ++var21) {
+ var22 = var29 + (var20 - 1) * var30;
+ var23 = var15 + var21;
+ var24 = var16 + (var20 - 1) * var18;
+ var33 = var20 == 0 || var20 == 3 || var21 == -1 || var21 == 3;
+ this.worldServerInstance.setBlock(var22, var23, var24,
+ var33 ? Block.obsidian.blockID : Block.portal.blockID, 0, 2);
+ }
+ }
+
+ for (var20 = 0; var20 < 4; ++var20) {
+ for (var21 = -1; var21 < 4; ++var21) {
+ var22 = var29 + (var20 - 1) * var30;
+ var23 = var15 + var21;
+ var24 = var16 + (var20 - 1) * var18;
+ this.worldServerInstance.notifyBlocksOfNeighborChange(var22, var23, var24,
+ this.worldServerInstance.getBlockId(var22, var23, var24));
+ }
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * called periodically to remove out-of-date portal locations from the cache
+ * list. Argument par1 is a WorldServer.getTotalWorldTime() value.
+ */
+ public void removeStalePortalLocations(long par1) {
+ if (par1 % 100L == 0L) {
+ Iterator var3 = this.destinationCoordinateKeys.iterator();
+ long var4 = par1 - 600L;
+
+ while (var3.hasNext()) {
+ Long var6 = (Long) var3.next();
+ PortalPosition var7 = (PortalPosition) this.destinationCoordinateCache.getValueByKey(var6.longValue());
+
+ if (var7 == null || var7.lastUpdateTime < var4) {
+ var3.remove();
+ this.destinationCoordinateCache.remove(var6.longValue());
+ }
+ }
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/TileEntity.java b/sp-server/src/main/java/net/minecraft/src/TileEntity.java
new file mode 100644
index 0000000..c142d5a
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/TileEntity.java
@@ -0,0 +1,234 @@
+package net.minecraft.src;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import net.minecraft.server.MinecraftServer;
+
+public class TileEntity {
+ /**
+ * A HashMap storing string names of classes mapping to the actual
+ * java.lang.Class type.
+ */
+ private static Map nameToClassMap = new HashMap();
+
+ /**
+ * A HashMap storing the classes and mapping to the string names (reverse of
+ * nameToClassMap).
+ */
+ private static Map classToNameMap = new HashMap();
+
+ /** The reference to the world. */
+ protected World worldObj;
+
+ /** The x coordinate of the tile entity. */
+ public int xCoord;
+
+ /** The y coordinate of the tile entity. */
+ public int yCoord;
+
+ /** The z coordinate of the tile entity. */
+ public int zCoord;
+ protected boolean tileEntityInvalid;
+ public int blockMetadata = -1;
+
+ /** the Block type that this TileEntity is contained within */
+ public Block blockType;
+
+ /**
+ * Adds a new two-way mapping between the class and its string name in both
+ * hashmaps.
+ */
+ private static void addMapping(Class par0Class, String par1Str) {
+ if (nameToClassMap.containsKey(par1Str)) {
+ throw new IllegalArgumentException("Duplicate id: " + par1Str);
+ } else {
+ nameToClassMap.put(par1Str, par0Class);
+ classToNameMap.put(par0Class, par1Str);
+ }
+ }
+
+ /**
+ * Returns the worldObj for this tileEntity.
+ */
+ public World getWorldObj() {
+ return this.worldObj;
+ }
+
+ /**
+ * Sets the worldObj for this tileEntity.
+ */
+ public void setWorldObj(World par1World) {
+ this.worldObj = par1World;
+ }
+
+ public boolean func_70309_m() {
+ return this.worldObj != null;
+ }
+
+ /**
+ * Reads a tile entity from NBT.
+ */
+ public void readFromNBT(NBTTagCompound par1NBTTagCompound) {
+ this.xCoord = par1NBTTagCompound.getInteger("x");
+ this.yCoord = par1NBTTagCompound.getInteger("y");
+ this.zCoord = par1NBTTagCompound.getInteger("z");
+ }
+
+ /**
+ * Writes a tile entity to NBT.
+ */
+ public void writeToNBT(NBTTagCompound par1NBTTagCompound) {
+ String var2 = (String) classToNameMap.get(this.getClass());
+
+ if (var2 == null) {
+ throw new RuntimeException(this.getClass() + " is missing a mapping! This is a bug!");
+ } else {
+ par1NBTTagCompound.setString("id", var2);
+ par1NBTTagCompound.setInteger("x", this.xCoord);
+ par1NBTTagCompound.setInteger("y", this.yCoord);
+ par1NBTTagCompound.setInteger("z", this.zCoord);
+ }
+ }
+
+ /**
+ * Allows the entity to update its state. Overridden in most subclasses, e.g.
+ * the mob spawner uses this to count ticks and creates a new spawn inside its
+ * implementation.
+ */
+ public void updateEntity() {
+ }
+
+ /**
+ * Creates a new entity and loads its data from the specified NBT.
+ */
+ public static TileEntity createAndLoadEntity(NBTTagCompound par0NBTTagCompound) {
+ TileEntity var1 = null;
+
+ try {
+ Class var2 = (Class) nameToClassMap.get(par0NBTTagCompound.getString("id"));
+
+ if (var2 != null) {
+ var1 = (TileEntity) var2.newInstance();
+ }
+ } catch (Exception var3) {
+ var3.printStackTrace();
+ }
+
+ if (var1 != null) {
+ var1.readFromNBT(par0NBTTagCompound);
+ } else {
+ MinecraftServer.getServer().getLogAgent()
+ .func_98236_b("Skipping TileEntity with id " + par0NBTTagCompound.getString("id"));
+ }
+
+ return var1;
+ }
+
+ /**
+ * Returns block data at the location of this entity (client-only).
+ */
+ public int getBlockMetadata() {
+ if (this.blockMetadata == -1) {
+ this.blockMetadata = this.worldObj.getBlockMetadata(this.xCoord, this.yCoord, this.zCoord);
+ }
+
+ return this.blockMetadata;
+ }
+
+ /**
+ * Called when an the contents of an Inventory change, usually
+ */
+ public void onInventoryChanged() {
+ if (this.worldObj != null) {
+ this.blockMetadata = this.worldObj.getBlockMetadata(this.xCoord, this.yCoord, this.zCoord);
+ this.worldObj.updateTileEntityChunkAndDoNothing(this.xCoord, this.yCoord, this.zCoord, this);
+
+ if (this.getBlockType() != null) {
+ this.worldObj.func_96440_m(this.xCoord, this.yCoord, this.zCoord, this.getBlockType().blockID);
+ }
+ }
+ }
+
+ /**
+ * Gets the block type at the location of this entity (client-only).
+ */
+ public Block getBlockType() {
+ if (this.blockType == null) {
+ this.blockType = Block.blocksList[this.worldObj.getBlockId(this.xCoord, this.yCoord, this.zCoord)];
+ }
+
+ return this.blockType;
+ }
+
+ /**
+ * Overriden in a sign to provide the text.
+ */
+ public Packet getDescriptionPacket() {
+ return null;
+ }
+
+ /**
+ * returns true if tile entity is invalid, false otherwise
+ */
+ public boolean isInvalid() {
+ return this.tileEntityInvalid;
+ }
+
+ /**
+ * invalidates a tile entity
+ */
+ public void invalidate() {
+ this.tileEntityInvalid = true;
+ }
+
+ /**
+ * validates a tile entity
+ */
+ public void validate() {
+ this.tileEntityInvalid = false;
+ }
+
+ /**
+ * Called when a client event is received with the event number and argument,
+ * see World.sendClientEvent
+ */
+ public boolean receiveClientEvent(int par1, int par2) {
+ return false;
+ }
+
+ /**
+ * Causes the TileEntity to reset all it's cached values for it's container
+ * block, blockID, metaData and in the case of chests, the adjcacent chest check
+ */
+ public void updateContainingBlockInfo() {
+ this.blockType = null;
+ this.blockMetadata = -1;
+ }
+
+ static Map getClassToNameMap() {
+ return classToNameMap;
+ }
+
+ static {
+ addMapping(TileEntityFurnace.class, "Furnace");
+ addMapping(TileEntityChest.class, "Chest");
+ addMapping(TileEntityEnderChest.class, "EnderChest");
+ addMapping(TileEntityRecordPlayer.class, "RecordPlayer");
+ addMapping(TileEntityDispenser.class, "Trap");
+ addMapping(TileEntityDropper.class, "Dropper");
+ addMapping(TileEntitySign.class, "Sign");
+ addMapping(TileEntityMobSpawner.class, "MobSpawner");
+ addMapping(TileEntityNote.class, "Music");
+ addMapping(TileEntityPiston.class, "Piston");
+ addMapping(TileEntityBrewingStand.class, "Cauldron");
+ addMapping(TileEntityEnchantmentTable.class, "EnchantTable");
+ addMapping(TileEntityEndPortal.class, "Airportal");
+ addMapping(TileEntityCommandBlock.class, "Control");
+ addMapping(TileEntityBeacon.class, "Beacon");
+ addMapping(TileEntitySkull.class, "Skull");
+ addMapping(TileEntityDaylightDetector.class, "DLDetector");
+ addMapping(TileEntityHopper.class, "Hopper");
+ addMapping(TileEntityComparator.class, "Comparator");
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/TileEntityBeacon.java b/sp-server/src/main/java/net/minecraft/src/TileEntityBeacon.java
new file mode 100644
index 0000000..09634ba
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/TileEntityBeacon.java
@@ -0,0 +1,311 @@
+package net.minecraft.src;
+
+import java.util.Iterator;
+import java.util.List;
+
+public class TileEntityBeacon extends TileEntity implements IInventory {
+ /** List of effects that Beacon can apply */
+ public static final Potion[][] effectsList = new Potion[][] { { Potion.moveSpeed, Potion.digSpeed },
+ { Potion.resistance, Potion.jump }, { Potion.damageBoost }, { Potion.regeneration } };
+ private boolean isBeaconActive;
+
+ /** Level of this beacon's pyramid. */
+ private int levels = -1;
+
+ /** Primary potion effect given by this beacon. */
+ private int primaryEffect;
+
+ /** Secondary potion effect given by this beacon. */
+ private int secondaryEffect;
+
+ /** Item given to this beacon as payment. */
+ private ItemStack payment;
+ private String field_94048_i;
+
+ /**
+ * Allows the entity to update its state. Overridden in most subclasses, e.g.
+ * the mob spawner uses this to count ticks and creates a new spawn inside its
+ * implementation.
+ */
+ public void updateEntity() {
+ if (this.worldObj.getTotalWorldTime() % 80L == 0L) {
+ this.updateState();
+ this.addEffectsToPlayers();
+ }
+ }
+
+ private void addEffectsToPlayers() {
+ if (this.isBeaconActive && this.levels > 0 && !this.worldObj.isRemote && this.primaryEffect > 0) {
+ double var1 = (double) (this.levels * 10 + 10);
+ byte var3 = 0;
+
+ if (this.levels >= 4 && this.primaryEffect == this.secondaryEffect) {
+ var3 = 1;
+ }
+
+ AxisAlignedBB var4 = AxisAlignedBB.getAABBPool()
+ .getAABB((double) this.xCoord, (double) this.yCoord, (double) this.zCoord,
+ (double) (this.xCoord + 1), (double) (this.yCoord + 1), (double) (this.zCoord + 1))
+ .expand(var1, var1, var1);
+ var4.maxY = (double) this.worldObj.getHeight();
+ List var5 = this.worldObj.getEntitiesWithinAABB(EntityPlayer.class, var4);
+ Iterator var6 = var5.iterator();
+ EntityPlayer var7;
+
+ while (var6.hasNext()) {
+ var7 = (EntityPlayer) var6.next();
+ var7.addPotionEffect(new PotionEffect(this.primaryEffect, 180, var3, true));
+ }
+
+ if (this.levels >= 4 && this.primaryEffect != this.secondaryEffect && this.secondaryEffect > 0) {
+ var6 = var5.iterator();
+
+ while (var6.hasNext()) {
+ var7 = (EntityPlayer) var6.next();
+ var7.addPotionEffect(new PotionEffect(this.secondaryEffect, 180, 0, true));
+ }
+ }
+ }
+ }
+
+ /**
+ * Checks if the Beacon has a valid pyramid underneath and direct sunlight above
+ */
+ private void updateState() {
+ if (!this.worldObj.canBlockSeeTheSky(this.xCoord, this.yCoord + 1, this.zCoord)) {
+ this.isBeaconActive = false;
+ this.levels = 0;
+ } else {
+ this.isBeaconActive = true;
+ this.levels = 0;
+
+ for (int var1 = 1; var1 <= 4; this.levels = var1++) {
+ int var2 = this.yCoord - var1;
+
+ if (var2 < 0) {
+ break;
+ }
+
+ boolean var3 = true;
+
+ for (int var4 = this.xCoord - var1; var4 <= this.xCoord + var1 && var3; ++var4) {
+ for (int var5 = this.zCoord - var1; var5 <= this.zCoord + var1; ++var5) {
+ int var6 = this.worldObj.getBlockId(var4, var2, var5);
+
+ if (var6 != Block.blockEmerald.blockID && var6 != Block.blockGold.blockID
+ && var6 != Block.blockDiamond.blockID && var6 != Block.blockIron.blockID) {
+ var3 = false;
+ break;
+ }
+ }
+ }
+
+ if (!var3) {
+ break;
+ }
+ }
+
+ if (this.levels == 0) {
+ this.isBeaconActive = false;
+ }
+ }
+ }
+
+ /**
+ * Return the primary potion effect given by this beacon.
+ */
+ public int getPrimaryEffect() {
+ return this.primaryEffect;
+ }
+
+ /**
+ * Return the secondary potion effect given by this beacon.
+ */
+ public int getSecondaryEffect() {
+ return this.secondaryEffect;
+ }
+
+ /**
+ * Return the levels of this beacon's pyramid.
+ */
+ public int getLevels() {
+ return this.levels;
+ }
+
+ public void setPrimaryEffect(int par1) {
+ this.primaryEffect = 0;
+
+ for (int var2 = 0; var2 < this.levels && var2 < 3; ++var2) {
+ Potion[] var3 = effectsList[var2];
+ int var4 = var3.length;
+
+ for (int var5 = 0; var5 < var4; ++var5) {
+ Potion var6 = var3[var5];
+
+ if (var6.id == par1) {
+ this.primaryEffect = par1;
+ return;
+ }
+ }
+ }
+ }
+
+ public void setSecondaryEffect(int par1) {
+ this.secondaryEffect = 0;
+
+ if (this.levels >= 4) {
+ for (int var2 = 0; var2 < 4; ++var2) {
+ Potion[] var3 = effectsList[var2];
+ int var4 = var3.length;
+
+ for (int var5 = 0; var5 < var4; ++var5) {
+ Potion var6 = var3[var5];
+
+ if (var6.id == par1) {
+ this.secondaryEffect = par1;
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Overriden in a sign to provide the text.
+ */
+ public Packet getDescriptionPacket() {
+ NBTTagCompound var1 = new NBTTagCompound();
+ this.writeToNBT(var1);
+ return new Packet132TileEntityData(this.xCoord, this.yCoord, this.zCoord, 3, var1);
+ }
+
+ /**
+ * Reads a tile entity from NBT.
+ */
+ public void readFromNBT(NBTTagCompound par1NBTTagCompound) {
+ super.readFromNBT(par1NBTTagCompound);
+ this.primaryEffect = par1NBTTagCompound.getInteger("Primary");
+ this.secondaryEffect = par1NBTTagCompound.getInteger("Secondary");
+ this.levels = par1NBTTagCompound.getInteger("Levels");
+ }
+
+ /**
+ * Writes a tile entity to NBT.
+ */
+ public void writeToNBT(NBTTagCompound par1NBTTagCompound) {
+ super.writeToNBT(par1NBTTagCompound);
+ par1NBTTagCompound.setInteger("Primary", this.primaryEffect);
+ par1NBTTagCompound.setInteger("Secondary", this.secondaryEffect);
+ par1NBTTagCompound.setInteger("Levels", this.levels);
+ }
+
+ /**
+ * Returns the number of slots in the inventory.
+ */
+ public int getSizeInventory() {
+ return 1;
+ }
+
+ /**
+ * Returns the stack in slot i
+ */
+ public ItemStack getStackInSlot(int par1) {
+ return par1 == 0 ? this.payment : null;
+ }
+
+ /**
+ * Removes from an inventory slot (first arg) up to a specified number (second
+ * arg) of items and returns them in a new stack.
+ */
+ public ItemStack decrStackSize(int par1, int par2) {
+ if (par1 == 0 && this.payment != null) {
+ if (par2 >= this.payment.stackSize) {
+ ItemStack var3 = this.payment;
+ this.payment = null;
+ return var3;
+ } else {
+ this.payment.stackSize -= par2;
+ return new ItemStack(this.payment.itemID, par2, this.payment.getItemDamage());
+ }
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * When some containers are closed they call this on each slot, then drop
+ * whatever it returns as an EntityItem - like when you close a workbench GUI.
+ */
+ public ItemStack getStackInSlotOnClosing(int par1) {
+ if (par1 == 0 && this.payment != null) {
+ ItemStack var2 = this.payment;
+ this.payment = null;
+ return var2;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Sets the given item stack to the specified slot in the inventory (can be
+ * crafting or armor sections).
+ */
+ public void setInventorySlotContents(int par1, ItemStack par2ItemStack) {
+ if (par1 == 0) {
+ this.payment = par2ItemStack;
+ }
+ }
+
+ /**
+ * Returns the name of the inventory.
+ */
+ public String getInvName() {
+ return this.isInvNameLocalized() ? this.field_94048_i : "container.beacon";
+ }
+
+ /**
+ * If this returns false, the inventory name will be used as an unlocalized
+ * name, and translated into the player's language. Otherwise it will be used
+ * directly.
+ */
+ public boolean isInvNameLocalized() {
+ return this.field_94048_i != null && this.field_94048_i.length() > 0;
+ }
+
+ public void func_94047_a(String par1Str) {
+ this.field_94048_i = par1Str;
+ }
+
+ /**
+ * Returns the maximum stack size for a inventory slot. Seems to always be 64,
+ * possibly will be extended. *Isn't this more of a set than a get?*
+ */
+ public int getInventoryStackLimit() {
+ return 1;
+ }
+
+ /**
+ * Do not make give this method the name canInteractWith because it clashes with
+ * Container
+ */
+ public boolean isUseableByPlayer(EntityPlayer par1EntityPlayer) {
+ return this.worldObj.getBlockTileEntity(this.xCoord, this.yCoord, this.zCoord) != this ? false
+ : par1EntityPlayer.getDistanceSq((double) this.xCoord + 0.5D, (double) this.yCoord + 0.5D,
+ (double) this.zCoord + 0.5D) <= 64.0D;
+ }
+
+ public void openChest() {
+ }
+
+ public void closeChest() {
+ }
+
+ /**
+ * Returns true if automation is allowed to insert the given stack (ignoring
+ * stack size) into the given slot.
+ */
+ public boolean isStackValidForSlot(int par1, ItemStack par2ItemStack) {
+ return par2ItemStack.itemID == Item.emerald.itemID || par2ItemStack.itemID == Item.diamond.itemID
+ || par2ItemStack.itemID == Item.ingotGold.itemID || par2ItemStack.itemID == Item.ingotIron.itemID;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/TileEntityBrewingStand.java b/sp-server/src/main/java/net/minecraft/src/TileEntityBrewingStand.java
new file mode 100644
index 0000000..08ffcbc
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/TileEntityBrewingStand.java
@@ -0,0 +1,332 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+public class TileEntityBrewingStand extends TileEntity implements ISidedInventory {
+ private static final int[] field_102017_a = new int[] { 3 };
+ private static final int[] field_102016_b = new int[] { 0, 1, 2 };
+
+ /** The itemstacks currently placed in the slots of the brewing stand */
+ private ItemStack[] brewingItemStacks = new ItemStack[4];
+ private int brewTime;
+
+ /**
+ * an integer with each bit specifying whether that slot of the stand contains a
+ * potion
+ */
+ private int filledSlots;
+ private int ingredientID;
+ private String field_94132_e;
+
+ /**
+ * Returns the name of the inventory.
+ */
+ public String getInvName() {
+ return this.isInvNameLocalized() ? this.field_94132_e : "container.brewing";
+ }
+
+ /**
+ * If this returns false, the inventory name will be used as an unlocalized
+ * name, and translated into the player's language. Otherwise it will be used
+ * directly.
+ */
+ public boolean isInvNameLocalized() {
+ return this.field_94132_e != null && this.field_94132_e.length() > 0;
+ }
+
+ public void func_94131_a(String par1Str) {
+ this.field_94132_e = par1Str;
+ }
+
+ /**
+ * Returns the number of slots in the inventory.
+ */
+ public int getSizeInventory() {
+ return this.brewingItemStacks.length;
+ }
+
+ /**
+ * Allows the entity to update its state. Overridden in most subclasses, e.g.
+ * the mob spawner uses this to count ticks and creates a new spawn inside its
+ * implementation.
+ */
+ public void updateEntity() {
+ if (this.brewTime > 0) {
+ --this.brewTime;
+
+ if (this.brewTime == 0) {
+ this.brewPotions();
+ this.onInventoryChanged();
+ } else if (!this.canBrew()) {
+ this.brewTime = 0;
+ this.onInventoryChanged();
+ } else if (this.ingredientID != this.brewingItemStacks[3].itemID) {
+ this.brewTime = 0;
+ this.onInventoryChanged();
+ }
+ } else if (this.canBrew()) {
+ this.brewTime = 400;
+ this.ingredientID = this.brewingItemStacks[3].itemID;
+ }
+
+ int var1 = this.getFilledSlots();
+
+ if (var1 != this.filledSlots) {
+ this.filledSlots = var1;
+ this.worldObj.setBlockMetadata(this.xCoord, this.yCoord, this.zCoord, var1, 2);
+ }
+
+ super.updateEntity();
+ }
+
+ public int getBrewTime() {
+ return this.brewTime;
+ }
+
+ private boolean canBrew() {
+ if (this.brewingItemStacks[3] != null && this.brewingItemStacks[3].stackSize > 0) {
+ ItemStack var1 = this.brewingItemStacks[3];
+
+ if (!Item.itemsList[var1.itemID].isPotionIngredient()) {
+ return false;
+ } else {
+ boolean var2 = false;
+
+ for (int var3 = 0; var3 < 3; ++var3) {
+ if (this.brewingItemStacks[var3] != null
+ && this.brewingItemStacks[var3].itemID == Item.potion.itemID) {
+ int var4 = this.brewingItemStacks[var3].getItemDamage();
+ int var5 = this.getPotionResult(var4, var1);
+
+ if (!ItemPotion.isSplash(var4) && ItemPotion.isSplash(var5)) {
+ var2 = true;
+ break;
+ }
+
+ List var6 = Item.potion.getEffects(var4);
+ List var7 = Item.potion.getEffects(var5);
+
+ if ((var4 <= 0 || var6 != var7) && (var6 == null || !var6.equals(var7) && var7 != null)
+ && var4 != var5) {
+ var2 = true;
+ break;
+ }
+ }
+ }
+
+ return var2;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ private void brewPotions() {
+ if (this.canBrew()) {
+ ItemStack var1 = this.brewingItemStacks[3];
+
+ for (int var2 = 0; var2 < 3; ++var2) {
+ if (this.brewingItemStacks[var2] != null && this.brewingItemStacks[var2].itemID == Item.potion.itemID) {
+ int var3 = this.brewingItemStacks[var2].getItemDamage();
+ int var4 = this.getPotionResult(var3, var1);
+ List var5 = Item.potion.getEffects(var3);
+ List var6 = Item.potion.getEffects(var4);
+
+ if ((var3 <= 0 || var5 != var6) && (var5 == null || !var5.equals(var6) && var6 != null)) {
+ if (var3 != var4) {
+ this.brewingItemStacks[var2].setItemDamage(var4);
+ }
+ } else if (!ItemPotion.isSplash(var3) && ItemPotion.isSplash(var4)) {
+ this.brewingItemStacks[var2].setItemDamage(var4);
+ }
+ }
+ }
+
+ if (Item.itemsList[var1.itemID].hasContainerItem()) {
+ this.brewingItemStacks[3] = new ItemStack(Item.itemsList[var1.itemID].getContainerItem());
+ } else {
+ --this.brewingItemStacks[3].stackSize;
+
+ if (this.brewingItemStacks[3].stackSize <= 0) {
+ this.brewingItemStacks[3] = null;
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the new potion damage value after the specified item is applied as an
+ * ingredient to the specified potion.
+ */
+ private int getPotionResult(int par1, ItemStack par2ItemStack) {
+ return par2ItemStack == null ? par1
+ : (Item.itemsList[par2ItemStack.itemID].isPotionIngredient()
+ ? PotionHelper.applyIngredient(par1, Item.itemsList[par2ItemStack.itemID].getPotionEffect())
+ : par1);
+ }
+
+ /**
+ * Reads a tile entity from NBT.
+ */
+ public void readFromNBT(NBTTagCompound par1NBTTagCompound) {
+ super.readFromNBT(par1NBTTagCompound);
+ NBTTagList var2 = par1NBTTagCompound.getTagList("Items");
+ this.brewingItemStacks = new ItemStack[this.getSizeInventory()];
+
+ for (int var3 = 0; var3 < var2.tagCount(); ++var3) {
+ NBTTagCompound var4 = (NBTTagCompound) var2.tagAt(var3);
+ byte var5 = var4.getByte("Slot");
+
+ if (var5 >= 0 && var5 < this.brewingItemStacks.length) {
+ this.brewingItemStacks[var5] = ItemStack.loadItemStackFromNBT(var4);
+ }
+ }
+
+ this.brewTime = par1NBTTagCompound.getShort("BrewTime");
+
+ if (par1NBTTagCompound.hasKey("CustomName")) {
+ this.field_94132_e = par1NBTTagCompound.getString("CustomName");
+ }
+ }
+
+ /**
+ * Writes a tile entity to NBT.
+ */
+ public void writeToNBT(NBTTagCompound par1NBTTagCompound) {
+ super.writeToNBT(par1NBTTagCompound);
+ par1NBTTagCompound.setShort("BrewTime", (short) this.brewTime);
+ NBTTagList var2 = new NBTTagList();
+
+ for (int var3 = 0; var3 < this.brewingItemStacks.length; ++var3) {
+ if (this.brewingItemStacks[var3] != null) {
+ NBTTagCompound var4 = new NBTTagCompound();
+ var4.setByte("Slot", (byte) var3);
+ this.brewingItemStacks[var3].writeToNBT(var4);
+ var2.appendTag(var4);
+ }
+ }
+
+ par1NBTTagCompound.setTag("Items", var2);
+
+ if (this.isInvNameLocalized()) {
+ par1NBTTagCompound.setString("CustomName", this.field_94132_e);
+ }
+ }
+
+ /**
+ * Returns the stack in slot i
+ */
+ public ItemStack getStackInSlot(int par1) {
+ return par1 >= 0 && par1 < this.brewingItemStacks.length ? this.brewingItemStacks[par1] : null;
+ }
+
+ /**
+ * Removes from an inventory slot (first arg) up to a specified number (second
+ * arg) of items and returns them in a new stack.
+ */
+ public ItemStack decrStackSize(int par1, int par2) {
+ if (par1 >= 0 && par1 < this.brewingItemStacks.length) {
+ ItemStack var3 = this.brewingItemStacks[par1];
+ this.brewingItemStacks[par1] = null;
+ return var3;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * When some containers are closed they call this on each slot, then drop
+ * whatever it returns as an EntityItem - like when you close a workbench GUI.
+ */
+ public ItemStack getStackInSlotOnClosing(int par1) {
+ if (par1 >= 0 && par1 < this.brewingItemStacks.length) {
+ ItemStack var2 = this.brewingItemStacks[par1];
+ this.brewingItemStacks[par1] = null;
+ return var2;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Sets the given item stack to the specified slot in the inventory (can be
+ * crafting or armor sections).
+ */
+ public void setInventorySlotContents(int par1, ItemStack par2ItemStack) {
+ if (par1 >= 0 && par1 < this.brewingItemStacks.length) {
+ this.brewingItemStacks[par1] = par2ItemStack;
+ }
+ }
+
+ /**
+ * Returns the maximum stack size for a inventory slot. Seems to always be 64,
+ * possibly will be extended. *Isn't this more of a set than a get?*
+ */
+ public int getInventoryStackLimit() {
+ return 64;
+ }
+
+ /**
+ * Do not make give this method the name canInteractWith because it clashes with
+ * Container
+ */
+ public boolean isUseableByPlayer(EntityPlayer par1EntityPlayer) {
+ return this.worldObj.getBlockTileEntity(this.xCoord, this.yCoord, this.zCoord) != this ? false
+ : par1EntityPlayer.getDistanceSq((double) this.xCoord + 0.5D, (double) this.yCoord + 0.5D,
+ (double) this.zCoord + 0.5D) <= 64.0D;
+ }
+
+ public void openChest() {
+ }
+
+ public void closeChest() {
+ }
+
+ /**
+ * Returns true if automation is allowed to insert the given stack (ignoring
+ * stack size) into the given slot.
+ */
+ public boolean isStackValidForSlot(int par1, ItemStack par2ItemStack) {
+ return par1 == 3 ? Item.itemsList[par2ItemStack.itemID].isPotionIngredient()
+ : par2ItemStack.itemID == Item.potion.itemID || par2ItemStack.itemID == Item.glassBottle.itemID;
+ }
+
+ /**
+ * returns an integer with each bit specifying wether that slot of the stand
+ * contains a potion
+ */
+ public int getFilledSlots() {
+ int var1 = 0;
+
+ for (int var2 = 0; var2 < 3; ++var2) {
+ if (this.brewingItemStacks[var2] != null) {
+ var1 |= 1 << var2;
+ }
+ }
+
+ return var1;
+ }
+
+ /**
+ * param side
+ */
+ public int[] getSlotsForFace(int par1) {
+ return par1 == 1 ? field_102017_a : field_102016_b;
+ }
+
+ /**
+ * Returns true if automation can insert the given item in the given slot from
+ * the given side. Args: Slot, item, side
+ */
+ public boolean canInsertItem(int par1, ItemStack par2ItemStack, int par3) {
+ return this.isStackValidForSlot(par1, par2ItemStack);
+ }
+
+ /**
+ * Returns true if automation can extract the given item in the given slot from
+ * the given side. Args: Slot, item, side
+ */
+ public boolean canExtractItem(int par1, ItemStack par2ItemStack, int par3) {
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/TileEntityChest.java b/sp-server/src/main/java/net/minecraft/src/TileEntityChest.java
new file mode 100644
index 0000000..24af14d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/TileEntityChest.java
@@ -0,0 +1,451 @@
+package net.minecraft.src;
+
+import java.util.Iterator;
+import java.util.List;
+
+public class TileEntityChest extends TileEntity implements IInventory {
+ private ItemStack[] chestContents = new ItemStack[36];
+
+ /** Determines if the check for adjacent chests has taken place. */
+ public boolean adjacentChestChecked = false;
+
+ /** Contains the chest tile located adjacent to this one (if any) */
+ public TileEntityChest adjacentChestZNeg;
+
+ /** Contains the chest tile located adjacent to this one (if any) */
+ public TileEntityChest adjacentChestXPos;
+
+ /** Contains the chest tile located adjacent to this one (if any) */
+ public TileEntityChest adjacentChestXNeg;
+
+ /** Contains the chest tile located adjacent to this one (if any) */
+ public TileEntityChest adjacentChestZPosition;
+
+ /** The current angle of the lid (between 0 and 1) */
+ public float lidAngle;
+
+ /** The angle of the lid last tick */
+ public float prevLidAngle;
+
+ /** The number of players currently using this chest */
+ public int numUsingPlayers;
+
+ /** Server sync counter (once per 20 ticks) */
+ private int ticksSinceSync;
+ private int field_94046_i = -1;
+ private String field_94045_s;
+
+ /**
+ * Returns the number of slots in the inventory.
+ */
+ public int getSizeInventory() {
+ return 27;
+ }
+
+ /**
+ * Returns the stack in slot i
+ */
+ public ItemStack getStackInSlot(int par1) {
+ return this.chestContents[par1];
+ }
+
+ /**
+ * Removes from an inventory slot (first arg) up to a specified number (second
+ * arg) of items and returns them in a new stack.
+ */
+ public ItemStack decrStackSize(int par1, int par2) {
+ if (this.chestContents[par1] != null) {
+ ItemStack var3;
+
+ if (this.chestContents[par1].stackSize <= par2) {
+ var3 = this.chestContents[par1];
+ this.chestContents[par1] = null;
+ this.onInventoryChanged();
+ return var3;
+ } else {
+ var3 = this.chestContents[par1].splitStack(par2);
+
+ if (this.chestContents[par1].stackSize == 0) {
+ this.chestContents[par1] = null;
+ }
+
+ this.onInventoryChanged();
+ return var3;
+ }
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * When some containers are closed they call this on each slot, then drop
+ * whatever it returns as an EntityItem - like when you close a workbench GUI.
+ */
+ public ItemStack getStackInSlotOnClosing(int par1) {
+ if (this.chestContents[par1] != null) {
+ ItemStack var2 = this.chestContents[par1];
+ this.chestContents[par1] = null;
+ return var2;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Sets the given item stack to the specified slot in the inventory (can be
+ * crafting or armor sections).
+ */
+ public void setInventorySlotContents(int par1, ItemStack par2ItemStack) {
+ this.chestContents[par1] = par2ItemStack;
+
+ if (par2ItemStack != null && par2ItemStack.stackSize > this.getInventoryStackLimit()) {
+ par2ItemStack.stackSize = this.getInventoryStackLimit();
+ }
+
+ this.onInventoryChanged();
+ }
+
+ /**
+ * Returns the name of the inventory.
+ */
+ public String getInvName() {
+ return this.isInvNameLocalized() ? this.field_94045_s : "container.chest";
+ }
+
+ /**
+ * If this returns false, the inventory name will be used as an unlocalized
+ * name, and translated into the player's language. Otherwise it will be used
+ * directly.
+ */
+ public boolean isInvNameLocalized() {
+ return this.field_94045_s != null && this.field_94045_s.length() > 0;
+ }
+
+ public void func_94043_a(String par1Str) {
+ this.field_94045_s = par1Str;
+ }
+
+ /**
+ * Reads a tile entity from NBT.
+ */
+ public void readFromNBT(NBTTagCompound par1NBTTagCompound) {
+ super.readFromNBT(par1NBTTagCompound);
+ NBTTagList var2 = par1NBTTagCompound.getTagList("Items");
+ this.chestContents = new ItemStack[this.getSizeInventory()];
+
+ if (par1NBTTagCompound.hasKey("CustomName")) {
+ this.field_94045_s = par1NBTTagCompound.getString("CustomName");
+ }
+
+ for (int var3 = 0; var3 < var2.tagCount(); ++var3) {
+ NBTTagCompound var4 = (NBTTagCompound) var2.tagAt(var3);
+ int var5 = var4.getByte("Slot") & 255;
+
+ if (var5 >= 0 && var5 < this.chestContents.length) {
+ this.chestContents[var5] = ItemStack.loadItemStackFromNBT(var4);
+ }
+ }
+ }
+
+ /**
+ * Writes a tile entity to NBT.
+ */
+ public void writeToNBT(NBTTagCompound par1NBTTagCompound) {
+ super.writeToNBT(par1NBTTagCompound);
+ NBTTagList var2 = new NBTTagList();
+
+ for (int var3 = 0; var3 < this.chestContents.length; ++var3) {
+ if (this.chestContents[var3] != null) {
+ NBTTagCompound var4 = new NBTTagCompound();
+ var4.setByte("Slot", (byte) var3);
+ this.chestContents[var3].writeToNBT(var4);
+ var2.appendTag(var4);
+ }
+ }
+
+ par1NBTTagCompound.setTag("Items", var2);
+
+ if (this.isInvNameLocalized()) {
+ par1NBTTagCompound.setString("CustomName", this.field_94045_s);
+ }
+ }
+
+ /**
+ * Returns the maximum stack size for a inventory slot. Seems to always be 64,
+ * possibly will be extended. *Isn't this more of a set than a get?*
+ */
+ public int getInventoryStackLimit() {
+ return 64;
+ }
+
+ /**
+ * Do not make give this method the name canInteractWith because it clashes with
+ * Container
+ */
+ public boolean isUseableByPlayer(EntityPlayer par1EntityPlayer) {
+ return this.worldObj.getBlockTileEntity(this.xCoord, this.yCoord, this.zCoord) != this ? false
+ : par1EntityPlayer.getDistanceSq((double) this.xCoord + 0.5D, (double) this.yCoord + 0.5D,
+ (double) this.zCoord + 0.5D) <= 64.0D;
+ }
+
+ /**
+ * Causes the TileEntity to reset all it's cached values for it's container
+ * block, blockID, metaData and in the case of chests, the adjcacent chest check
+ */
+ public void updateContainingBlockInfo() {
+ super.updateContainingBlockInfo();
+ this.adjacentChestChecked = false;
+ }
+
+ private void func_90009_a(TileEntityChest par1TileEntityChest, int par2) {
+ if (par1TileEntityChest.isInvalid()) {
+ this.adjacentChestChecked = false;
+ } else if (this.adjacentChestChecked) {
+ switch (par2) {
+ case 0:
+ if (this.adjacentChestZPosition != par1TileEntityChest) {
+ this.adjacentChestChecked = false;
+ }
+
+ break;
+
+ case 1:
+ if (this.adjacentChestXNeg != par1TileEntityChest) {
+ this.adjacentChestChecked = false;
+ }
+
+ break;
+
+ case 2:
+ if (this.adjacentChestZNeg != par1TileEntityChest) {
+ this.adjacentChestChecked = false;
+ }
+
+ break;
+
+ case 3:
+ if (this.adjacentChestXPos != par1TileEntityChest) {
+ this.adjacentChestChecked = false;
+ }
+ }
+ }
+ }
+
+ /**
+ * Performs the check for adjacent chests to determine if this chest is double
+ * or not.
+ */
+ public void checkForAdjacentChests() {
+ if (!this.adjacentChestChecked) {
+ this.adjacentChestChecked = true;
+ this.adjacentChestZNeg = null;
+ this.adjacentChestXPos = null;
+ this.adjacentChestXNeg = null;
+ this.adjacentChestZPosition = null;
+
+ if (this.func_94044_a(this.xCoord - 1, this.yCoord, this.zCoord)) {
+ this.adjacentChestXNeg = (TileEntityChest) this.worldObj.getBlockTileEntity(this.xCoord - 1,
+ this.yCoord, this.zCoord);
+ }
+
+ if (this.func_94044_a(this.xCoord + 1, this.yCoord, this.zCoord)) {
+ this.adjacentChestXPos = (TileEntityChest) this.worldObj.getBlockTileEntity(this.xCoord + 1,
+ this.yCoord, this.zCoord);
+ }
+
+ if (this.func_94044_a(this.xCoord, this.yCoord, this.zCoord - 1)) {
+ this.adjacentChestZNeg = (TileEntityChest) this.worldObj.getBlockTileEntity(this.xCoord, this.yCoord,
+ this.zCoord - 1);
+ }
+
+ if (this.func_94044_a(this.xCoord, this.yCoord, this.zCoord + 1)) {
+ this.adjacentChestZPosition = (TileEntityChest) this.worldObj.getBlockTileEntity(this.xCoord,
+ this.yCoord, this.zCoord + 1);
+ }
+
+ if (this.adjacentChestZNeg != null) {
+ this.adjacentChestZNeg.func_90009_a(this, 0);
+ }
+
+ if (this.adjacentChestZPosition != null) {
+ this.adjacentChestZPosition.func_90009_a(this, 2);
+ }
+
+ if (this.adjacentChestXPos != null) {
+ this.adjacentChestXPos.func_90009_a(this, 1);
+ }
+
+ if (this.adjacentChestXNeg != null) {
+ this.adjacentChestXNeg.func_90009_a(this, 3);
+ }
+ }
+ }
+
+ private boolean func_94044_a(int par1, int par2, int par3) {
+ Block var4 = Block.blocksList[this.worldObj.getBlockId(par1, par2, par3)];
+ return var4 != null && var4 instanceof BlockChest ? ((BlockChest) var4).isTrapped == this.func_98041_l()
+ : false;
+ }
+
+ /**
+ * Allows the entity to update its state. Overridden in most subclasses, e.g.
+ * the mob spawner uses this to count ticks and creates a new spawn inside its
+ * implementation.
+ */
+ public void updateEntity() {
+ super.updateEntity();
+ this.checkForAdjacentChests();
+ ++this.ticksSinceSync;
+ float var1;
+
+ if (!this.worldObj.isRemote && this.numUsingPlayers != 0
+ && (this.ticksSinceSync + this.xCoord + this.yCoord + this.zCoord) % 200 == 0) {
+ this.numUsingPlayers = 0;
+ var1 = 5.0F;
+ List var2 = this.worldObj.getEntitiesWithinAABB(EntityPlayer.class,
+ AxisAlignedBB.getAABBPool().getAABB((double) ((float) this.xCoord - var1),
+ (double) ((float) this.yCoord - var1), (double) ((float) this.zCoord - var1),
+ (double) ((float) (this.xCoord + 1) + var1), (double) ((float) (this.yCoord + 1) + var1),
+ (double) ((float) (this.zCoord + 1) + var1)));
+ Iterator var3 = var2.iterator();
+
+ while (var3.hasNext()) {
+ EntityPlayer var4 = (EntityPlayer) var3.next();
+
+ if (var4.openContainer instanceof ContainerChest) {
+ IInventory var5 = ((ContainerChest) var4.openContainer).getLowerChestInventory();
+
+ if (var5 == this || var5 instanceof InventoryLargeChest
+ && ((InventoryLargeChest) var5).isPartOfLargeChest(this)) {
+ ++this.numUsingPlayers;
+ }
+ }
+ }
+ }
+
+ this.prevLidAngle = this.lidAngle;
+ var1 = 0.1F;
+ double var11;
+
+ if (this.numUsingPlayers > 0 && this.lidAngle == 0.0F && this.adjacentChestZNeg == null
+ && this.adjacentChestXNeg == null) {
+ double var8 = (double) this.xCoord + 0.5D;
+ var11 = (double) this.zCoord + 0.5D;
+
+ if (this.adjacentChestZPosition != null) {
+ var11 += 0.5D;
+ }
+
+ if (this.adjacentChestXPos != null) {
+ var8 += 0.5D;
+ }
+
+ this.worldObj.playSoundEffect(var8, (double) this.yCoord + 0.5D, var11, "random.chestopen", 0.5F,
+ this.worldObj.rand.nextFloat() * 0.1F + 0.9F);
+ }
+
+ if (this.numUsingPlayers == 0 && this.lidAngle > 0.0F || this.numUsingPlayers > 0 && this.lidAngle < 1.0F) {
+ float var9 = this.lidAngle;
+
+ if (this.numUsingPlayers > 0) {
+ this.lidAngle += var1;
+ } else {
+ this.lidAngle -= var1;
+ }
+
+ if (this.lidAngle > 1.0F) {
+ this.lidAngle = 1.0F;
+ }
+
+ float var10 = 0.5F;
+
+ if (this.lidAngle < var10 && var9 >= var10 && this.adjacentChestZNeg == null
+ && this.adjacentChestXNeg == null) {
+ var11 = (double) this.xCoord + 0.5D;
+ double var6 = (double) this.zCoord + 0.5D;
+
+ if (this.adjacentChestZPosition != null) {
+ var6 += 0.5D;
+ }
+
+ if (this.adjacentChestXPos != null) {
+ var11 += 0.5D;
+ }
+
+ this.worldObj.playSoundEffect(var11, (double) this.yCoord + 0.5D, var6, "random.chestclosed", 0.5F,
+ this.worldObj.rand.nextFloat() * 0.1F + 0.9F);
+ }
+
+ if (this.lidAngle < 0.0F) {
+ this.lidAngle = 0.0F;
+ }
+ }
+ }
+
+ /**
+ * Called when a client event is received with the event number and argument,
+ * see World.sendClientEvent
+ */
+ public boolean receiveClientEvent(int par1, int par2) {
+ if (par1 == 1) {
+ this.numUsingPlayers = par2;
+ return true;
+ } else {
+ return super.receiveClientEvent(par1, par2);
+ }
+ }
+
+ public void openChest() {
+ if (this.numUsingPlayers < 0) {
+ this.numUsingPlayers = 0;
+ }
+
+ ++this.numUsingPlayers;
+ this.worldObj.addBlockEvent(this.xCoord, this.yCoord, this.zCoord, this.getBlockType().blockID, 1,
+ this.numUsingPlayers);
+ this.worldObj.notifyBlocksOfNeighborChange(this.xCoord, this.yCoord, this.zCoord, this.getBlockType().blockID);
+ this.worldObj.notifyBlocksOfNeighborChange(this.xCoord, this.yCoord - 1, this.zCoord,
+ this.getBlockType().blockID);
+ }
+
+ public void closeChest() {
+ if (this.getBlockType() != null && this.getBlockType() instanceof BlockChest) {
+ --this.numUsingPlayers;
+ this.worldObj.addBlockEvent(this.xCoord, this.yCoord, this.zCoord, this.getBlockType().blockID, 1,
+ this.numUsingPlayers);
+ this.worldObj.notifyBlocksOfNeighborChange(this.xCoord, this.yCoord, this.zCoord,
+ this.getBlockType().blockID);
+ this.worldObj.notifyBlocksOfNeighborChange(this.xCoord, this.yCoord - 1, this.zCoord,
+ this.getBlockType().blockID);
+ }
+ }
+
+ /**
+ * Returns true if automation is allowed to insert the given stack (ignoring
+ * stack size) into the given slot.
+ */
+ public boolean isStackValidForSlot(int par1, ItemStack par2ItemStack) {
+ return true;
+ }
+
+ /**
+ * invalidates a tile entity
+ */
+ public void invalidate() {
+ super.invalidate();
+ this.updateContainingBlockInfo();
+ this.checkForAdjacentChests();
+ }
+
+ public int func_98041_l() {
+ if (this.field_94046_i == -1) {
+ if (this.worldObj == null || !(this.getBlockType() instanceof BlockChest)) {
+ return 0;
+ }
+
+ this.field_94046_i = ((BlockChest) this.getBlockType()).isTrapped;
+ }
+
+ return this.field_94046_i;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/TileEntityCommandBlock.java b/sp-server/src/main/java/net/minecraft/src/TileEntityCommandBlock.java
new file mode 100644
index 0000000..00a56f8
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/TileEntityCommandBlock.java
@@ -0,0 +1,117 @@
+package net.minecraft.src;
+
+import net.minecraft.server.MinecraftServer;
+
+public class TileEntityCommandBlock extends TileEntity implements ICommandSender {
+ private int succesCount = 0;
+
+ /** The command this block will execute when powered. */
+ private String command = "";
+
+ /** The name of command sender (usually username, but possibly "Rcon") */
+ private String commandSenderName = "@";
+
+ /**
+ * Sets the command this block will execute when powered.
+ */
+ public void setCommand(String par1Str) {
+ this.command = par1Str;
+ this.onInventoryChanged();
+ }
+
+ /**
+ * Execute the command, called when the command block is powered.
+ */
+ public int executeCommandOnPowered(World par1World) {
+ if (par1World.isRemote) {
+ return 0;
+ } else {
+ MinecraftServer var2 = MinecraftServer.getServer();
+
+ if (var2 != null && var2.isCommandBlockEnabled()) {
+ ICommandManager var3 = var2.getCommandManager();
+ return var3.executeCommand(this, this.command);
+ } else {
+ return 0;
+ }
+ }
+ }
+
+ /**
+ * Gets the name of this command sender (usually username, but possibly "Rcon")
+ */
+ public String getCommandSenderName() {
+ return this.commandSenderName;
+ }
+
+ /**
+ * Sets the name of the command sender
+ */
+ public void setCommandSenderName(String par1Str) {
+ this.commandSenderName = par1Str;
+ }
+
+ public void sendChatToPlayer(String par1Str) {
+ }
+
+ /**
+ * Returns true if the command sender is allowed to use the given command.
+ */
+ public boolean canCommandSenderUseCommand(int par1, String par2Str) {
+ return par1 <= 2;
+ }
+
+ /**
+ * Translates and formats the given string key with the given arguments.
+ */
+ public String translateString(String par1Str, Object... par2ArrayOfObj) {
+ return par1Str;
+ }
+
+ /**
+ * Writes a tile entity to NBT.
+ */
+ public void writeToNBT(NBTTagCompound par1NBTTagCompound) {
+ super.writeToNBT(par1NBTTagCompound);
+ par1NBTTagCompound.setString("Command", this.command);
+ par1NBTTagCompound.setInteger("SuccessCount", this.succesCount);
+ par1NBTTagCompound.setString("CustomName", this.commandSenderName);
+ }
+
+ /**
+ * Reads a tile entity from NBT.
+ */
+ public void readFromNBT(NBTTagCompound par1NBTTagCompound) {
+ super.readFromNBT(par1NBTTagCompound);
+ this.command = par1NBTTagCompound.getString("Command");
+ this.succesCount = par1NBTTagCompound.getInteger("SuccessCount");
+
+ if (par1NBTTagCompound.hasKey("CustomName")) {
+ this.commandSenderName = par1NBTTagCompound.getString("CustomName");
+ }
+ }
+
+ /**
+ * Return the position for this command sender.
+ */
+ public ChunkCoordinates getCommandSenderPosition() {
+ return new ChunkCoordinates(this.xCoord, this.yCoord, this.zCoord);
+ }
+
+ /**
+ * Overriden in a sign to provide the text.
+ */
+ public Packet getDescriptionPacket() {
+ NBTTagCompound var1 = new NBTTagCompound();
+ this.writeToNBT(var1);
+ return new Packet132TileEntityData(this.xCoord, this.yCoord, this.zCoord, 2, var1);
+ }
+
+ public int func_96103_d() {
+ return this.succesCount;
+ }
+
+ public void func_96102_a(int par1) {
+ this.succesCount = par1;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/TileEntityComparator.java b/sp-server/src/main/java/net/minecraft/src/TileEntityComparator.java
new file mode 100644
index 0000000..fb02bff
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/TileEntityComparator.java
@@ -0,0 +1,29 @@
+package net.minecraft.src;
+
+public class TileEntityComparator extends TileEntity {
+ private int field_96101_a = 0;
+
+ /**
+ * Writes a tile entity to NBT.
+ */
+ public void writeToNBT(NBTTagCompound par1NBTTagCompound) {
+ super.writeToNBT(par1NBTTagCompound);
+ par1NBTTagCompound.setInteger("OutputSignal", this.field_96101_a);
+ }
+
+ /**
+ * Reads a tile entity from NBT.
+ */
+ public void readFromNBT(NBTTagCompound par1NBTTagCompound) {
+ super.readFromNBT(par1NBTTagCompound);
+ this.field_96101_a = par1NBTTagCompound.getInteger("OutputSignal");
+ }
+
+ public int func_96100_a() {
+ return this.field_96101_a;
+ }
+
+ public void func_96099_a(int par1) {
+ this.field_96101_a = par1;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/TileEntityDaylightDetector.java b/sp-server/src/main/java/net/minecraft/src/TileEntityDaylightDetector.java
new file mode 100644
index 0000000..a5f06cf
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/TileEntityDaylightDetector.java
@@ -0,0 +1,19 @@
+package net.minecraft.src;
+
+public class TileEntityDaylightDetector extends TileEntity {
+ /**
+ * Allows the entity to update its state. Overridden in most subclasses, e.g.
+ * the mob spawner uses this to count ticks and creates a new spawn inside its
+ * implementation.
+ */
+ public void updateEntity() {
+ if (this.worldObj != null && !this.worldObj.isRemote && this.worldObj.getTotalWorldTime() % 20L == 0L) {
+ this.blockType = this.getBlockType();
+
+ if (this.blockType != null && this.blockType instanceof BlockDaylightDetector) {
+ ((BlockDaylightDetector) this.blockType).updateLightLevel(this.worldObj, this.xCoord, this.yCoord,
+ this.zCoord);
+ }
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/TileEntityDispenser.java b/sp-server/src/main/java/net/minecraft/src/TileEntityDispenser.java
new file mode 100644
index 0000000..ba2e29f
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/TileEntityDispenser.java
@@ -0,0 +1,207 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class TileEntityDispenser extends TileEntity implements IInventory {
+ private ItemStack[] dispenserContents = new ItemStack[9];
+
+ /**
+ * random number generator for instance. Used in random item stack selection.
+ */
+ private EaglercraftRandom dispenserRandom = new EaglercraftRandom();
+ protected String field_94050_c;
+
+ /**
+ * Returns the number of slots in the inventory.
+ */
+ public int getSizeInventory() {
+ return 9;
+ }
+
+ /**
+ * Returns the stack in slot i
+ */
+ public ItemStack getStackInSlot(int par1) {
+ return this.dispenserContents[par1];
+ }
+
+ /**
+ * Removes from an inventory slot (first arg) up to a specified number (second
+ * arg) of items and returns them in a new stack.
+ */
+ public ItemStack decrStackSize(int par1, int par2) {
+ if (this.dispenserContents[par1] != null) {
+ ItemStack var3;
+
+ if (this.dispenserContents[par1].stackSize <= par2) {
+ var3 = this.dispenserContents[par1];
+ this.dispenserContents[par1] = null;
+ this.onInventoryChanged();
+ return var3;
+ } else {
+ var3 = this.dispenserContents[par1].splitStack(par2);
+
+ if (this.dispenserContents[par1].stackSize == 0) {
+ this.dispenserContents[par1] = null;
+ }
+
+ this.onInventoryChanged();
+ return var3;
+ }
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * When some containers are closed they call this on each slot, then drop
+ * whatever it returns as an EntityItem - like when you close a workbench GUI.
+ */
+ public ItemStack getStackInSlotOnClosing(int par1) {
+ if (this.dispenserContents[par1] != null) {
+ ItemStack var2 = this.dispenserContents[par1];
+ this.dispenserContents[par1] = null;
+ return var2;
+ } else {
+ return null;
+ }
+ }
+
+ public int getRandomStackFromInventory() {
+ int var1 = -1;
+ int var2 = 1;
+
+ for (int var3 = 0; var3 < this.dispenserContents.length; ++var3) {
+ if (this.dispenserContents[var3] != null && this.dispenserRandom.nextInt(var2++) == 0) {
+ var1 = var3;
+ }
+ }
+
+ return var1;
+ }
+
+ /**
+ * Sets the given item stack to the specified slot in the inventory (can be
+ * crafting or armor sections).
+ */
+ public void setInventorySlotContents(int par1, ItemStack par2ItemStack) {
+ this.dispenserContents[par1] = par2ItemStack;
+
+ if (par2ItemStack != null && par2ItemStack.stackSize > this.getInventoryStackLimit()) {
+ par2ItemStack.stackSize = this.getInventoryStackLimit();
+ }
+
+ this.onInventoryChanged();
+ }
+
+ /**
+ * Add item stack in first available inventory slot
+ */
+ public int addItem(ItemStack par1ItemStack) {
+ for (int var2 = 0; var2 < this.dispenserContents.length; ++var2) {
+ if (this.dispenserContents[var2] == null || this.dispenserContents[var2].itemID == 0) {
+ this.setInventorySlotContents(var2, par1ItemStack);
+ return var2;
+ }
+ }
+
+ return -1;
+ }
+
+ /**
+ * Returns the name of the inventory.
+ */
+ public String getInvName() {
+ return this.isInvNameLocalized() ? this.field_94050_c : "container.dispenser";
+ }
+
+ public void func_94049_a(String par1Str) {
+ this.field_94050_c = par1Str;
+ }
+
+ /**
+ * If this returns false, the inventory name will be used as an unlocalized
+ * name, and translated into the player's language. Otherwise it will be used
+ * directly.
+ */
+ public boolean isInvNameLocalized() {
+ return this.field_94050_c != null;
+ }
+
+ /**
+ * Reads a tile entity from NBT.
+ */
+ public void readFromNBT(NBTTagCompound par1NBTTagCompound) {
+ super.readFromNBT(par1NBTTagCompound);
+ NBTTagList var2 = par1NBTTagCompound.getTagList("Items");
+ this.dispenserContents = new ItemStack[this.getSizeInventory()];
+
+ for (int var3 = 0; var3 < var2.tagCount(); ++var3) {
+ NBTTagCompound var4 = (NBTTagCompound) var2.tagAt(var3);
+ int var5 = var4.getByte("Slot") & 255;
+
+ if (var5 >= 0 && var5 < this.dispenserContents.length) {
+ this.dispenserContents[var5] = ItemStack.loadItemStackFromNBT(var4);
+ }
+ }
+
+ if (par1NBTTagCompound.hasKey("CustomName")) {
+ this.field_94050_c = par1NBTTagCompound.getString("CustomName");
+ }
+ }
+
+ /**
+ * Writes a tile entity to NBT.
+ */
+ public void writeToNBT(NBTTagCompound par1NBTTagCompound) {
+ super.writeToNBT(par1NBTTagCompound);
+ NBTTagList var2 = new NBTTagList();
+
+ for (int var3 = 0; var3 < this.dispenserContents.length; ++var3) {
+ if (this.dispenserContents[var3] != null) {
+ NBTTagCompound var4 = new NBTTagCompound();
+ var4.setByte("Slot", (byte) var3);
+ this.dispenserContents[var3].writeToNBT(var4);
+ var2.appendTag(var4);
+ }
+ }
+
+ par1NBTTagCompound.setTag("Items", var2);
+
+ if (this.isInvNameLocalized()) {
+ par1NBTTagCompound.setString("CustomName", this.field_94050_c);
+ }
+ }
+
+ /**
+ * Returns the maximum stack size for a inventory slot. Seems to always be 64,
+ * possibly will be extended. *Isn't this more of a set than a get?*
+ */
+ public int getInventoryStackLimit() {
+ return 64;
+ }
+
+ /**
+ * Do not make give this method the name canInteractWith because it clashes with
+ * Container
+ */
+ public boolean isUseableByPlayer(EntityPlayer par1EntityPlayer) {
+ return this.worldObj.getBlockTileEntity(this.xCoord, this.yCoord, this.zCoord) != this ? false
+ : par1EntityPlayer.getDistanceSq((double) this.xCoord + 0.5D, (double) this.yCoord + 0.5D,
+ (double) this.zCoord + 0.5D) <= 64.0D;
+ }
+
+ public void openChest() {
+ }
+
+ public void closeChest() {
+ }
+
+ /**
+ * Returns true if automation is allowed to insert the given stack (ignoring
+ * stack size) into the given slot.
+ */
+ public boolean isStackValidForSlot(int par1, ItemStack par2ItemStack) {
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/TileEntityDropper.java b/sp-server/src/main/java/net/minecraft/src/TileEntityDropper.java
new file mode 100644
index 0000000..7c802b2
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/TileEntityDropper.java
@@ -0,0 +1,10 @@
+package net.minecraft.src;
+
+public class TileEntityDropper extends TileEntityDispenser {
+ /**
+ * Returns the name of the inventory.
+ */
+ public String getInvName() {
+ return this.isInvNameLocalized() ? this.field_94050_c : "container.dropper";
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/TileEntityEnchantmentTable.java b/sp-server/src/main/java/net/minecraft/src/TileEntityEnchantmentTable.java
new file mode 100644
index 0000000..9634097
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/TileEntityEnchantmentTable.java
@@ -0,0 +1,144 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class TileEntityEnchantmentTable extends TileEntity {
+ /** Used by the render to make the book 'bounce' */
+ public int tickCount;
+
+ /** Value used for determining how the page flip should look. */
+ public float pageFlip;
+
+ /** The last tick's pageFlip value. */
+ public float pageFlipPrev;
+ public float field_70373_d;
+ public float field_70374_e;
+
+ /** The amount that the book is open. */
+ public float bookSpread;
+
+ /** The amount that the book was open last tick. */
+ public float bookSpreadPrev;
+ public float bookRotation2;
+ public float bookRotationPrev;
+ public float bookRotation;
+ private static EaglercraftRandom rand = new EaglercraftRandom();
+ private String field_94136_s;
+
+ /**
+ * Writes a tile entity to NBT.
+ */
+ public void writeToNBT(NBTTagCompound par1NBTTagCompound) {
+ super.writeToNBT(par1NBTTagCompound);
+
+ if (this.func_94135_b()) {
+ par1NBTTagCompound.setString("CustomName", this.field_94136_s);
+ }
+ }
+
+ /**
+ * Reads a tile entity from NBT.
+ */
+ public void readFromNBT(NBTTagCompound par1NBTTagCompound) {
+ super.readFromNBT(par1NBTTagCompound);
+
+ if (par1NBTTagCompound.hasKey("CustomName")) {
+ this.field_94136_s = par1NBTTagCompound.getString("CustomName");
+ }
+ }
+
+ /**
+ * Allows the entity to update its state. Overridden in most subclasses, e.g.
+ * the mob spawner uses this to count ticks and creates a new spawn inside its
+ * implementation.
+ */
+ public void updateEntity() {
+ super.updateEntity();
+ this.bookSpreadPrev = this.bookSpread;
+ this.bookRotationPrev = this.bookRotation2;
+ EntityPlayer var1 = this.worldObj.getClosestPlayer((double) ((float) this.xCoord + 0.5F),
+ (double) ((float) this.yCoord + 0.5F), (double) ((float) this.zCoord + 0.5F), 3.0D);
+
+ if (var1 != null) {
+ double var2 = var1.posX - (double) ((float) this.xCoord + 0.5F);
+ double var4 = var1.posZ - (double) ((float) this.zCoord + 0.5F);
+ this.bookRotation = (float) Math.atan2(var4, var2);
+ this.bookSpread += 0.1F;
+
+ if (this.bookSpread < 0.5F || rand.nextInt(40) == 0) {
+ float var6 = this.field_70373_d;
+
+ do {
+ this.field_70373_d += (float) (rand.nextInt(4) - rand.nextInt(4));
+ } while (var6 == this.field_70373_d);
+ }
+ } else {
+ this.bookRotation += 0.02F;
+ this.bookSpread -= 0.1F;
+ }
+
+ while (this.bookRotation2 >= (float) Math.PI) {
+ this.bookRotation2 -= ((float) Math.PI * 2F);
+ }
+
+ while (this.bookRotation2 < -(float) Math.PI) {
+ this.bookRotation2 += ((float) Math.PI * 2F);
+ }
+
+ while (this.bookRotation >= (float) Math.PI) {
+ this.bookRotation -= ((float) Math.PI * 2F);
+ }
+
+ while (this.bookRotation < -(float) Math.PI) {
+ this.bookRotation += ((float) Math.PI * 2F);
+ }
+
+ float var7;
+
+ for (var7 = this.bookRotation - this.bookRotation2; var7 >= (float) Math.PI; var7 -= ((float) Math.PI * 2F)) {
+ ;
+ }
+
+ while (var7 < -(float) Math.PI) {
+ var7 += ((float) Math.PI * 2F);
+ }
+
+ this.bookRotation2 += var7 * 0.4F;
+
+ if (this.bookSpread < 0.0F) {
+ this.bookSpread = 0.0F;
+ }
+
+ if (this.bookSpread > 1.0F) {
+ this.bookSpread = 1.0F;
+ }
+
+ ++this.tickCount;
+ this.pageFlipPrev = this.pageFlip;
+ float var3 = (this.field_70373_d - this.pageFlip) * 0.4F;
+ float var8 = 0.2F;
+
+ if (var3 < -var8) {
+ var3 = -var8;
+ }
+
+ if (var3 > var8) {
+ var3 = var8;
+ }
+
+ this.field_70374_e += (var3 - this.field_70374_e) * 0.9F;
+ this.pageFlip += this.field_70374_e;
+ }
+
+ public String func_94133_a() {
+ return this.func_94135_b() ? this.field_94136_s : "container.enchant";
+ }
+
+ public boolean func_94135_b() {
+ return this.field_94136_s != null && this.field_94136_s.length() > 0;
+ }
+
+ public void func_94134_a(String par1Str) {
+ this.field_94136_s = par1Str;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/TileEntityEndPortal.java b/sp-server/src/main/java/net/minecraft/src/TileEntityEndPortal.java
new file mode 100644
index 0000000..64b43cc
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/TileEntityEndPortal.java
@@ -0,0 +1,4 @@
+package net.minecraft.src;
+
+public class TileEntityEndPortal extends TileEntity {
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/TileEntityEnderChest.java b/sp-server/src/main/java/net/minecraft/src/TileEntityEnderChest.java
new file mode 100644
index 0000000..1fed3eb
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/TileEntityEnderChest.java
@@ -0,0 +1,106 @@
+package net.minecraft.src;
+
+public class TileEntityEnderChest extends TileEntity {
+ /** The current angle of the chest lid (between 0 and 1) */
+ public float lidAngle;
+
+ /** The angle of the chest lid last tick */
+ public float prevLidAngle;
+
+ /** The number of players currently using this ender chest. */
+ public int numUsingPlayers;
+
+ /** Server sync counter (once per 20 ticks) */
+ private int ticksSinceSync;
+
+ /**
+ * Allows the entity to update its state. Overridden in most subclasses, e.g.
+ * the mob spawner uses this to count ticks and creates a new spawn inside its
+ * implementation.
+ */
+ public void updateEntity() {
+ super.updateEntity();
+
+ if (++this.ticksSinceSync % 20 * 4 == 0) {
+ this.worldObj.addBlockEvent(this.xCoord, this.yCoord, this.zCoord, Block.enderChest.blockID, 1,
+ this.numUsingPlayers);
+ }
+
+ this.prevLidAngle = this.lidAngle;
+ float var1 = 0.1F;
+ double var4;
+
+ if (this.numUsingPlayers > 0 && this.lidAngle == 0.0F) {
+ double var2 = (double) this.xCoord + 0.5D;
+ var4 = (double) this.zCoord + 0.5D;
+ this.worldObj.playSoundEffect(var2, (double) this.yCoord + 0.5D, var4, "random.chestopen", 0.5F,
+ this.worldObj.rand.nextFloat() * 0.1F + 0.9F);
+ }
+
+ if (this.numUsingPlayers == 0 && this.lidAngle > 0.0F || this.numUsingPlayers > 0 && this.lidAngle < 1.0F) {
+ float var8 = this.lidAngle;
+
+ if (this.numUsingPlayers > 0) {
+ this.lidAngle += var1;
+ } else {
+ this.lidAngle -= var1;
+ }
+
+ if (this.lidAngle > 1.0F) {
+ this.lidAngle = 1.0F;
+ }
+
+ float var3 = 0.5F;
+
+ if (this.lidAngle < var3 && var8 >= var3) {
+ var4 = (double) this.xCoord + 0.5D;
+ double var6 = (double) this.zCoord + 0.5D;
+ this.worldObj.playSoundEffect(var4, (double) this.yCoord + 0.5D, var6, "random.chestclosed", 0.5F,
+ this.worldObj.rand.nextFloat() * 0.1F + 0.9F);
+ }
+
+ if (this.lidAngle < 0.0F) {
+ this.lidAngle = 0.0F;
+ }
+ }
+ }
+
+ /**
+ * Called when a client event is received with the event number and argument,
+ * see World.sendClientEvent
+ */
+ public boolean receiveClientEvent(int par1, int par2) {
+ if (par1 == 1) {
+ this.numUsingPlayers = par2;
+ return true;
+ } else {
+ return super.receiveClientEvent(par1, par2);
+ }
+ }
+
+ /**
+ * invalidates a tile entity
+ */
+ public void invalidate() {
+ this.updateContainingBlockInfo();
+ super.invalidate();
+ }
+
+ public void openChest() {
+ ++this.numUsingPlayers;
+ this.worldObj.addBlockEvent(this.xCoord, this.yCoord, this.zCoord, Block.enderChest.blockID, 1,
+ this.numUsingPlayers);
+ }
+
+ public void closeChest() {
+ --this.numUsingPlayers;
+ this.worldObj.addBlockEvent(this.xCoord, this.yCoord, this.zCoord, Block.enderChest.blockID, 1,
+ this.numUsingPlayers);
+ }
+
+ public boolean isUseableByPlayer(EntityPlayer par1EntityPlayer) {
+ return this.worldObj.getBlockTileEntity(this.xCoord, this.yCoord, this.zCoord) != this ? false
+ : par1EntityPlayer.getDistanceSq((double) this.xCoord + 0.5D, (double) this.yCoord + 0.5D,
+ (double) this.zCoord + 0.5D) <= 64.0D;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/TileEntityFurnace.java b/sp-server/src/main/java/net/minecraft/src/TileEntityFurnace.java
new file mode 100644
index 0000000..f8c1d08
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/TileEntityFurnace.java
@@ -0,0 +1,362 @@
+package net.minecraft.src;
+
+public class TileEntityFurnace extends TileEntity implements ISidedInventory {
+ private static final int[] field_102010_d = new int[] { 0 };
+ private static final int[] field_102011_e = new int[] { 2, 1 };
+ private static final int[] field_102009_f = new int[] { 1 };
+
+ /**
+ * The ItemStacks that hold the items currently being used in the furnace
+ */
+ private ItemStack[] furnaceItemStacks = new ItemStack[3];
+
+ /** The number of ticks that the furnace will keep burning */
+ public int furnaceBurnTime = 0;
+
+ /**
+ * The number of ticks that a fresh copy of the currently-burning item would
+ * keep the furnace burning for
+ */
+ public int currentItemBurnTime = 0;
+
+ /** The number of ticks that the current item has been cooking for */
+ public int furnaceCookTime = 0;
+ private String field_94130_e;
+
+ /**
+ * Returns the number of slots in the inventory.
+ */
+ public int getSizeInventory() {
+ return this.furnaceItemStacks.length;
+ }
+
+ /**
+ * Returns the stack in slot i
+ */
+ public ItemStack getStackInSlot(int par1) {
+ return this.furnaceItemStacks[par1];
+ }
+
+ /**
+ * Removes from an inventory slot (first arg) up to a specified number (second
+ * arg) of items and returns them in a new stack.
+ */
+ public ItemStack decrStackSize(int par1, int par2) {
+ if (this.furnaceItemStacks[par1] != null) {
+ ItemStack var3;
+
+ if (this.furnaceItemStacks[par1].stackSize <= par2) {
+ var3 = this.furnaceItemStacks[par1];
+ this.furnaceItemStacks[par1] = null;
+ return var3;
+ } else {
+ var3 = this.furnaceItemStacks[par1].splitStack(par2);
+
+ if (this.furnaceItemStacks[par1].stackSize == 0) {
+ this.furnaceItemStacks[par1] = null;
+ }
+
+ return var3;
+ }
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * When some containers are closed they call this on each slot, then drop
+ * whatever it returns as an EntityItem - like when you close a workbench GUI.
+ */
+ public ItemStack getStackInSlotOnClosing(int par1) {
+ if (this.furnaceItemStacks[par1] != null) {
+ ItemStack var2 = this.furnaceItemStacks[par1];
+ this.furnaceItemStacks[par1] = null;
+ return var2;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Sets the given item stack to the specified slot in the inventory (can be
+ * crafting or armor sections).
+ */
+ public void setInventorySlotContents(int par1, ItemStack par2ItemStack) {
+ this.furnaceItemStacks[par1] = par2ItemStack;
+
+ if (par2ItemStack != null && par2ItemStack.stackSize > this.getInventoryStackLimit()) {
+ par2ItemStack.stackSize = this.getInventoryStackLimit();
+ }
+ }
+
+ /**
+ * Returns the name of the inventory.
+ */
+ public String getInvName() {
+ return this.isInvNameLocalized() ? this.field_94130_e : "container.furnace";
+ }
+
+ /**
+ * If this returns false, the inventory name will be used as an unlocalized
+ * name, and translated into the player's language. Otherwise it will be used
+ * directly.
+ */
+ public boolean isInvNameLocalized() {
+ return this.field_94130_e != null && this.field_94130_e.length() > 0;
+ }
+
+ public void func_94129_a(String par1Str) {
+ this.field_94130_e = par1Str;
+ }
+
+ /**
+ * Reads a tile entity from NBT.
+ */
+ public void readFromNBT(NBTTagCompound par1NBTTagCompound) {
+ super.readFromNBT(par1NBTTagCompound);
+ NBTTagList var2 = par1NBTTagCompound.getTagList("Items");
+ this.furnaceItemStacks = new ItemStack[this.getSizeInventory()];
+
+ for (int var3 = 0; var3 < var2.tagCount(); ++var3) {
+ NBTTagCompound var4 = (NBTTagCompound) var2.tagAt(var3);
+ byte var5 = var4.getByte("Slot");
+
+ if (var5 >= 0 && var5 < this.furnaceItemStacks.length) {
+ this.furnaceItemStacks[var5] = ItemStack.loadItemStackFromNBT(var4);
+ }
+ }
+
+ this.furnaceBurnTime = par1NBTTagCompound.getShort("BurnTime");
+ this.furnaceCookTime = par1NBTTagCompound.getShort("CookTime");
+ this.currentItemBurnTime = getItemBurnTime(this.furnaceItemStacks[1]);
+
+ if (par1NBTTagCompound.hasKey("CustomName")) {
+ this.field_94130_e = par1NBTTagCompound.getString("CustomName");
+ }
+ }
+
+ /**
+ * Writes a tile entity to NBT.
+ */
+ public void writeToNBT(NBTTagCompound par1NBTTagCompound) {
+ super.writeToNBT(par1NBTTagCompound);
+ par1NBTTagCompound.setShort("BurnTime", (short) this.furnaceBurnTime);
+ par1NBTTagCompound.setShort("CookTime", (short) this.furnaceCookTime);
+ NBTTagList var2 = new NBTTagList();
+
+ for (int var3 = 0; var3 < this.furnaceItemStacks.length; ++var3) {
+ if (this.furnaceItemStacks[var3] != null) {
+ NBTTagCompound var4 = new NBTTagCompound();
+ var4.setByte("Slot", (byte) var3);
+ this.furnaceItemStacks[var3].writeToNBT(var4);
+ var2.appendTag(var4);
+ }
+ }
+
+ par1NBTTagCompound.setTag("Items", var2);
+
+ if (this.isInvNameLocalized()) {
+ par1NBTTagCompound.setString("CustomName", this.field_94130_e);
+ }
+ }
+
+ /**
+ * Returns the maximum stack size for a inventory slot. Seems to always be 64,
+ * possibly will be extended. *Isn't this more of a set than a get?*
+ */
+ public int getInventoryStackLimit() {
+ return 64;
+ }
+
+ /**
+ * Returns true if the furnace is currently burning
+ */
+ public boolean isBurning() {
+ return this.furnaceBurnTime > 0;
+ }
+
+ /**
+ * Allows the entity to update its state. Overridden in most subclasses, e.g.
+ * the mob spawner uses this to count ticks and creates a new spawn inside its
+ * implementation.
+ */
+ public void updateEntity() {
+ boolean var1 = this.furnaceBurnTime > 0;
+ boolean var2 = false;
+
+ if (this.furnaceBurnTime > 0) {
+ --this.furnaceBurnTime;
+ }
+
+ if (!this.worldObj.isRemote) {
+ if (this.furnaceBurnTime == 0 && this.canSmelt()) {
+ this.currentItemBurnTime = this.furnaceBurnTime = getItemBurnTime(this.furnaceItemStacks[1]);
+
+ if (this.furnaceBurnTime > 0) {
+ var2 = true;
+
+ if (this.furnaceItemStacks[1] != null) {
+ --this.furnaceItemStacks[1].stackSize;
+
+ if (this.furnaceItemStacks[1].stackSize == 0) {
+ Item var3 = this.furnaceItemStacks[1].getItem().getContainerItem();
+ this.furnaceItemStacks[1] = var3 != null ? new ItemStack(var3) : null;
+ }
+ }
+ }
+ }
+
+ if (this.isBurning() && this.canSmelt()) {
+ ++this.furnaceCookTime;
+
+ if (this.furnaceCookTime == 200) {
+ this.furnaceCookTime = 0;
+ this.smeltItem();
+ var2 = true;
+ }
+ } else {
+ this.furnaceCookTime = 0;
+ }
+
+ if (var1 != this.furnaceBurnTime > 0) {
+ var2 = true;
+ BlockFurnace.updateFurnaceBlockState(this.furnaceBurnTime > 0, this.worldObj, this.xCoord, this.yCoord,
+ this.zCoord);
+ }
+ }
+
+ if (var2) {
+ this.onInventoryChanged();
+ }
+ }
+
+ /**
+ * Returns true if the furnace can smelt an item, i.e. has a source item,
+ * destination stack isn't full, etc.
+ */
+ private boolean canSmelt() {
+ if (this.furnaceItemStacks[0] == null) {
+ return false;
+ } else {
+ ItemStack var1 = FurnaceRecipes.smelting().getSmeltingResult(this.furnaceItemStacks[0].getItem().itemID);
+ return var1 == null ? false
+ : (this.furnaceItemStacks[2] == null ? true
+ : (!this.furnaceItemStacks[2].isItemEqual(var1) ? false
+ : (this.furnaceItemStacks[2].stackSize < this.getInventoryStackLimit()
+ && this.furnaceItemStacks[2].stackSize < this.furnaceItemStacks[2]
+ .getMaxStackSize() ? true
+ : this.furnaceItemStacks[2].stackSize < var1
+ .getMaxStackSize())));
+ }
+ }
+
+ /**
+ * Turn one item from the furnace source stack into the appropriate smelted item
+ * in the furnace result stack
+ */
+ public void smeltItem() {
+ if (this.canSmelt()) {
+ ItemStack var1 = FurnaceRecipes.smelting().getSmeltingResult(this.furnaceItemStacks[0].getItem().itemID);
+
+ if (this.furnaceItemStacks[2] == null) {
+ this.furnaceItemStacks[2] = var1.copy();
+ } else if (this.furnaceItemStacks[2].itemID == var1.itemID) {
+ ++this.furnaceItemStacks[2].stackSize;
+ }
+
+ --this.furnaceItemStacks[0].stackSize;
+
+ if (this.furnaceItemStacks[0].stackSize <= 0) {
+ this.furnaceItemStacks[0] = null;
+ }
+ }
+ }
+
+ /**
+ * Returns the number of ticks that the supplied fuel item will keep the furnace
+ * burning, or 0 if the item isn't fuel
+ */
+ public static int getItemBurnTime(ItemStack par0ItemStack) {
+ if (par0ItemStack == null) {
+ return 0;
+ } else {
+ int var1 = par0ItemStack.getItem().itemID;
+ Item var2 = par0ItemStack.getItem();
+
+ if (var1 < 256 && Block.blocksList[var1] != null) {
+ Block var3 = Block.blocksList[var1];
+
+ if (var3 == Block.woodSingleSlab) {
+ return 150;
+ }
+
+ if (var3.blockMaterial == Material.wood) {
+ return 300;
+ }
+ }
+
+ return var2 instanceof ItemTool && ((ItemTool) var2).getToolMaterialName().equals("WOOD") ? 200
+ : (var2 instanceof ItemSword && ((ItemSword) var2).getToolMaterialName().equals("WOOD") ? 200
+ : (var2 instanceof ItemHoe && ((ItemHoe) var2).getMaterialName().equals("WOOD") ? 200
+ : (var1 == Item.stick.itemID ? 100
+ : (var1 == Item.coal.itemID ? 1600
+ : (var1 == Item.bucketLava.itemID ? 20000
+ : (var1 == Block.sapling.blockID ? 100
+ : (var1 == Item.blazeRod.itemID ? 2400 : 0)))))));
+ }
+ }
+
+ /**
+ * Return true if item is a fuel source (getItemBurnTime() > 0).
+ */
+ public static boolean isItemFuel(ItemStack par0ItemStack) {
+ return getItemBurnTime(par0ItemStack) > 0;
+ }
+
+ /**
+ * Do not make give this method the name canInteractWith because it clashes with
+ * Container
+ */
+ public boolean isUseableByPlayer(EntityPlayer par1EntityPlayer) {
+ return this.worldObj.getBlockTileEntity(this.xCoord, this.yCoord, this.zCoord) != this ? false
+ : par1EntityPlayer.getDistanceSq((double) this.xCoord + 0.5D, (double) this.yCoord + 0.5D,
+ (double) this.zCoord + 0.5D) <= 64.0D;
+ }
+
+ public void openChest() {
+ }
+
+ public void closeChest() {
+ }
+
+ /**
+ * Returns true if automation is allowed to insert the given stack (ignoring
+ * stack size) into the given slot.
+ */
+ public boolean isStackValidForSlot(int par1, ItemStack par2ItemStack) {
+ return par1 == 2 ? false : (par1 == 1 ? isItemFuel(par2ItemStack) : true);
+ }
+
+ /**
+ * param side
+ */
+ public int[] getSlotsForFace(int par1) {
+ return par1 == 0 ? field_102011_e : (par1 == 1 ? field_102010_d : field_102009_f);
+ }
+
+ /**
+ * Returns true if automation can insert the given item in the given slot from
+ * the given side. Args: Slot, item, side
+ */
+ public boolean canInsertItem(int par1, ItemStack par2ItemStack, int par3) {
+ return this.isStackValidForSlot(par1, par2ItemStack);
+ }
+
+ /**
+ * Returns true if automation can extract the given item in the given slot from
+ * the given side. Args: Slot, item, side
+ */
+ public boolean canExtractItem(int par1, ItemStack par2ItemStack, int par3) {
+ return par3 != 0 || par1 != 1 || par2ItemStack.itemID == Item.bucketEmpty.itemID;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/TileEntityHopper.java b/sp-server/src/main/java/net/minecraft/src/TileEntityHopper.java
new file mode 100644
index 0000000..c59607c
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/TileEntityHopper.java
@@ -0,0 +1,494 @@
+package net.minecraft.src;
+
+import java.util.List;
+
+public class TileEntityHopper extends TileEntity implements Hopper {
+ private ItemStack[] hopperItemStacks = new ItemStack[5];
+
+ /** The name that is displayed if the hopper was renamed */
+ private String inventoryName;
+ private int transferCooldown = -1;
+
+ /**
+ * Reads a tile entity from NBT.
+ */
+ public void readFromNBT(NBTTagCompound par1NBTTagCompound) {
+ super.readFromNBT(par1NBTTagCompound);
+ NBTTagList var2 = par1NBTTagCompound.getTagList("Items");
+ this.hopperItemStacks = new ItemStack[this.getSizeInventory()];
+
+ if (par1NBTTagCompound.hasKey("CustomName")) {
+ this.inventoryName = par1NBTTagCompound.getString("CustomName");
+ }
+
+ this.transferCooldown = par1NBTTagCompound.getInteger("TransferCooldown");
+
+ for (int var3 = 0; var3 < var2.tagCount(); ++var3) {
+ NBTTagCompound var4 = (NBTTagCompound) var2.tagAt(var3);
+ byte var5 = var4.getByte("Slot");
+
+ if (var5 >= 0 && var5 < this.hopperItemStacks.length) {
+ this.hopperItemStacks[var5] = ItemStack.loadItemStackFromNBT(var4);
+ }
+ }
+ }
+
+ /**
+ * Writes a tile entity to NBT.
+ */
+ public void writeToNBT(NBTTagCompound par1NBTTagCompound) {
+ super.writeToNBT(par1NBTTagCompound);
+ NBTTagList var2 = new NBTTagList();
+
+ for (int var3 = 0; var3 < this.hopperItemStacks.length; ++var3) {
+ if (this.hopperItemStacks[var3] != null) {
+ NBTTagCompound var4 = new NBTTagCompound();
+ var4.setByte("Slot", (byte) var3);
+ this.hopperItemStacks[var3].writeToNBT(var4);
+ var2.appendTag(var4);
+ }
+ }
+
+ par1NBTTagCompound.setTag("Items", var2);
+ par1NBTTagCompound.setInteger("TransferCooldown", this.transferCooldown);
+
+ if (this.isInvNameLocalized()) {
+ par1NBTTagCompound.setString("CustomName", this.inventoryName);
+ }
+ }
+
+ /**
+ * Called when an the contents of an Inventory change, usually
+ */
+ public void onInventoryChanged() {
+ super.onInventoryChanged();
+ }
+
+ /**
+ * Returns the number of slots in the inventory.
+ */
+ public int getSizeInventory() {
+ return this.hopperItemStacks.length;
+ }
+
+ /**
+ * Returns the stack in slot i
+ */
+ public ItemStack getStackInSlot(int par1) {
+ return this.hopperItemStacks[par1];
+ }
+
+ /**
+ * Removes from an inventory slot (first arg) up to a specified number (second
+ * arg) of items and returns them in a new stack.
+ */
+ public ItemStack decrStackSize(int par1, int par2) {
+ if (this.hopperItemStacks[par1] != null) {
+ ItemStack var3;
+
+ if (this.hopperItemStacks[par1].stackSize <= par2) {
+ var3 = this.hopperItemStacks[par1];
+ this.hopperItemStacks[par1] = null;
+ return var3;
+ } else {
+ var3 = this.hopperItemStacks[par1].splitStack(par2);
+
+ if (this.hopperItemStacks[par1].stackSize == 0) {
+ this.hopperItemStacks[par1] = null;
+ }
+
+ return var3;
+ }
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * When some containers are closed they call this on each slot, then drop
+ * whatever it returns as an EntityItem - like when you close a workbench GUI.
+ */
+ public ItemStack getStackInSlotOnClosing(int par1) {
+ if (this.hopperItemStacks[par1] != null) {
+ ItemStack var2 = this.hopperItemStacks[par1];
+ this.hopperItemStacks[par1] = null;
+ return var2;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Sets the given item stack to the specified slot in the inventory (can be
+ * crafting or armor sections).
+ */
+ public void setInventorySlotContents(int par1, ItemStack par2ItemStack) {
+ this.hopperItemStacks[par1] = par2ItemStack;
+
+ if (par2ItemStack != null && par2ItemStack.stackSize > this.getInventoryStackLimit()) {
+ par2ItemStack.stackSize = this.getInventoryStackLimit();
+ }
+ }
+
+ /**
+ * Returns the name of the inventory.
+ */
+ public String getInvName() {
+ return this.isInvNameLocalized() ? this.inventoryName : "container.hopper";
+ }
+
+ /**
+ * If this returns false, the inventory name will be used as an unlocalized
+ * name, and translated into the player's language. Otherwise it will be used
+ * directly.
+ */
+ public boolean isInvNameLocalized() {
+ return this.inventoryName != null && this.inventoryName.length() > 0;
+ }
+
+ public void setInventoryName(String par1Str) {
+ this.inventoryName = par1Str;
+ }
+
+ /**
+ * Returns the maximum stack size for a inventory slot. Seems to always be 64,
+ * possibly will be extended. *Isn't this more of a set than a get?*
+ */
+ public int getInventoryStackLimit() {
+ return 64;
+ }
+
+ /**
+ * Do not make give this method the name canInteractWith because it clashes with
+ * Container
+ */
+ public boolean isUseableByPlayer(EntityPlayer par1EntityPlayer) {
+ return this.worldObj.getBlockTileEntity(this.xCoord, this.yCoord, this.zCoord) != this ? false
+ : par1EntityPlayer.getDistanceSq((double) this.xCoord + 0.5D, (double) this.yCoord + 0.5D,
+ (double) this.zCoord + 0.5D) <= 64.0D;
+ }
+
+ public void openChest() {
+ }
+
+ public void closeChest() {
+ }
+
+ /**
+ * Returns true if automation is allowed to insert the given stack (ignoring
+ * stack size) into the given slot.
+ */
+ public boolean isStackValidForSlot(int par1, ItemStack par2ItemStack) {
+ return true;
+ }
+
+ /**
+ * Allows the entity to update its state. Overridden in most subclasses, e.g.
+ * the mob spawner uses this to count ticks and creates a new spawn inside its
+ * implementation.
+ */
+ public void updateEntity() {
+ if (this.worldObj != null && !this.worldObj.isRemote) {
+ --this.transferCooldown;
+
+ if (!this.isCoolingDown()) {
+ this.setTransferCooldown(0);
+ this.func_98045_j();
+ }
+ }
+ }
+
+ public boolean func_98045_j() {
+ if (this.worldObj != null && !this.worldObj.isRemote) {
+ if (!this.isCoolingDown() && BlockHopper.getIsBlockNotPoweredFromMetadata(this.getBlockMetadata())) {
+ boolean var1 = this.insertItemToInventory() | suckItemsIntoHopper(this);
+
+ if (var1) {
+ this.setTransferCooldown(8);
+ this.onInventoryChanged();
+ return true;
+ }
+ }
+
+ return false;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Inserts one item from the hopper into the inventory the hopper is pointing
+ * at.
+ */
+ private boolean insertItemToInventory() {
+ IInventory var1 = this.getOutputInventory();
+
+ if (var1 == null) {
+ return false;
+ } else {
+ for (int var2 = 0; var2 < this.getSizeInventory(); ++var2) {
+ if (this.getStackInSlot(var2) != null) {
+ ItemStack var3 = this.getStackInSlot(var2).copy();
+ ItemStack var4 = insertStack(var1, this.decrStackSize(var2, 1),
+ Facing.oppositeSide[BlockHopper.getDirectionFromMetadata(this.getBlockMetadata())]);
+
+ if (var4 == null || var4.stackSize == 0) {
+ var1.onInventoryChanged();
+ return true;
+ }
+
+ this.setInventorySlotContents(var2, var3);
+ }
+ }
+
+ return false;
+ }
+ }
+
+ /**
+ * Sucks one item into the given hopper from an inventory or EntityItem above
+ * it.
+ */
+ public static boolean suckItemsIntoHopper(Hopper par0Hopper) {
+ IInventory var1 = getInventoryAboveHopper(par0Hopper);
+
+ if (var1 != null) {
+ byte var2 = 0;
+
+ if (var1 instanceof ISidedInventory && var2 > -1) {
+ ISidedInventory var7 = (ISidedInventory) var1;
+ int[] var8 = var7.getSlotsForFace(var2);
+
+ for (int var5 = 0; var5 < var8.length; ++var5) {
+ if (func_102012_a(par0Hopper, var1, var8[var5], var2)) {
+ return true;
+ }
+ }
+ } else {
+ int var3 = var1.getSizeInventory();
+
+ for (int var4 = 0; var4 < var3; ++var4) {
+ if (func_102012_a(par0Hopper, var1, var4, var2)) {
+ return true;
+ }
+ }
+ }
+ } else {
+ EntityItem var6 = func_96119_a(par0Hopper.getWorldObj(), par0Hopper.getXPos(), par0Hopper.getYPos() + 1.0D,
+ par0Hopper.getZPos());
+
+ if (var6 != null) {
+ return func_96114_a(par0Hopper, var6);
+ }
+ }
+
+ return false;
+ }
+
+ private static boolean func_102012_a(Hopper par0Hopper, IInventory par1IInventory, int par2, int par3) {
+ ItemStack var4 = par1IInventory.getStackInSlot(par2);
+
+ if (var4 != null && canExtractItemFromInventory(par1IInventory, var4, par2, par3)) {
+ ItemStack var5 = var4.copy();
+ ItemStack var6 = insertStack(par0Hopper, par1IInventory.decrStackSize(par2, 1), -1);
+
+ if (var6 == null || var6.stackSize == 0) {
+ par1IInventory.onInventoryChanged();
+ return true;
+ }
+
+ par1IInventory.setInventorySlotContents(par2, var5);
+ }
+
+ return false;
+ }
+
+ public static boolean func_96114_a(IInventory par0IInventory, EntityItem par1EntityItem) {
+ boolean var2 = false;
+
+ if (par1EntityItem == null) {
+ return false;
+ } else {
+ ItemStack var3 = par1EntityItem.getEntityItem().copy();
+ ItemStack var4 = insertStack(par0IInventory, var3, -1);
+
+ if (var4 != null && var4.stackSize != 0) {
+ par1EntityItem.setEntityItemStack(var4);
+ } else {
+ var2 = true;
+ par1EntityItem.setDead();
+ }
+
+ return var2;
+ }
+ }
+
+ /**
+ * Inserts a stack into an inventory. Args: Inventory, stack, side. Returns
+ * leftover items.
+ */
+ public static ItemStack insertStack(IInventory par1IInventory, ItemStack par2ItemStack, int par3) {
+ if (par1IInventory instanceof ISidedInventory && par3 > -1) {
+ ISidedInventory var6 = (ISidedInventory) par1IInventory;
+ int[] var7 = var6.getSlotsForFace(par3);
+
+ for (int var5 = 0; var5 < var7.length && par2ItemStack != null && par2ItemStack.stackSize > 0; ++var5) {
+ par2ItemStack = func_102014_c(par1IInventory, par2ItemStack, var7[var5], par3);
+ }
+ } else {
+ int var3 = par1IInventory.getSizeInventory();
+
+ for (int var4 = 0; var4 < var3 && par2ItemStack != null && par2ItemStack.stackSize > 0; ++var4) {
+ par2ItemStack = func_102014_c(par1IInventory, par2ItemStack, var4, par3);
+ }
+ }
+
+ if (par2ItemStack != null && par2ItemStack.stackSize == 0) {
+ par2ItemStack = null;
+ }
+
+ return par2ItemStack;
+ }
+
+ private static boolean func_102015_a(IInventory par0IInventory, ItemStack par1ItemStack, int par2, int par3) {
+ return !par0IInventory.isStackValidForSlot(par2, par1ItemStack) ? false
+ : !(par0IInventory instanceof ISidedInventory)
+ || ((ISidedInventory) par0IInventory).canInsertItem(par2, par1ItemStack, par3);
+ }
+
+ private static boolean canExtractItemFromInventory(IInventory par0IInventory, ItemStack par1ItemStack, int par2,
+ int par3) {
+ return !(par0IInventory instanceof ISidedInventory)
+ || ((ISidedInventory) par0IInventory).canExtractItem(par2, par1ItemStack, par3);
+ }
+
+ private static ItemStack func_102014_c(IInventory par0IInventory, ItemStack par1ItemStack, int par2, int par3) {
+ ItemStack var4 = par0IInventory.getStackInSlot(par2);
+
+ if (func_102015_a(par0IInventory, par1ItemStack, par2, par3)) {
+ boolean var5 = false;
+
+ if (var4 == null) {
+ par0IInventory.setInventorySlotContents(par2, par1ItemStack);
+ par1ItemStack = null;
+ var5 = true;
+ } else if (areItemStacksEqualItem(var4, par1ItemStack)) {
+ int var6 = par1ItemStack.getMaxStackSize() - var4.stackSize;
+ int var7 = Math.min(par1ItemStack.stackSize, var6);
+ par1ItemStack.stackSize -= var7;
+ var4.stackSize += var7;
+ var5 = var7 > 0;
+ }
+
+ if (var5) {
+ if (par0IInventory instanceof TileEntityHopper) {
+ ((TileEntityHopper) par0IInventory).setTransferCooldown(8);
+ }
+
+ par0IInventory.onInventoryChanged();
+ }
+ }
+
+ return par1ItemStack;
+ }
+
+ /**
+ * Gets the inventory the hopper is pointing at.
+ */
+ private IInventory getOutputInventory() {
+ int var1 = BlockHopper.getDirectionFromMetadata(this.getBlockMetadata());
+ return getInventoryAtLocation(this.getWorldObj(), (double) (this.xCoord + Facing.offsetsXForSide[var1]),
+ (double) (this.yCoord + Facing.offsetsYForSide[var1]),
+ (double) (this.zCoord + Facing.offsetsZForSide[var1]));
+ }
+
+ /**
+ * Looks for anything, that can hold items (like chests, furnaces, etc.) one
+ * block above the given hopper.
+ */
+ public static IInventory getInventoryAboveHopper(Hopper par0Hopper) {
+ return getInventoryAtLocation(par0Hopper.getWorldObj(), par0Hopper.getXPos(), par0Hopper.getYPos() + 1.0D,
+ par0Hopper.getZPos());
+ }
+
+ public static EntityItem func_96119_a(World par0World, double par1, double par3, double par5) {
+ List var7 = par0World.selectEntitiesWithinAABB(EntityItem.class,
+ AxisAlignedBB.getAABBPool().getAABB(par1, par3, par5, par1 + 1.0D, par3 + 1.0D, par5 + 1.0D),
+ IEntitySelector.selectAnything);
+ return var7.size() > 0 ? (EntityItem) var7.get(0) : null;
+ }
+
+ /**
+ * Gets an inventory at the given location to extract items into or take items
+ * from. Can find either a tile entity or regular entity implementing
+ * IInventory.
+ */
+ public static IInventory getInventoryAtLocation(World par0World, double par1, double par3, double par5) {
+ IInventory var7 = null;
+ int var8 = MathHelper.floor_double(par1);
+ int var9 = MathHelper.floor_double(par3);
+ int var10 = MathHelper.floor_double(par5);
+ TileEntity var11 = par0World.getBlockTileEntity(var8, var9, var10);
+
+ if (var11 != null && var11 instanceof IInventory) {
+ var7 = (IInventory) var11;
+
+ if (var7 instanceof TileEntityChest) {
+ int var12 = par0World.getBlockId(var8, var9, var10);
+ Block var13 = Block.blocksList[var12];
+
+ if (var13 instanceof BlockChest) {
+ var7 = ((BlockChest) var13).getInventory(par0World, var8, var9, var10);
+ }
+ }
+ }
+
+ if (var7 == null) {
+ List var14 = par0World.getEntitiesWithinAABBExcludingEntity((Entity) null,
+ AxisAlignedBB.getAABBPool().getAABB(par1, par3, par5, par1 + 1.0D, par3 + 1.0D, par5 + 1.0D),
+ IEntitySelector.selectInventories);
+
+ if (var14 != null && var14.size() > 0) {
+ var7 = (IInventory) var14.get(par0World.rand.nextInt(var14.size()));
+ }
+ }
+
+ return var7;
+ }
+
+ private static boolean areItemStacksEqualItem(ItemStack par1ItemStack, ItemStack par2ItemStack) {
+ return par1ItemStack.itemID != par2ItemStack.itemID ? false
+ : (par1ItemStack.getItemDamage() != par2ItemStack.getItemDamage() ? false
+ : (par1ItemStack.stackSize > par1ItemStack.getMaxStackSize() ? false
+ : ItemStack.areItemStackTagsEqual(par1ItemStack, par2ItemStack)));
+ }
+
+ /**
+ * Gets the world X position for this hopper entity.
+ */
+ public double getXPos() {
+ return (double) this.xCoord;
+ }
+
+ /**
+ * Gets the world Y position for this hopper entity.
+ */
+ public double getYPos() {
+ return (double) this.yCoord;
+ }
+
+ /**
+ * Gets the world Z position for this hopper entity.
+ */
+ public double getZPos() {
+ return (double) this.zCoord;
+ }
+
+ public void setTransferCooldown(int par1) {
+ this.transferCooldown = par1;
+ }
+
+ public boolean isCoolingDown() {
+ return this.transferCooldown > 0;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/TileEntityMobSpawner.java b/sp-server/src/main/java/net/minecraft/src/TileEntityMobSpawner.java
new file mode 100644
index 0000000..dfdf0d1
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/TileEntityMobSpawner.java
@@ -0,0 +1,53 @@
+package net.minecraft.src;
+
+public class TileEntityMobSpawner extends TileEntity {
+ private final MobSpawnerBaseLogic field_98050_a = new TileEntityMobSpawnerLogic(this);
+
+ /**
+ * Reads a tile entity from NBT.
+ */
+ public void readFromNBT(NBTTagCompound par1NBTTagCompound) {
+ super.readFromNBT(par1NBTTagCompound);
+ this.field_98050_a.readFromNBT(par1NBTTagCompound);
+ }
+
+ /**
+ * Writes a tile entity to NBT.
+ */
+ public void writeToNBT(NBTTagCompound par1NBTTagCompound) {
+ super.writeToNBT(par1NBTTagCompound);
+ this.field_98050_a.writeToNBT(par1NBTTagCompound);
+ }
+
+ /**
+ * Allows the entity to update its state. Overridden in most subclasses, e.g.
+ * the mob spawner uses this to count ticks and creates a new spawn inside its
+ * implementation.
+ */
+ public void updateEntity() {
+ this.field_98050_a.updateSpawner();
+ super.updateEntity();
+ }
+
+ /**
+ * Overriden in a sign to provide the text.
+ */
+ public Packet getDescriptionPacket() {
+ NBTTagCompound var1 = new NBTTagCompound();
+ this.writeToNBT(var1);
+ var1.removeTag("SpawnPotentials");
+ return new Packet132TileEntityData(this.xCoord, this.yCoord, this.zCoord, 1, var1);
+ }
+
+ /**
+ * Called when a client event is received with the event number and argument,
+ * see World.sendClientEvent
+ */
+ public boolean receiveClientEvent(int par1, int par2) {
+ return this.field_98050_a.setDelayToMin(par1) ? true : super.receiveClientEvent(par1, par2);
+ }
+
+ public MobSpawnerBaseLogic func_98049_a() {
+ return this.field_98050_a;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/TileEntityMobSpawnerLogic.java b/sp-server/src/main/java/net/minecraft/src/TileEntityMobSpawnerLogic.java
new file mode 100644
index 0000000..7a32d1f
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/TileEntityMobSpawnerLogic.java
@@ -0,0 +1,40 @@
+package net.minecraft.src;
+
+class TileEntityMobSpawnerLogic extends MobSpawnerBaseLogic {
+ /** The mob spawner we deal with */
+ final TileEntityMobSpawner mobSpawnerEntity;
+
+ TileEntityMobSpawnerLogic(TileEntityMobSpawner par1TileEntityMobSpawner) {
+ this.mobSpawnerEntity = par1TileEntityMobSpawner;
+ }
+
+ public void func_98267_a(int par1) {
+ this.mobSpawnerEntity.worldObj.addBlockEvent(this.mobSpawnerEntity.xCoord, this.mobSpawnerEntity.yCoord,
+ this.mobSpawnerEntity.zCoord, Block.mobSpawner.blockID, par1, 0);
+ }
+
+ public World getSpawnerWorld() {
+ return this.mobSpawnerEntity.worldObj;
+ }
+
+ public int getSpawnerX() {
+ return this.mobSpawnerEntity.xCoord;
+ }
+
+ public int getSpawnerY() {
+ return this.mobSpawnerEntity.yCoord;
+ }
+
+ public int getSpawnerZ() {
+ return this.mobSpawnerEntity.zCoord;
+ }
+
+ public void setRandomMinecart(WeightedRandomMinecart par1WeightedRandomMinecart) {
+ super.setRandomMinecart(par1WeightedRandomMinecart);
+
+ if (this.getSpawnerWorld() != null) {
+ this.getSpawnerWorld().markBlockForUpdate(this.mobSpawnerEntity.xCoord, this.mobSpawnerEntity.yCoord,
+ this.mobSpawnerEntity.zCoord);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/TileEntityNote.java b/sp-server/src/main/java/net/minecraft/src/TileEntityNote.java
new file mode 100644
index 0000000..1e19519
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/TileEntityNote.java
@@ -0,0 +1,69 @@
+package net.minecraft.src;
+
+public class TileEntityNote extends TileEntity {
+ /** Note to play */
+ public byte note = 0;
+
+ /** stores the latest redstone state */
+ public boolean previousRedstoneState = false;
+
+ /**
+ * Writes a tile entity to NBT.
+ */
+ public void writeToNBT(NBTTagCompound par1NBTTagCompound) {
+ super.writeToNBT(par1NBTTagCompound);
+ par1NBTTagCompound.setByte("note", this.note);
+ }
+
+ /**
+ * Reads a tile entity from NBT.
+ */
+ public void readFromNBT(NBTTagCompound par1NBTTagCompound) {
+ super.readFromNBT(par1NBTTagCompound);
+ this.note = par1NBTTagCompound.getByte("note");
+
+ if (this.note < 0) {
+ this.note = 0;
+ }
+
+ if (this.note > 24) {
+ this.note = 24;
+ }
+ }
+
+ /**
+ * change pitch by -> (currentPitch + 1) % 25
+ */
+ public void changePitch() {
+ this.note = (byte) ((this.note + 1) % 25);
+ this.onInventoryChanged();
+ }
+
+ /**
+ * plays the stored note
+ */
+ public void triggerNote(World par1World, int par2, int par3, int par4) {
+ if (par1World.getBlockMaterial(par2, par3 + 1, par4) == Material.air) {
+ Material var5 = par1World.getBlockMaterial(par2, par3 - 1, par4);
+ byte var6 = 0;
+
+ if (var5 == Material.rock) {
+ var6 = 1;
+ }
+
+ if (var5 == Material.sand) {
+ var6 = 2;
+ }
+
+ if (var5 == Material.glass) {
+ var6 = 3;
+ }
+
+ if (var5 == Material.wood) {
+ var6 = 4;
+ }
+
+ par1World.addBlockEvent(par2, par3, par4, Block.music.blockID, var6, this.note);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/TileEntityPiston.java b/sp-server/src/main/java/net/minecraft/src/TileEntityPiston.java
new file mode 100644
index 0000000..5da2a73
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/TileEntityPiston.java
@@ -0,0 +1,171 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+public class TileEntityPiston extends TileEntity {
+ private int storedBlockID;
+ private int storedMetadata;
+
+ /** the side the front of the piston is on */
+ private int storedOrientation;
+
+ /** if this piston is extending or not */
+ private boolean extending;
+ private boolean shouldHeadBeRendered;
+ private float progress;
+
+ /** the progress in (de)extending */
+ private float lastProgress;
+ private List pushedObjects = new ArrayList();
+
+ public TileEntityPiston() {
+ }
+
+ public TileEntityPiston(int par1, int par2, int par3, boolean par4, boolean par5) {
+ this.storedBlockID = par1;
+ this.storedMetadata = par2;
+ this.storedOrientation = par3;
+ this.extending = par4;
+ this.shouldHeadBeRendered = par5;
+ }
+
+ public int getStoredBlockID() {
+ return this.storedBlockID;
+ }
+
+ /**
+ * Returns block data at the location of this entity (client-only).
+ */
+ public int getBlockMetadata() {
+ return this.storedMetadata;
+ }
+
+ /**
+ * Returns true if a piston is extending
+ */
+ public boolean isExtending() {
+ return this.extending;
+ }
+
+ /**
+ * Returns the orientation of the piston as an int
+ */
+ public int getPistonOrientation() {
+ return this.storedOrientation;
+ }
+
+ /**
+ * Get interpolated progress value (between lastProgress and progress) given the
+ * fractional time between ticks as an argument.
+ */
+ public float getProgress(float par1) {
+ if (par1 > 1.0F) {
+ par1 = 1.0F;
+ }
+
+ return this.lastProgress + (this.progress - this.lastProgress) * par1;
+ }
+
+ private void updatePushedObjects(float par1, float par2) {
+ if (this.extending) {
+ par1 = 1.0F - par1;
+ } else {
+ --par1;
+ }
+
+ AxisAlignedBB var3 = Block.pistonMoving.getAxisAlignedBB(this.worldObj, this.xCoord, this.yCoord, this.zCoord,
+ this.storedBlockID, par1, this.storedOrientation);
+
+ if (var3 != null) {
+ List var4 = this.worldObj.getEntitiesWithinAABBExcludingEntity((Entity) null, var3);
+
+ if (!var4.isEmpty()) {
+ this.pushedObjects.addAll(var4);
+ Iterator var5 = this.pushedObjects.iterator();
+
+ while (var5.hasNext()) {
+ Entity var6 = (Entity) var5.next();
+ var6.moveEntity((double) (par2 * (float) Facing.offsetsXForSide[this.storedOrientation]),
+ (double) (par2 * (float) Facing.offsetsYForSide[this.storedOrientation]),
+ (double) (par2 * (float) Facing.offsetsZForSide[this.storedOrientation]));
+ }
+
+ this.pushedObjects.clear();
+ }
+ }
+ }
+
+ /**
+ * removes a pistons tile entity (and if the piston is moving, stops it)
+ */
+ public void clearPistonTileEntity() {
+ if (this.lastProgress < 1.0F && this.worldObj != null) {
+ this.lastProgress = this.progress = 1.0F;
+ this.worldObj.removeBlockTileEntity(this.xCoord, this.yCoord, this.zCoord);
+ this.invalidate();
+
+ if (this.worldObj.getBlockId(this.xCoord, this.yCoord, this.zCoord) == Block.pistonMoving.blockID) {
+ this.worldObj.setBlock(this.xCoord, this.yCoord, this.zCoord, this.storedBlockID, this.storedMetadata,
+ 3);
+ this.worldObj.notifyBlockOfNeighborChange(this.xCoord, this.yCoord, this.zCoord, this.storedBlockID);
+ }
+ }
+ }
+
+ /**
+ * Allows the entity to update its state. Overridden in most subclasses, e.g.
+ * the mob spawner uses this to count ticks and creates a new spawn inside its
+ * implementation.
+ */
+ public void updateEntity() {
+ this.lastProgress = this.progress;
+
+ if (this.lastProgress >= 1.0F) {
+ this.updatePushedObjects(1.0F, 0.25F);
+ this.worldObj.removeBlockTileEntity(this.xCoord, this.yCoord, this.zCoord);
+ this.invalidate();
+
+ if (this.worldObj.getBlockId(this.xCoord, this.yCoord, this.zCoord) == Block.pistonMoving.blockID) {
+ this.worldObj.setBlock(this.xCoord, this.yCoord, this.zCoord, this.storedBlockID, this.storedMetadata,
+ 3);
+ this.worldObj.notifyBlockOfNeighborChange(this.xCoord, this.yCoord, this.zCoord, this.storedBlockID);
+ }
+ } else {
+ this.progress += 0.5F;
+
+ if (this.progress >= 1.0F) {
+ this.progress = 1.0F;
+ }
+
+ if (this.extending) {
+ this.updatePushedObjects(this.progress, this.progress - this.lastProgress + 0.0625F);
+ }
+ }
+ }
+
+ /**
+ * Reads a tile entity from NBT.
+ */
+ public void readFromNBT(NBTTagCompound par1NBTTagCompound) {
+ super.readFromNBT(par1NBTTagCompound);
+ this.storedBlockID = par1NBTTagCompound.getInteger("blockId");
+ this.storedMetadata = par1NBTTagCompound.getInteger("blockData");
+ this.storedOrientation = par1NBTTagCompound.getInteger("facing");
+ this.lastProgress = this.progress = par1NBTTagCompound.getFloat("progress");
+ this.extending = par1NBTTagCompound.getBoolean("extending");
+ }
+
+ /**
+ * Writes a tile entity to NBT.
+ */
+ public void writeToNBT(NBTTagCompound par1NBTTagCompound) {
+ super.writeToNBT(par1NBTTagCompound);
+ par1NBTTagCompound.setInteger("blockId", this.storedBlockID);
+ par1NBTTagCompound.setInteger("blockData", this.storedMetadata);
+ par1NBTTagCompound.setInteger("facing", this.storedOrientation);
+ par1NBTTagCompound.setFloat("progress", this.lastProgress);
+ par1NBTTagCompound.setBoolean("extending", this.extending);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/TileEntityRecordPlayer.java b/sp-server/src/main/java/net/minecraft/src/TileEntityRecordPlayer.java
new file mode 100644
index 0000000..dc72931
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/TileEntityRecordPlayer.java
@@ -0,0 +1,40 @@
+package net.minecraft.src;
+
+public class TileEntityRecordPlayer extends TileEntity {
+ /** ID of record which is in Jukebox */
+ private ItemStack record;
+
+ /**
+ * Reads a tile entity from NBT.
+ */
+ public void readFromNBT(NBTTagCompound par1NBTTagCompound) {
+ super.readFromNBT(par1NBTTagCompound);
+
+ if (par1NBTTagCompound.hasKey("RecordItem")) {
+ this.func_96098_a(ItemStack.loadItemStackFromNBT(par1NBTTagCompound.getCompoundTag("RecordItem")));
+ } else if (par1NBTTagCompound.getInteger("Record") > 0) {
+ this.func_96098_a(new ItemStack(par1NBTTagCompound.getInteger("Record"), 1, 0));
+ }
+ }
+
+ /**
+ * Writes a tile entity to NBT.
+ */
+ public void writeToNBT(NBTTagCompound par1NBTTagCompound) {
+ super.writeToNBT(par1NBTTagCompound);
+
+ if (this.func_96097_a() != null) {
+ par1NBTTagCompound.setCompoundTag("RecordItem", this.func_96097_a().writeToNBT(new NBTTagCompound()));
+ par1NBTTagCompound.setInteger("Record", this.func_96097_a().itemID);
+ }
+ }
+
+ public ItemStack func_96097_a() {
+ return this.record;
+ }
+
+ public void func_96098_a(ItemStack par1ItemStack) {
+ this.record = par1ItemStack;
+ this.onInventoryChanged();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/TileEntitySign.java b/sp-server/src/main/java/net/minecraft/src/TileEntitySign.java
new file mode 100644
index 0000000..dfa3d88
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/TileEntitySign.java
@@ -0,0 +1,54 @@
+package net.minecraft.src;
+
+public class TileEntitySign extends TileEntity {
+ /** An array of four strings storing the lines of text on the sign. */
+ public String[] signText = new String[] { "", "", "", "" };
+
+ /**
+ * The index of the line currently being edited. Only used on client side, but
+ * defined on both. Note this is only really used when the > < are going to be
+ * visible.
+ */
+ public int lineBeingEdited = -1;
+ private boolean isEditable = true;
+
+ /**
+ * Writes a tile entity to NBT.
+ */
+ public void writeToNBT(NBTTagCompound par1NBTTagCompound) {
+ super.writeToNBT(par1NBTTagCompound);
+ par1NBTTagCompound.setString("Text1", this.signText[0]);
+ par1NBTTagCompound.setString("Text2", this.signText[1]);
+ par1NBTTagCompound.setString("Text3", this.signText[2]);
+ par1NBTTagCompound.setString("Text4", this.signText[3]);
+ }
+
+ /**
+ * Reads a tile entity from NBT.
+ */
+ public void readFromNBT(NBTTagCompound par1NBTTagCompound) {
+ this.isEditable = false;
+ super.readFromNBT(par1NBTTagCompound);
+
+ for (int var2 = 0; var2 < 4; ++var2) {
+ this.signText[var2] = par1NBTTagCompound.getString("Text" + (var2 + 1));
+
+ if (this.signText[var2].length() > 15) {
+ this.signText[var2] = this.signText[var2].substring(0, 15);
+ }
+ }
+ }
+
+ /**
+ * Overriden in a sign to provide the text.
+ */
+ public Packet getDescriptionPacket() {
+ String[] var1 = new String[4];
+ System.arraycopy(this.signText, 0, var1, 0, 4);
+ return new Packet130UpdateSign(this.xCoord, this.yCoord, this.zCoord, var1);
+ }
+
+ public boolean isEditable() {
+ return this.isEditable;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/TileEntitySkull.java b/sp-server/src/main/java/net/minecraft/src/TileEntitySkull.java
new file mode 100644
index 0000000..79d33a5
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/TileEntitySkull.java
@@ -0,0 +1,73 @@
+package net.minecraft.src;
+
+public class TileEntitySkull extends TileEntity {
+ /** Entity type for this skull. */
+ private int skullType;
+
+ /** The skull's rotation. */
+ private int skullRotation;
+
+ /** Extra data for this skull, used as player username by player heads */
+ private String extraType = "";
+
+ /**
+ * Writes a tile entity to NBT.
+ */
+ public void writeToNBT(NBTTagCompound par1NBTTagCompound) {
+ super.writeToNBT(par1NBTTagCompound);
+ par1NBTTagCompound.setByte("SkullType", (byte) (this.skullType & 255));
+ par1NBTTagCompound.setByte("Rot", (byte) (this.skullRotation & 255));
+ par1NBTTagCompound.setString("ExtraType", this.extraType);
+ }
+
+ /**
+ * Reads a tile entity from NBT.
+ */
+ public void readFromNBT(NBTTagCompound par1NBTTagCompound) {
+ super.readFromNBT(par1NBTTagCompound);
+ this.skullType = par1NBTTagCompound.getByte("SkullType");
+ this.skullRotation = par1NBTTagCompound.getByte("Rot");
+
+ if (par1NBTTagCompound.hasKey("ExtraType")) {
+ this.extraType = par1NBTTagCompound.getString("ExtraType");
+ }
+ }
+
+ /**
+ * Overriden in a sign to provide the text.
+ */
+ public Packet getDescriptionPacket() {
+ NBTTagCompound var1 = new NBTTagCompound();
+ this.writeToNBT(var1);
+ return new Packet132TileEntityData(this.xCoord, this.yCoord, this.zCoord, 4, var1);
+ }
+
+ /**
+ * Set the entity type for the skull
+ */
+ public void setSkullType(int par1, String par2Str) {
+ this.skullType = par1;
+ this.extraType = par2Str;
+ }
+
+ /**
+ * Get the entity type for the skull
+ */
+ public int getSkullType() {
+ return this.skullType;
+ }
+
+ /**
+ * Set the skull's rotation
+ */
+ public void setSkullRotation(int par1) {
+ this.skullRotation = par1;
+ }
+
+ /**
+ * Get the extra data foor this skull, used as player username by player heads
+ */
+ public String getExtraType() {
+ return this.extraType;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Tuple.java b/sp-server/src/main/java/net/minecraft/src/Tuple.java
new file mode 100644
index 0000000..0cb4453
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Tuple.java
@@ -0,0 +1,28 @@
+package net.minecraft.src;
+
+public class Tuple {
+ /** First Object in the Tuple */
+ private Object first;
+
+ /** Second Object in the Tuple */
+ private Object second;
+
+ public Tuple(Object par1Obj, Object par2Obj) {
+ this.first = par1Obj;
+ this.second = par2Obj;
+ }
+
+ /**
+ * Get the first Object in the Tuple
+ */
+ public Object getFirst() {
+ return this.first;
+ }
+
+ /**
+ * Get the second Object in the Tuple
+ */
+ public Object getSecond() {
+ return this.second;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Vec3.java b/sp-server/src/main/java/net/minecraft/src/Vec3.java
new file mode 100644
index 0000000..7d7b721
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Vec3.java
@@ -0,0 +1,210 @@
+package net.minecraft.src;
+
+public class Vec3 {
+ /**
+ * A global Vec3Pool that always creates new vectors instead of reusing them and
+ * is thread-safe.
+ */
+ public static final Vec3Pool fakePool = new Vec3Pool(-1, -1);
+ public final Vec3Pool myVec3LocalPool;
+
+ /** X coordinate of Vec3D */
+ public double xCoord;
+
+ /** Y coordinate of Vec3D */
+ public double yCoord;
+
+ /** Z coordinate of Vec3D */
+ public double zCoord;
+
+ /**
+ * Static method for creating a new Vec3D given the three x,y,z values. This is
+ * only called from the other static method which creates and places it in the
+ * list.
+ */
+ public static Vec3 createVectorHelper(double par0, double par2, double par4) {
+ return new Vec3(fakePool, par0, par2, par4);
+ }
+
+ protected Vec3(Vec3Pool par1Vec3Pool, double par2, double par4, double par6) {
+ if (par2 == -0.0D) {
+ par2 = 0.0D;
+ }
+
+ if (par4 == -0.0D) {
+ par4 = 0.0D;
+ }
+
+ if (par6 == -0.0D) {
+ par6 = 0.0D;
+ }
+
+ this.xCoord = par2;
+ this.yCoord = par4;
+ this.zCoord = par6;
+ this.myVec3LocalPool = par1Vec3Pool;
+ }
+
+ /**
+ * Sets the x,y,z components of the vector as specified.
+ */
+ protected Vec3 setComponents(double par1, double par3, double par5) {
+ this.xCoord = par1;
+ this.yCoord = par3;
+ this.zCoord = par5;
+ return this;
+ }
+
+ /**
+ * Normalizes the vector to a length of 1 (except if it is the zero vector)
+ */
+ public Vec3 normalize() {
+ double var1 = (double) MathHelper
+ .sqrt_double(this.xCoord * this.xCoord + this.yCoord * this.yCoord + this.zCoord * this.zCoord);
+ return var1 < 1.0E-4D ? this.myVec3LocalPool.getVecFromPool(0.0D, 0.0D, 0.0D)
+ : this.myVec3LocalPool.getVecFromPool(this.xCoord / var1, this.yCoord / var1, this.zCoord / var1);
+ }
+
+ public double dotProduct(Vec3 par1Vec3) {
+ return this.xCoord * par1Vec3.xCoord + this.yCoord * par1Vec3.yCoord + this.zCoord * par1Vec3.zCoord;
+ }
+
+ /**
+ * Adds the specified x,y,z vector components to this vector and returns the
+ * resulting vector. Does not change this vector.
+ */
+ public Vec3 addVector(double par1, double par3, double par5) {
+ return this.myVec3LocalPool.getVecFromPool(this.xCoord + par1, this.yCoord + par3, this.zCoord + par5);
+ }
+
+ /**
+ * Euclidean distance between this and the specified vector, returned as double.
+ */
+ public double distanceTo(Vec3 par1Vec3) {
+ double var2 = par1Vec3.xCoord - this.xCoord;
+ double var4 = par1Vec3.yCoord - this.yCoord;
+ double var6 = par1Vec3.zCoord - this.zCoord;
+ return (double) MathHelper.sqrt_double(var2 * var2 + var4 * var4 + var6 * var6);
+ }
+
+ /**
+ * The square of the Euclidean distance between this and the specified vector.
+ */
+ public double squareDistanceTo(Vec3 par1Vec3) {
+ double var2 = par1Vec3.xCoord - this.xCoord;
+ double var4 = par1Vec3.yCoord - this.yCoord;
+ double var6 = par1Vec3.zCoord - this.zCoord;
+ return var2 * var2 + var4 * var4 + var6 * var6;
+ }
+
+ /**
+ * The square of the Euclidean distance between this and the vector of x,y,z
+ * components passed in.
+ */
+ public double squareDistanceTo(double par1, double par3, double par5) {
+ double var7 = par1 - this.xCoord;
+ double var9 = par3 - this.yCoord;
+ double var11 = par5 - this.zCoord;
+ return var7 * var7 + var9 * var9 + var11 * var11;
+ }
+
+ /**
+ * Returns the length of the vector.
+ */
+ public double lengthVector() {
+ return (double) MathHelper
+ .sqrt_double(this.xCoord * this.xCoord + this.yCoord * this.yCoord + this.zCoord * this.zCoord);
+ }
+
+ /**
+ * Returns a new vector with x value equal to the second parameter, along the
+ * line between this vector and the passed in vector, or null if not possible.
+ */
+ public Vec3 getIntermediateWithXValue(Vec3 par1Vec3, double par2) {
+ double var4 = par1Vec3.xCoord - this.xCoord;
+ double var6 = par1Vec3.yCoord - this.yCoord;
+ double var8 = par1Vec3.zCoord - this.zCoord;
+
+ if (var4 * var4 < 1.0000000116860974E-7D) {
+ return null;
+ } else {
+ double var10 = (par2 - this.xCoord) / var4;
+ return var10 >= 0.0D && var10 <= 1.0D
+ ? this.myVec3LocalPool.getVecFromPool(this.xCoord + var4 * var10, this.yCoord + var6 * var10,
+ this.zCoord + var8 * var10)
+ : null;
+ }
+ }
+
+ /**
+ * Returns a new vector with y value equal to the second parameter, along the
+ * line between this vector and the passed in vector, or null if not possible.
+ */
+ public Vec3 getIntermediateWithYValue(Vec3 par1Vec3, double par2) {
+ double var4 = par1Vec3.xCoord - this.xCoord;
+ double var6 = par1Vec3.yCoord - this.yCoord;
+ double var8 = par1Vec3.zCoord - this.zCoord;
+
+ if (var6 * var6 < 1.0000000116860974E-7D) {
+ return null;
+ } else {
+ double var10 = (par2 - this.yCoord) / var6;
+ return var10 >= 0.0D && var10 <= 1.0D
+ ? this.myVec3LocalPool.getVecFromPool(this.xCoord + var4 * var10, this.yCoord + var6 * var10,
+ this.zCoord + var8 * var10)
+ : null;
+ }
+ }
+
+ /**
+ * Returns a new vector with z value equal to the second parameter, along the
+ * line between this vector and the passed in vector, or null if not possible.
+ */
+ public Vec3 getIntermediateWithZValue(Vec3 par1Vec3, double par2) {
+ double var4 = par1Vec3.xCoord - this.xCoord;
+ double var6 = par1Vec3.yCoord - this.yCoord;
+ double var8 = par1Vec3.zCoord - this.zCoord;
+
+ if (var8 * var8 < 1.0000000116860974E-7D) {
+ return null;
+ } else {
+ double var10 = (par2 - this.zCoord) / var8;
+ return var10 >= 0.0D && var10 <= 1.0D
+ ? this.myVec3LocalPool.getVecFromPool(this.xCoord + var4 * var10, this.yCoord + var6 * var10,
+ this.zCoord + var8 * var10)
+ : null;
+ }
+ }
+
+ public String toString() {
+ return "(" + this.xCoord + ", " + this.yCoord + ", " + this.zCoord + ")";
+ }
+
+ /**
+ * Rotates the vector around the x axis by the specified angle.
+ */
+ public void rotateAroundX(float par1) {
+ float var2 = MathHelper.cos(par1);
+ float var3 = MathHelper.sin(par1);
+ double var4 = this.xCoord;
+ double var6 = this.yCoord * (double) var2 + this.zCoord * (double) var3;
+ double var8 = this.zCoord * (double) var2 - this.yCoord * (double) var3;
+ this.xCoord = var4;
+ this.yCoord = var6;
+ this.zCoord = var8;
+ }
+
+ /**
+ * Rotates the vector around the y axis by the specified angle.
+ */
+ public void rotateAroundY(float par1) {
+ float var2 = MathHelper.cos(par1);
+ float var3 = MathHelper.sin(par1);
+ double var4 = this.xCoord * (double) var2 + this.zCoord * (double) var3;
+ double var6 = this.yCoord;
+ double var8 = this.zCoord * (double) var2 - this.xCoord * (double) var3;
+ this.xCoord = var4;
+ this.yCoord = var6;
+ this.zCoord = var8;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Vec3Pool.java b/sp-server/src/main/java/net/minecraft/src/Vec3Pool.java
new file mode 100644
index 0000000..0cb0c97
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Vec3Pool.java
@@ -0,0 +1,79 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Vec3Pool {
+ private final int truncateArrayResetThreshold;
+ private final int minimumSize;
+
+ /** items at and above nextFreeSpace are assumed to be available */
+ private final List vec3Cache = new ArrayList();
+ private int nextFreeSpace = 0;
+ private int maximumSizeSinceLastTruncation = 0;
+ private int resetCount = 0;
+
+ public Vec3Pool(int par1, int par2) {
+ this.truncateArrayResetThreshold = par1;
+ this.minimumSize = par2;
+ }
+
+ /**
+ * extends the pool if all vecs are currently "out"
+ */
+ public Vec3 getVecFromPool(double par1, double par3, double par5) {
+ if (this.func_82589_e()) {
+ return new Vec3(this, par1, par3, par5);
+ } else {
+ Vec3 var7;
+
+ if (this.nextFreeSpace >= this.vec3Cache.size()) {
+ var7 = new Vec3(this, par1, par3, par5);
+ this.vec3Cache.add(var7);
+ } else {
+ var7 = (Vec3) this.vec3Cache.get(this.nextFreeSpace);
+ var7.setComponents(par1, par3, par5);
+ }
+
+ ++this.nextFreeSpace;
+ return var7;
+ }
+ }
+
+ /**
+ * Will truncate the array everyN clears to the maximum size observed since the
+ * last truncation.
+ */
+ public void clear() {
+ if (!this.func_82589_e()) {
+ if (this.nextFreeSpace > this.maximumSizeSinceLastTruncation) {
+ this.maximumSizeSinceLastTruncation = this.nextFreeSpace;
+ }
+
+ if (this.resetCount++ == this.truncateArrayResetThreshold) {
+ int var1 = Math.max(this.maximumSizeSinceLastTruncation, this.vec3Cache.size() - this.minimumSize);
+
+ while (this.vec3Cache.size() > var1) {
+ this.vec3Cache.remove(var1);
+ }
+
+ this.maximumSizeSinceLastTruncation = 0;
+ this.resetCount = 0;
+ }
+
+ this.nextFreeSpace = 0;
+ }
+ }
+
+ public int getPoolSize() {
+ return this.vec3Cache.size();
+ }
+
+ public int func_82590_d() {
+ return this.nextFreeSpace;
+ }
+
+ private boolean func_82589_e() {
+ return this.minimumSize < 0 || this.truncateArrayResetThreshold < 0;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/Village.java b/sp-server/src/main/java/net/minecraft/src/Village.java
new file mode 100644
index 0000000..6521897
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/Village.java
@@ -0,0 +1,514 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.TreeMap;
+
+public class Village {
+ private World worldObj;
+
+ /** list of VillageDoorInfo objects */
+ private final List villageDoorInfoList = new ArrayList();
+
+ /**
+ * This is the sum of all door coordinates and used to calculate the actual
+ * village center by dividing by the number of doors.
+ */
+ private final ChunkCoordinates centerHelper = new ChunkCoordinates(0, 0, 0);
+
+ /** This is the actual village center. */
+ private final ChunkCoordinates center = new ChunkCoordinates(0, 0, 0);
+ private int villageRadius = 0;
+ private int lastAddDoorTimestamp = 0;
+ private int tickCounter = 0;
+ private int numVillagers = 0;
+
+ /** Timestamp of tick count when villager last bred */
+ private int noBreedTicks;
+
+ /** List of player reputations with this village */
+ private TreeMap playerReputation = new TreeMap();
+ private List villageAgressors = new ArrayList();
+ private int numIronGolems = 0;
+
+ public Village() {
+ }
+
+ public Village(World par1World) {
+ this.worldObj = par1World;
+ }
+
+ public void func_82691_a(World par1World) {
+ this.worldObj = par1World;
+ }
+
+ /**
+ * Called periodically by VillageCollection
+ */
+ public void tick(int par1) {
+ this.tickCounter = par1;
+ this.removeDeadAndOutOfRangeDoors();
+ this.removeDeadAndOldAgressors();
+
+ if (par1 % 20 == 0) {
+ this.updateNumVillagers();
+ }
+
+ if (par1 % 30 == 0) {
+ this.updateNumIronGolems();
+ }
+
+ int var2 = this.numVillagers / 10;
+
+ if (this.numIronGolems < var2 && this.villageDoorInfoList.size() > 20
+ && this.worldObj.rand.nextInt(7000) == 0) {
+ Vec3 var3 = this.tryGetIronGolemSpawningLocation(MathHelper.floor_float((float) this.center.posX),
+ MathHelper.floor_float((float) this.center.posY), MathHelper.floor_float((float) this.center.posZ),
+ 2, 4, 2);
+
+ if (var3 != null) {
+ EntityIronGolem var4 = new EntityIronGolem(this.worldObj);
+ var4.setPosition(var3.xCoord, var3.yCoord, var3.zCoord);
+ this.worldObj.spawnEntityInWorld(var4);
+ ++this.numIronGolems;
+ }
+ }
+ }
+
+ /**
+ * Tries up to 10 times to get a valid spawning location before eventually
+ * failing and returning null.
+ */
+ private Vec3 tryGetIronGolemSpawningLocation(int par1, int par2, int par3, int par4, int par5, int par6) {
+ for (int var7 = 0; var7 < 10; ++var7) {
+ int var8 = par1 + this.worldObj.rand.nextInt(16) - 8;
+ int var9 = par2 + this.worldObj.rand.nextInt(6) - 3;
+ int var10 = par3 + this.worldObj.rand.nextInt(16) - 8;
+
+ if (this.isInRange(var8, var9, var10)
+ && this.isValidIronGolemSpawningLocation(var8, var9, var10, par4, par5, par6)) {
+ return this.worldObj.getWorldVec3Pool().getVecFromPool((double) var8, (double) var9, (double) var10);
+ }
+ }
+
+ return null;
+ }
+
+ private boolean isValidIronGolemSpawningLocation(int par1, int par2, int par3, int par4, int par5, int par6) {
+ if (!this.worldObj.doesBlockHaveSolidTopSurface(par1, par2 - 1, par3)) {
+ return false;
+ } else {
+ int var7 = par1 - par4 / 2;
+ int var8 = par3 - par6 / 2;
+
+ for (int var9 = var7; var9 < var7 + par4; ++var9) {
+ for (int var10 = par2; var10 < par2 + par5; ++var10) {
+ for (int var11 = var8; var11 < var8 + par6; ++var11) {
+ if (this.worldObj.isBlockNormalCube(var9, var10, var11)) {
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+ }
+
+ private void updateNumIronGolems() {
+ List var1 = this.worldObj.getEntitiesWithinAABB(EntityIronGolem.class,
+ AxisAlignedBB.getAABBPool().getAABB((double) (this.center.posX - this.villageRadius),
+ (double) (this.center.posY - 4), (double) (this.center.posZ - this.villageRadius),
+ (double) (this.center.posX + this.villageRadius), (double) (this.center.posY + 4),
+ (double) (this.center.posZ + this.villageRadius)));
+ this.numIronGolems = var1.size();
+ }
+
+ private void updateNumVillagers() {
+ List var1 = this.worldObj.getEntitiesWithinAABB(EntityVillager.class,
+ AxisAlignedBB.getAABBPool().getAABB((double) (this.center.posX - this.villageRadius),
+ (double) (this.center.posY - 4), (double) (this.center.posZ - this.villageRadius),
+ (double) (this.center.posX + this.villageRadius), (double) (this.center.posY + 4),
+ (double) (this.center.posZ + this.villageRadius)));
+ this.numVillagers = var1.size();
+
+ if (this.numVillagers == 0) {
+ this.playerReputation.clear();
+ }
+ }
+
+ public ChunkCoordinates getCenter() {
+ return this.center;
+ }
+
+ public int getVillageRadius() {
+ return this.villageRadius;
+ }
+
+ /**
+ * Actually get num village door info entries, but that boils down to number of
+ * doors. Called by EntityAIVillagerMate and VillageSiege
+ */
+ public int getNumVillageDoors() {
+ return this.villageDoorInfoList.size();
+ }
+
+ public int getTicksSinceLastDoorAdding() {
+ return this.tickCounter - this.lastAddDoorTimestamp;
+ }
+
+ public int getNumVillagers() {
+ return this.numVillagers;
+ }
+
+ /**
+ * Returns true, if the given coordinates are within the bounding box of the
+ * village.
+ */
+ public boolean isInRange(int par1, int par2, int par3) {
+ return this.center.getDistanceSquared(par1, par2, par3) < (float) (this.villageRadius * this.villageRadius);
+ }
+
+ /**
+ * called only by class EntityAIMoveThroughVillage
+ */
+ public List getVillageDoorInfoList() {
+ return this.villageDoorInfoList;
+ }
+
+ public VillageDoorInfo findNearestDoor(int par1, int par2, int par3) {
+ VillageDoorInfo var4 = null;
+ int var5 = Integer.MAX_VALUE;
+ Iterator var6 = this.villageDoorInfoList.iterator();
+
+ while (var6.hasNext()) {
+ VillageDoorInfo var7 = (VillageDoorInfo) var6.next();
+ int var8 = var7.getDistanceSquared(par1, par2, par3);
+
+ if (var8 < var5) {
+ var4 = var7;
+ var5 = var8;
+ }
+ }
+
+ return var4;
+ }
+
+ /**
+ * Find a door suitable for shelter. If there are more doors in a distance of 16
+ * blocks, then the least restricted one (i.e. the one protecting the lowest
+ * number of villagers) of them is chosen, else the nearest one regardless of
+ * restriction.
+ */
+ public VillageDoorInfo findNearestDoorUnrestricted(int par1, int par2, int par3) {
+ VillageDoorInfo var4 = null;
+ int var5 = Integer.MAX_VALUE;
+ Iterator var6 = this.villageDoorInfoList.iterator();
+
+ while (var6.hasNext()) {
+ VillageDoorInfo var7 = (VillageDoorInfo) var6.next();
+ int var8 = var7.getDistanceSquared(par1, par2, par3);
+
+ if (var8 > 256) {
+ var8 *= 1000;
+ } else {
+ var8 = var7.getDoorOpeningRestrictionCounter();
+ }
+
+ if (var8 < var5) {
+ var4 = var7;
+ var5 = var8;
+ }
+ }
+
+ return var4;
+ }
+
+ public VillageDoorInfo getVillageDoorAt(int par1, int par2, int par3) {
+ if (this.center.getDistanceSquared(par1, par2, par3) > (float) (this.villageRadius * this.villageRadius)) {
+ return null;
+ } else {
+ Iterator var4 = this.villageDoorInfoList.iterator();
+ VillageDoorInfo var5;
+
+ do {
+ if (!var4.hasNext()) {
+ return null;
+ }
+
+ var5 = (VillageDoorInfo) var4.next();
+ } while (var5.posX != par1 || var5.posZ != par3 || Math.abs(var5.posY - par2) > 1);
+
+ return var5;
+ }
+ }
+
+ public void addVillageDoorInfo(VillageDoorInfo par1VillageDoorInfo) {
+ this.villageDoorInfoList.add(par1VillageDoorInfo);
+ this.centerHelper.posX += par1VillageDoorInfo.posX;
+ this.centerHelper.posY += par1VillageDoorInfo.posY;
+ this.centerHelper.posZ += par1VillageDoorInfo.posZ;
+ this.updateVillageRadiusAndCenter();
+ this.lastAddDoorTimestamp = par1VillageDoorInfo.lastActivityTimestamp;
+ }
+
+ /**
+ * Returns true, if there is not a single village door left. Called by
+ * VillageCollection
+ */
+ public boolean isAnnihilated() {
+ return this.villageDoorInfoList.isEmpty();
+ }
+
+ public void addOrRenewAgressor(EntityLiving par1EntityLiving) {
+ Iterator var2 = this.villageAgressors.iterator();
+ VillageAgressor var3;
+
+ do {
+ if (!var2.hasNext()) {
+ this.villageAgressors.add(new VillageAgressor(this, par1EntityLiving, this.tickCounter));
+ return;
+ }
+
+ var3 = (VillageAgressor) var2.next();
+ } while (var3.agressor != par1EntityLiving);
+
+ var3.agressionTime = this.tickCounter;
+ }
+
+ public EntityLiving findNearestVillageAggressor(EntityLiving par1EntityLiving) {
+ double var2 = Double.MAX_VALUE;
+ VillageAgressor var4 = null;
+
+ for (int var5 = 0; var5 < this.villageAgressors.size(); ++var5) {
+ VillageAgressor var6 = (VillageAgressor) this.villageAgressors.get(var5);
+ double var7 = var6.agressor.getDistanceSqToEntity(par1EntityLiving);
+
+ if (var7 <= var2) {
+ var4 = var6;
+ var2 = var7;
+ }
+ }
+
+ return var4 != null ? var4.agressor : null;
+ }
+
+ public EntityPlayer func_82685_c(EntityLiving par1EntityLiving) {
+ double var2 = Double.MAX_VALUE;
+ EntityPlayer var4 = null;
+ Iterator var5 = this.playerReputation.keySet().iterator();
+
+ while (var5.hasNext()) {
+ String var6 = (String) var5.next();
+
+ if (this.isPlayerReputationTooLow(var6)) {
+ EntityPlayer var7 = this.worldObj.getPlayerEntityByName(var6);
+
+ if (var7 != null) {
+ double var8 = var7.getDistanceSqToEntity(par1EntityLiving);
+
+ if (var8 <= var2) {
+ var4 = var7;
+ var2 = var8;
+ }
+ }
+ }
+ }
+
+ return var4;
+ }
+
+ private void removeDeadAndOldAgressors() {
+ Iterator var1 = this.villageAgressors.iterator();
+
+ while (var1.hasNext()) {
+ VillageAgressor var2 = (VillageAgressor) var1.next();
+
+ if (!var2.agressor.isEntityAlive() || Math.abs(this.tickCounter - var2.agressionTime) > 300) {
+ var1.remove();
+ }
+ }
+ }
+
+ private void removeDeadAndOutOfRangeDoors() {
+ boolean var1 = false;
+ boolean var2 = this.worldObj.rand.nextInt(50) == 0;
+ Iterator var3 = this.villageDoorInfoList.iterator();
+
+ while (var3.hasNext()) {
+ VillageDoorInfo var4 = (VillageDoorInfo) var3.next();
+
+ if (var2) {
+ var4.resetDoorOpeningRestrictionCounter();
+ }
+
+ if (!this.isBlockDoor(var4.posX, var4.posY, var4.posZ)
+ || Math.abs(this.tickCounter - var4.lastActivityTimestamp) > 1200) {
+ this.centerHelper.posX -= var4.posX;
+ this.centerHelper.posY -= var4.posY;
+ this.centerHelper.posZ -= var4.posZ;
+ var1 = true;
+ var4.isDetachedFromVillageFlag = true;
+ var3.remove();
+ }
+ }
+
+ if (var1) {
+ this.updateVillageRadiusAndCenter();
+ }
+ }
+
+ private boolean isBlockDoor(int par1, int par2, int par3) {
+ int var4 = this.worldObj.getBlockId(par1, par2, par3);
+ return var4 <= 0 ? false : var4 == Block.doorWood.blockID;
+ }
+
+ private void updateVillageRadiusAndCenter() {
+ int var1 = this.villageDoorInfoList.size();
+
+ if (var1 == 0) {
+ this.center.set(0, 0, 0);
+ this.villageRadius = 0;
+ } else {
+ this.center.set(this.centerHelper.posX / var1, this.centerHelper.posY / var1,
+ this.centerHelper.posZ / var1);
+ int var2 = 0;
+ VillageDoorInfo var4;
+
+ for (Iterator var3 = this.villageDoorInfoList.iterator(); var3.hasNext(); var2 = Math
+ .max(var4.getDistanceSquared(this.center.posX, this.center.posY, this.center.posZ), var2)) {
+ var4 = (VillageDoorInfo) var3.next();
+ }
+
+ this.villageRadius = Math.max(32, (int) Math.sqrt((double) var2) + 1);
+ }
+ }
+
+ /**
+ * Return the village reputation for a player
+ */
+ public int getReputationForPlayer(String par1Str) {
+ Integer var2 = (Integer) this.playerReputation.get(par1Str);
+ return var2 != null ? var2.intValue() : 0;
+ }
+
+ /**
+ * Set the village reputation for a player.
+ */
+ public int setReputationForPlayer(String par1Str, int par2) {
+ int var3 = this.getReputationForPlayer(par1Str);
+ int var4 = MathHelper.clamp_int(var3 + par2, -30, 10);
+ this.playerReputation.put(par1Str, Integer.valueOf(var4));
+ return var4;
+ }
+
+ /**
+ * Return whether this player has a too low reputation with this village.
+ */
+ public boolean isPlayerReputationTooLow(String par1Str) {
+ return this.getReputationForPlayer(par1Str) <= -15;
+ }
+
+ /**
+ * Read this village's data from NBT.
+ */
+ public void readVillageDataFromNBT(NBTTagCompound par1NBTTagCompound) {
+ this.numVillagers = par1NBTTagCompound.getInteger("PopSize");
+ this.villageRadius = par1NBTTagCompound.getInteger("Radius");
+ this.numIronGolems = par1NBTTagCompound.getInteger("Golems");
+ this.lastAddDoorTimestamp = par1NBTTagCompound.getInteger("Stable");
+ this.tickCounter = par1NBTTagCompound.getInteger("Tick");
+ this.noBreedTicks = par1NBTTagCompound.getInteger("MTick");
+ this.center.posX = par1NBTTagCompound.getInteger("CX");
+ this.center.posY = par1NBTTagCompound.getInteger("CY");
+ this.center.posZ = par1NBTTagCompound.getInteger("CZ");
+ this.centerHelper.posX = par1NBTTagCompound.getInteger("ACX");
+ this.centerHelper.posY = par1NBTTagCompound.getInteger("ACY");
+ this.centerHelper.posZ = par1NBTTagCompound.getInteger("ACZ");
+ NBTTagList var2 = par1NBTTagCompound.getTagList("Doors");
+
+ for (int var3 = 0; var3 < var2.tagCount(); ++var3) {
+ NBTTagCompound var4 = (NBTTagCompound) var2.tagAt(var3);
+ VillageDoorInfo var5 = new VillageDoorInfo(var4.getInteger("X"), var4.getInteger("Y"), var4.getInteger("Z"),
+ var4.getInteger("IDX"), var4.getInteger("IDZ"), var4.getInteger("TS"));
+ this.villageDoorInfoList.add(var5);
+ }
+
+ NBTTagList var6 = par1NBTTagCompound.getTagList("Players");
+
+ for (int var7 = 0; var7 < var6.tagCount(); ++var7) {
+ NBTTagCompound var8 = (NBTTagCompound) var6.tagAt(var7);
+ this.playerReputation.put(var8.getString("Name"), Integer.valueOf(var8.getInteger("S")));
+ }
+ }
+
+ /**
+ * Write this village's data to NBT.
+ */
+ public void writeVillageDataToNBT(NBTTagCompound par1NBTTagCompound) {
+ par1NBTTagCompound.setInteger("PopSize", this.numVillagers);
+ par1NBTTagCompound.setInteger("Radius", this.villageRadius);
+ par1NBTTagCompound.setInteger("Golems", this.numIronGolems);
+ par1NBTTagCompound.setInteger("Stable", this.lastAddDoorTimestamp);
+ par1NBTTagCompound.setInteger("Tick", this.tickCounter);
+ par1NBTTagCompound.setInteger("MTick", this.noBreedTicks);
+ par1NBTTagCompound.setInteger("CX", this.center.posX);
+ par1NBTTagCompound.setInteger("CY", this.center.posY);
+ par1NBTTagCompound.setInteger("CZ", this.center.posZ);
+ par1NBTTagCompound.setInteger("ACX", this.centerHelper.posX);
+ par1NBTTagCompound.setInteger("ACY", this.centerHelper.posY);
+ par1NBTTagCompound.setInteger("ACZ", this.centerHelper.posZ);
+ NBTTagList var2 = new NBTTagList("Doors");
+ Iterator var3 = this.villageDoorInfoList.iterator();
+
+ while (var3.hasNext()) {
+ VillageDoorInfo var4 = (VillageDoorInfo) var3.next();
+ NBTTagCompound var5 = new NBTTagCompound("Door");
+ var5.setInteger("X", var4.posX);
+ var5.setInteger("Y", var4.posY);
+ var5.setInteger("Z", var4.posZ);
+ var5.setInteger("IDX", var4.insideDirectionX);
+ var5.setInteger("IDZ", var4.insideDirectionZ);
+ var5.setInteger("TS", var4.lastActivityTimestamp);
+ var2.appendTag(var5);
+ }
+
+ par1NBTTagCompound.setTag("Doors", var2);
+ NBTTagList var7 = new NBTTagList("Players");
+ Iterator var8 = this.playerReputation.keySet().iterator();
+
+ while (var8.hasNext()) {
+ String var9 = (String) var8.next();
+ NBTTagCompound var6 = new NBTTagCompound(var9);
+ var6.setString("Name", var9);
+ var6.setInteger("S", ((Integer) this.playerReputation.get(var9)).intValue());
+ var7.appendTag(var6);
+ }
+
+ par1NBTTagCompound.setTag("Players", var7);
+ }
+
+ /**
+ * Prevent villager breeding for a fixed interval of time
+ */
+ public void endMatingSeason() {
+ this.noBreedTicks = this.tickCounter;
+ }
+
+ /**
+ * Return whether villagers mating refractory period has passed
+ */
+ public boolean isMatingSeason() {
+ return this.noBreedTicks == 0 || this.tickCounter - this.noBreedTicks >= 3600;
+ }
+
+ public void func_82683_b(int par1) {
+ Iterator var2 = this.playerReputation.keySet().iterator();
+
+ while (var2.hasNext()) {
+ String var3 = (String) var2.next();
+ this.setReputationForPlayer(var3, par1);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/VillageAgressor.java b/sp-server/src/main/java/net/minecraft/src/VillageAgressor.java
new file mode 100644
index 0000000..20da98c
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/VillageAgressor.java
@@ -0,0 +1,14 @@
+package net.minecraft.src;
+
+class VillageAgressor {
+ public EntityLiving agressor;
+ public int agressionTime;
+
+ final Village villageObj;
+
+ VillageAgressor(Village par1Village, EntityLiving par2EntityLiving, int par3) {
+ this.villageObj = par1Village;
+ this.agressor = par2EntityLiving;
+ this.agressionTime = par3;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/VillageCollection.java b/sp-server/src/main/java/net/minecraft/src/VillageCollection.java
new file mode 100644
index 0000000..f60fe87
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/VillageCollection.java
@@ -0,0 +1,309 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+public class VillageCollection extends WorldSavedData {
+ private World worldObj;
+
+ /**
+ * This is a black hole. You can add data to this list through a public
+ * interface, but you can't query that information in any way and it's not used
+ * internally either.
+ */
+ private final List villagerPositionsList = new ArrayList();
+ private final List newDoors = new ArrayList();
+ private final List villageList = new ArrayList();
+ private int tickCounter = 0;
+
+ public VillageCollection(String par1Str) {
+ super(par1Str);
+ }
+
+ public VillageCollection(World par1World) {
+ super("villages");
+ this.worldObj = par1World;
+ this.markDirty();
+ }
+
+ public void func_82566_a(World par1World) {
+ this.worldObj = par1World;
+ Iterator var2 = this.villageList.iterator();
+
+ while (var2.hasNext()) {
+ Village var3 = (Village) var2.next();
+ var3.func_82691_a(par1World);
+ }
+ }
+
+ /**
+ * This is a black hole. You can add data to this list through a public
+ * interface, but you can't query that information in any way and it's not used
+ * internally either.
+ */
+ public void addVillagerPosition(int par1, int par2, int par3) {
+ if (this.villagerPositionsList.size() <= 64) {
+ if (!this.isVillagerPositionPresent(par1, par2, par3)) {
+ this.villagerPositionsList.add(new ChunkCoordinates(par1, par2, par3));
+ }
+ }
+ }
+
+ /**
+ * Runs a single tick for the village collection
+ */
+ public void tick() {
+ ++this.tickCounter;
+ Iterator var1 = this.villageList.iterator();
+
+ while (var1.hasNext()) {
+ Village var2 = (Village) var1.next();
+ var2.tick(this.tickCounter);
+ }
+
+ this.removeAnnihilatedVillages();
+ this.dropOldestVillagerPosition();
+ this.addNewDoorsToVillageOrCreateVillage();
+
+ if (this.tickCounter % 400 == 0) {
+ this.markDirty();
+ }
+ }
+
+ private void removeAnnihilatedVillages() {
+ Iterator var1 = this.villageList.iterator();
+
+ while (var1.hasNext()) {
+ Village var2 = (Village) var1.next();
+
+ if (var2.isAnnihilated()) {
+ var1.remove();
+ this.markDirty();
+ }
+ }
+ }
+
+ /**
+ * Get a list of villages.
+ */
+ public List getVillageList() {
+ return this.villageList;
+ }
+
+ /**
+ * Finds the nearest village, but only the given coordinates are withing it's
+ * bounding box plus the given the distance.
+ */
+ public Village findNearestVillage(int par1, int par2, int par3, int par4) {
+ Village var5 = null;
+ float var6 = Float.MAX_VALUE;
+ Iterator var7 = this.villageList.iterator();
+
+ while (var7.hasNext()) {
+ Village var8 = (Village) var7.next();
+ float var9 = var8.getCenter().getDistanceSquared(par1, par2, par3);
+
+ if (var9 < var6) {
+ int var10 = par4 + var8.getVillageRadius();
+
+ if (var9 <= (float) (var10 * var10)) {
+ var5 = var8;
+ var6 = var9;
+ }
+ }
+ }
+
+ return var5;
+ }
+
+ private void dropOldestVillagerPosition() {
+ if (!this.villagerPositionsList.isEmpty()) {
+ this.addUnassignedWoodenDoorsAroundToNewDoorsList((ChunkCoordinates) this.villagerPositionsList.remove(0));
+ }
+ }
+
+ private void addNewDoorsToVillageOrCreateVillage() {
+ int var1 = 0;
+
+ while (var1 < this.newDoors.size()) {
+ VillageDoorInfo var2 = (VillageDoorInfo) this.newDoors.get(var1);
+ boolean var3 = false;
+ Iterator var4 = this.villageList.iterator();
+
+ while (true) {
+ if (var4.hasNext()) {
+ Village var5 = (Village) var4.next();
+ int var6 = (int) var5.getCenter().getDistanceSquared(var2.posX, var2.posY, var2.posZ);
+ int var7 = 32 + var5.getVillageRadius();
+
+ if (var6 > var7 * var7) {
+ continue;
+ }
+
+ var5.addVillageDoorInfo(var2);
+ var3 = true;
+ }
+
+ if (!var3) {
+ Village var8 = new Village(this.worldObj);
+ var8.addVillageDoorInfo(var2);
+ this.villageList.add(var8);
+ this.markDirty();
+ }
+
+ ++var1;
+ break;
+ }
+ }
+
+ this.newDoors.clear();
+ }
+
+ private void addUnassignedWoodenDoorsAroundToNewDoorsList(ChunkCoordinates par1ChunkCoordinates) {
+ byte var2 = 16;
+ byte var3 = 4;
+ byte var4 = 16;
+
+ for (int var5 = par1ChunkCoordinates.posX - var2; var5 < par1ChunkCoordinates.posX + var2; ++var5) {
+ for (int var6 = par1ChunkCoordinates.posY - var3; var6 < par1ChunkCoordinates.posY + var3; ++var6) {
+ for (int var7 = par1ChunkCoordinates.posZ - var4; var7 < par1ChunkCoordinates.posZ + var4; ++var7) {
+ if (this.isWoodenDoorAt(var5, var6, var7)) {
+ VillageDoorInfo var8 = this.getVillageDoorAt(var5, var6, var7);
+
+ if (var8 == null) {
+ this.addDoorToNewListIfAppropriate(var5, var6, var7);
+ } else {
+ var8.lastActivityTimestamp = this.tickCounter;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private VillageDoorInfo getVillageDoorAt(int par1, int par2, int par3) {
+ Iterator var4 = this.newDoors.iterator();
+ VillageDoorInfo var5;
+
+ do {
+ if (!var4.hasNext()) {
+ var4 = this.villageList.iterator();
+ VillageDoorInfo var6;
+
+ do {
+ if (!var4.hasNext()) {
+ return null;
+ }
+
+ Village var7 = (Village) var4.next();
+ var6 = var7.getVillageDoorAt(par1, par2, par3);
+ } while (var6 == null);
+
+ return var6;
+ }
+
+ var5 = (VillageDoorInfo) var4.next();
+ } while (var5.posX != par1 || var5.posZ != par3 || Math.abs(var5.posY - par2) > 1);
+
+ return var5;
+ }
+
+ private void addDoorToNewListIfAppropriate(int par1, int par2, int par3) {
+ int var4 = ((BlockDoor) Block.doorWood).getDoorOrientation(this.worldObj, par1, par2, par3);
+ int var5;
+ int var6;
+
+ if (var4 != 0 && var4 != 2) {
+ var5 = 0;
+
+ for (var6 = -5; var6 < 0; ++var6) {
+ if (this.worldObj.canBlockSeeTheSky(par1, par2, par3 + var6)) {
+ --var5;
+ }
+ }
+
+ for (var6 = 1; var6 <= 5; ++var6) {
+ if (this.worldObj.canBlockSeeTheSky(par1, par2, par3 + var6)) {
+ ++var5;
+ }
+ }
+
+ if (var5 != 0) {
+ this.newDoors.add(new VillageDoorInfo(par1, par2, par3, 0, var5 > 0 ? -2 : 2, this.tickCounter));
+ }
+ } else {
+ var5 = 0;
+
+ for (var6 = -5; var6 < 0; ++var6) {
+ if (this.worldObj.canBlockSeeTheSky(par1 + var6, par2, par3)) {
+ --var5;
+ }
+ }
+
+ for (var6 = 1; var6 <= 5; ++var6) {
+ if (this.worldObj.canBlockSeeTheSky(par1 + var6, par2, par3)) {
+ ++var5;
+ }
+ }
+
+ if (var5 != 0) {
+ this.newDoors.add(new VillageDoorInfo(par1, par2, par3, var5 > 0 ? -2 : 2, 0, this.tickCounter));
+ }
+ }
+ }
+
+ private boolean isVillagerPositionPresent(int par1, int par2, int par3) {
+ Iterator var4 = this.villagerPositionsList.iterator();
+ ChunkCoordinates var5;
+
+ do {
+ if (!var4.hasNext()) {
+ return false;
+ }
+
+ var5 = (ChunkCoordinates) var4.next();
+ } while (var5.posX != par1 || var5.posY != par2 || var5.posZ != par3);
+
+ return true;
+ }
+
+ private boolean isWoodenDoorAt(int par1, int par2, int par3) {
+ int var4 = this.worldObj.getBlockId(par1, par2, par3);
+ return var4 == Block.doorWood.blockID;
+ }
+
+ /**
+ * reads in data from the NBTTagCompound into this MapDataBase
+ */
+ public void readFromNBT(NBTTagCompound par1NBTTagCompound) {
+ this.tickCounter = par1NBTTagCompound.getInteger("Tick");
+ NBTTagList var2 = par1NBTTagCompound.getTagList("Villages");
+
+ for (int var3 = 0; var3 < var2.tagCount(); ++var3) {
+ NBTTagCompound var4 = (NBTTagCompound) var2.tagAt(var3);
+ Village var5 = new Village();
+ var5.readVillageDataFromNBT(var4);
+ this.villageList.add(var5);
+ }
+ }
+
+ /**
+ * write data to NBTTagCompound from this MapDataBase, similar to Entities and
+ * TileEntities
+ */
+ public void writeToNBT(NBTTagCompound par1NBTTagCompound) {
+ par1NBTTagCompound.setInteger("Tick", this.tickCounter);
+ NBTTagList var2 = new NBTTagList("Villages");
+ Iterator var3 = this.villageList.iterator();
+
+ while (var3.hasNext()) {
+ Village var4 = (Village) var3.next();
+ NBTTagCompound var5 = new NBTTagCompound("Village");
+ var4.writeVillageDataToNBT(var5);
+ var2.appendTag(var5);
+ }
+
+ par1NBTTagCompound.setTag("Villages", var2);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/VillageDoorInfo.java b/sp-server/src/main/java/net/minecraft/src/VillageDoorInfo.java
new file mode 100644
index 0000000..260bc82
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/VillageDoorInfo.java
@@ -0,0 +1,72 @@
+package net.minecraft.src;
+
+public class VillageDoorInfo {
+ public final int posX;
+ public final int posY;
+ public final int posZ;
+ public final int insideDirectionX;
+ public final int insideDirectionZ;
+ public int lastActivityTimestamp;
+ public boolean isDetachedFromVillageFlag = false;
+ private int doorOpeningRestrictionCounter = 0;
+
+ public VillageDoorInfo(int par1, int par2, int par3, int par4, int par5, int par6) {
+ this.posX = par1;
+ this.posY = par2;
+ this.posZ = par3;
+ this.insideDirectionX = par4;
+ this.insideDirectionZ = par5;
+ this.lastActivityTimestamp = par6;
+ }
+
+ /**
+ * Returns the squared distance between this door and the given coordinate.
+ */
+ public int getDistanceSquared(int par1, int par2, int par3) {
+ int var4 = par1 - this.posX;
+ int var5 = par2 - this.posY;
+ int var6 = par3 - this.posZ;
+ return var4 * var4 + var5 * var5 + var6 * var6;
+ }
+
+ /**
+ * Get the square of the distance from a location 2 blocks away from the door
+ * considered 'inside' and the given arguments
+ */
+ public int getInsideDistanceSquare(int par1, int par2, int par3) {
+ int var4 = par1 - this.posX - this.insideDirectionX;
+ int var5 = par2 - this.posY;
+ int var6 = par3 - this.posZ - this.insideDirectionZ;
+ return var4 * var4 + var5 * var5 + var6 * var6;
+ }
+
+ public int getInsidePosX() {
+ return this.posX + this.insideDirectionX;
+ }
+
+ public int getInsidePosY() {
+ return this.posY;
+ }
+
+ public int getInsidePosZ() {
+ return this.posZ + this.insideDirectionZ;
+ }
+
+ public boolean isInside(int par1, int par2) {
+ int var3 = par1 - this.posX;
+ int var4 = par2 - this.posZ;
+ return var3 * this.insideDirectionX + var4 * this.insideDirectionZ >= 0;
+ }
+
+ public void resetDoorOpeningRestrictionCounter() {
+ this.doorOpeningRestrictionCounter = 0;
+ }
+
+ public void incrementDoorOpeningRestrictionCounter() {
+ ++this.doorOpeningRestrictionCounter;
+ }
+
+ public int getDoorOpeningRestrictionCounter() {
+ return this.doorOpeningRestrictionCounter;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/VillageSiege.java b/sp-server/src/main/java/net/minecraft/src/VillageSiege.java
new file mode 100644
index 0000000..ebbd357
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/VillageSiege.java
@@ -0,0 +1,184 @@
+package net.minecraft.src;
+
+import java.util.Iterator;
+import java.util.List;
+
+public class VillageSiege {
+ private World worldObj;
+ private boolean field_75535_b = false;
+ private int field_75536_c = -1;
+ private int field_75533_d;
+ private int field_75534_e;
+
+ /** Instance of Village. */
+ private Village theVillage;
+ private int field_75532_g;
+ private int field_75538_h;
+ private int field_75539_i;
+
+ public VillageSiege(World par1World) {
+ this.worldObj = par1World;
+ }
+
+ /**
+ * Runs a single tick for the village siege
+ */
+ public void tick() {
+ boolean var1 = false;
+
+ if (var1) {
+ if (this.field_75536_c == 2) {
+ this.field_75533_d = 100;
+ return;
+ }
+ } else {
+ if (this.worldObj.isDaytime()) {
+ this.field_75536_c = 0;
+ return;
+ }
+
+ if (this.field_75536_c == 2) {
+ return;
+ }
+
+ if (this.field_75536_c == 0) {
+ float var2 = this.worldObj.getCelestialAngle(0.0F);
+
+ if ((double) var2 < 0.5D || (double) var2 > 0.501D) {
+ return;
+ }
+
+ this.field_75536_c = this.worldObj.rand.nextInt(10) == 0 ? 1 : 2;
+ this.field_75535_b = false;
+
+ if (this.field_75536_c == 2) {
+ return;
+ }
+ }
+ }
+
+ if (!this.field_75535_b) {
+ if (!this.func_75529_b()) {
+ return;
+ }
+
+ this.field_75535_b = true;
+ }
+
+ if (this.field_75534_e > 0) {
+ --this.field_75534_e;
+ } else {
+ this.field_75534_e = 2;
+
+ if (this.field_75533_d > 0) {
+ this.spawnZombie();
+ --this.field_75533_d;
+ } else {
+ this.field_75536_c = 2;
+ }
+ }
+ }
+
+ private boolean func_75529_b() {
+ List var1 = this.worldObj.playerEntities;
+ Iterator var2 = var1.iterator();
+
+ while (var2.hasNext()) {
+ EntityPlayer var3 = (EntityPlayer) var2.next();
+ this.theVillage = this.worldObj.villageCollectionObj.findNearestVillage((int) var3.posX, (int) var3.posY,
+ (int) var3.posZ, 1);
+
+ if (this.theVillage != null && this.theVillage.getNumVillageDoors() >= 10
+ && this.theVillage.getTicksSinceLastDoorAdding() >= 20 && this.theVillage.getNumVillagers() >= 20) {
+ ChunkCoordinates var4 = this.theVillage.getCenter();
+ float var5 = (float) this.theVillage.getVillageRadius();
+ boolean var6 = false;
+ int var7 = 0;
+
+ while (true) {
+ if (var7 < 10) {
+ this.field_75532_g = var4.posX + (int) ((double) (MathHelper
+ .cos(this.worldObj.rand.nextFloat() * (float) Math.PI * 2.0F) * var5) * 0.9D);
+ this.field_75538_h = var4.posY;
+ this.field_75539_i = var4.posZ + (int) ((double) (MathHelper
+ .sin(this.worldObj.rand.nextFloat() * (float) Math.PI * 2.0F) * var5) * 0.9D);
+ var6 = false;
+ Iterator var8 = this.worldObj.villageCollectionObj.getVillageList().iterator();
+
+ while (var8.hasNext()) {
+ Village var9 = (Village) var8.next();
+
+ if (var9 != this.theVillage
+ && var9.isInRange(this.field_75532_g, this.field_75538_h, this.field_75539_i)) {
+ var6 = true;
+ break;
+ }
+ }
+
+ if (var6) {
+ ++var7;
+ continue;
+ }
+ }
+
+ if (var6) {
+ return false;
+ }
+
+ Vec3 var10 = this.func_75527_a(this.field_75532_g, this.field_75538_h, this.field_75539_i);
+
+ if (var10 != null) {
+ this.field_75534_e = 0;
+ this.field_75533_d = 20;
+ return true;
+ }
+
+ break;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ private boolean spawnZombie() {
+ Vec3 var1 = this.func_75527_a(this.field_75532_g, this.field_75538_h, this.field_75539_i);
+
+ if (var1 == null) {
+ return false;
+ } else {
+ EntityZombie var2;
+
+ try {
+ var2 = new EntityZombie(this.worldObj);
+ var2.initCreature();
+ var2.setVillager(false);
+ } catch (Exception var4) {
+ var4.printStackTrace();
+ return false;
+ }
+
+ var2.setLocationAndAngles(var1.xCoord, var1.yCoord, var1.zCoord, this.worldObj.rand.nextFloat() * 360.0F,
+ 0.0F);
+ this.worldObj.spawnEntityInWorld(var2);
+ ChunkCoordinates var3 = this.theVillage.getCenter();
+ var2.setHomeArea(var3.posX, var3.posY, var3.posZ, this.theVillage.getVillageRadius());
+ return true;
+ }
+ }
+
+ private Vec3 func_75527_a(int par1, int par2, int par3) {
+ for (int var4 = 0; var4 < 10; ++var4) {
+ int var5 = par1 + this.worldObj.rand.nextInt(16) - 8;
+ int var6 = par2 + this.worldObj.rand.nextInt(6) - 3;
+ int var7 = par3 + this.worldObj.rand.nextInt(16) - 8;
+
+ if (this.theVillage.isInRange(var5, var6, var7) && SpawnerAnimals
+ .canCreatureTypeSpawnAtLocation(EnumCreatureType.monster, this.worldObj, var5, var6, var7)) {
+ this.worldObj.getWorldVec3Pool().getVecFromPool((double) var5, (double) var6, (double) var7);
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WatchableObject.java b/sp-server/src/main/java/net/minecraft/src/WatchableObject.java
new file mode 100644
index 0000000..d0bafe2
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WatchableObject.java
@@ -0,0 +1,48 @@
+package net.minecraft.src;
+
+public class WatchableObject {
+ private final int objectType;
+
+ /** id of max 31 */
+ private final int dataValueId;
+ private Object watchedObject;
+ private boolean watched;
+
+ public WatchableObject(int par1, int par2, Object par3Obj) {
+ this.dataValueId = par2;
+ this.watchedObject = par3Obj;
+ this.objectType = par1;
+ this.watched = true;
+ }
+
+ public int getDataValueId() {
+ return this.dataValueId;
+ }
+
+ public void setObject(Object par1Obj) {
+ this.watchedObject = par1Obj;
+ }
+
+ public Object getObject() {
+ return this.watchedObject;
+ }
+
+ public int getObjectType() {
+ return this.objectType;
+ }
+
+ public boolean isWatched() {
+ return this.watched;
+ }
+
+ public void setWatched(boolean par1) {
+ this.watched = par1;
+ }
+
+ /**
+ * Set whether the specified watchable object is being watched.
+ */
+ static boolean setWatchableObjectWatched(WatchableObject par0WatchableObject, boolean par1) {
+ return par0WatchableObject.watched = par1;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WeightedRandom.java b/sp-server/src/main/java/net/minecraft/src/WeightedRandom.java
new file mode 100644
index 0000000..73a8c01
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WeightedRandom.java
@@ -0,0 +1,103 @@
+package net.minecraft.src;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class WeightedRandom {
+ /**
+ * Returns the total weight of all items in a collection.
+ */
+ public static int getTotalWeight(Collection par0Collection) {
+ int var1 = 0;
+ WeightedRandomItem var3;
+
+ for (Iterator var2 = par0Collection.iterator(); var2.hasNext(); var1 += var3.itemWeight) {
+ var3 = (WeightedRandomItem) var2.next();
+ }
+
+ return var1;
+ }
+
+ /**
+ * Returns a random choice from the input items, with a total weight value.
+ */
+ public static WeightedRandomItem getRandomItem(EaglercraftRandom par0Random, Collection par1Collection, int par2) {
+ if (par2 <= 0) {
+ throw new IllegalArgumentException();
+ } else {
+ int var3 = par0Random.nextInt(par2);
+ Iterator var4 = par1Collection.iterator();
+ WeightedRandomItem var5;
+
+ do {
+ if (!var4.hasNext()) {
+ return null;
+ }
+
+ var5 = (WeightedRandomItem) var4.next();
+ var3 -= var5.itemWeight;
+ } while (var3 >= 0);
+
+ return var5;
+ }
+ }
+
+ /**
+ * Returns a random choice from the input items.
+ */
+ public static WeightedRandomItem getRandomItem(EaglercraftRandom par0Random, Collection par1Collection) {
+ return getRandomItem(par0Random, par1Collection, getTotalWeight(par1Collection));
+ }
+
+ /**
+ * Returns the total weight of all items in a array.
+ */
+ public static int getTotalWeight(WeightedRandomItem[] par0ArrayOfWeightedRandomItem) {
+ int var1 = 0;
+ WeightedRandomItem[] var2 = par0ArrayOfWeightedRandomItem;
+ int var3 = par0ArrayOfWeightedRandomItem.length;
+
+ for (int var4 = 0; var4 < var3; ++var4) {
+ WeightedRandomItem var5 = var2[var4];
+ var1 += var5.itemWeight;
+ }
+
+ return var1;
+ }
+
+ /**
+ * Returns a random choice from the input array of items, with a total weight
+ * value.
+ */
+ public static WeightedRandomItem getRandomItem(EaglercraftRandom par0Random,
+ WeightedRandomItem[] par1ArrayOfWeightedRandomItem, int par2) {
+ if (par2 <= 0) {
+ throw new IllegalArgumentException();
+ } else {
+ int var3 = par0Random.nextInt(par2);
+ WeightedRandomItem[] var4 = par1ArrayOfWeightedRandomItem;
+ int var5 = par1ArrayOfWeightedRandomItem.length;
+
+ for (int var6 = 0; var6 < var5; ++var6) {
+ WeightedRandomItem var7 = var4[var6];
+ var3 -= var7.itemWeight;
+
+ if (var3 < 0) {
+ return var7;
+ }
+ }
+
+ return null;
+ }
+ }
+
+ /**
+ * Returns a random choice from the input items.
+ */
+ public static WeightedRandomItem getRandomItem(EaglercraftRandom par0Random,
+ WeightedRandomItem[] par1ArrayOfWeightedRandomItem) {
+ return getRandomItem(par0Random, par1ArrayOfWeightedRandomItem, getTotalWeight(par1ArrayOfWeightedRandomItem));
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WeightedRandomChestContent.java b/sp-server/src/main/java/net/minecraft/src/WeightedRandomChestContent.java
new file mode 100644
index 0000000..6ebdc99
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WeightedRandomChestContent.java
@@ -0,0 +1,104 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class WeightedRandomChestContent extends WeightedRandomItem {
+ /** The Item/Block ID to generate in the Chest. */
+ private ItemStack theItemId = null;
+
+ /** The minimum chance of item generating. */
+ private int theMinimumChanceToGenerateItem;
+
+ /** The maximum chance of item generating. */
+ private int theMaximumChanceToGenerateItem;
+
+ public WeightedRandomChestContent(int par1, int par2, int par3, int par4, int par5) {
+ super(par5);
+ this.theItemId = new ItemStack(par1, 1, par2);
+ this.theMinimumChanceToGenerateItem = par3;
+ this.theMaximumChanceToGenerateItem = par4;
+ }
+
+ public WeightedRandomChestContent(ItemStack par1ItemStack, int par2, int par3, int par4) {
+ super(par4);
+ this.theItemId = par1ItemStack;
+ this.theMinimumChanceToGenerateItem = par2;
+ this.theMaximumChanceToGenerateItem = par3;
+ }
+
+ /**
+ * Generates the Chest contents.
+ */
+ public static void generateChestContents(EaglercraftRandom par0Random,
+ WeightedRandomChestContent[] par1ArrayOfWeightedRandomChestContent, IInventory par2IInventory, int par3) {
+ for (int var4 = 0; var4 < par3; ++var4) {
+ WeightedRandomChestContent var5 = (WeightedRandomChestContent) WeightedRandom.getRandomItem(par0Random,
+ par1ArrayOfWeightedRandomChestContent);
+ int var6 = var5.theMinimumChanceToGenerateItem
+ + par0Random.nextInt(var5.theMaximumChanceToGenerateItem - var5.theMinimumChanceToGenerateItem + 1);
+
+ if (var5.theItemId.getMaxStackSize() >= var6) {
+ ItemStack var7 = var5.theItemId.copy();
+ var7.stackSize = var6;
+ par2IInventory.setInventorySlotContents(par0Random.nextInt(par2IInventory.getSizeInventory()), var7);
+ } else {
+ for (int var9 = 0; var9 < var6; ++var9) {
+ ItemStack var8 = var5.theItemId.copy();
+ var8.stackSize = 1;
+ par2IInventory.setInventorySlotContents(par0Random.nextInt(par2IInventory.getSizeInventory()),
+ var8);
+ }
+ }
+ }
+ }
+
+ /**
+ * Generates the Dispenser contents.
+ */
+ public static void generateDispenserContents(EaglercraftRandom par0Random,
+ WeightedRandomChestContent[] par1ArrayOfWeightedRandomChestContent,
+ TileEntityDispenser par2TileEntityDispenser, int par3) {
+ for (int var4 = 0; var4 < par3; ++var4) {
+ WeightedRandomChestContent var5 = (WeightedRandomChestContent) WeightedRandom.getRandomItem(par0Random,
+ par1ArrayOfWeightedRandomChestContent);
+ int var6 = var5.theMinimumChanceToGenerateItem
+ + par0Random.nextInt(var5.theMaximumChanceToGenerateItem - var5.theMinimumChanceToGenerateItem + 1);
+
+ if (var5.theItemId.getMaxStackSize() >= var6) {
+ ItemStack var7 = var5.theItemId.copy();
+ var7.stackSize = var6;
+ par2TileEntityDispenser
+ .setInventorySlotContents(par0Random.nextInt(par2TileEntityDispenser.getSizeInventory()), var7);
+ } else {
+ for (int var9 = 0; var9 < var6; ++var9) {
+ ItemStack var8 = var5.theItemId.copy();
+ var8.stackSize = 1;
+ par2TileEntityDispenser.setInventorySlotContents(
+ par0Random.nextInt(par2TileEntityDispenser.getSizeInventory()), var8);
+ }
+ }
+ }
+ }
+
+ public static WeightedRandomChestContent[] func_92080_a(
+ WeightedRandomChestContent[] par0ArrayOfWeightedRandomChestContent,
+ WeightedRandomChestContent... par1ArrayOfWeightedRandomChestContent) {
+ WeightedRandomChestContent[] var2 = new WeightedRandomChestContent[par0ArrayOfWeightedRandomChestContent.length
+ + par1ArrayOfWeightedRandomChestContent.length];
+ int var3 = 0;
+
+ for (int var4 = 0; var4 < par0ArrayOfWeightedRandomChestContent.length; ++var4) {
+ var2[var3++] = par0ArrayOfWeightedRandomChestContent[var4];
+ }
+
+ WeightedRandomChestContent[] var8 = par1ArrayOfWeightedRandomChestContent;
+ int var5 = par1ArrayOfWeightedRandomChestContent.length;
+
+ for (int var6 = 0; var6 < var5; ++var6) {
+ WeightedRandomChestContent var7 = var8[var6];
+ var2[var3++] = var7;
+ }
+
+ return var2;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WeightedRandomItem.java b/sp-server/src/main/java/net/minecraft/src/WeightedRandomItem.java
new file mode 100644
index 0000000..d7d90ab
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WeightedRandomItem.java
@@ -0,0 +1,13 @@
+package net.minecraft.src;
+
+public class WeightedRandomItem {
+ /**
+ * The Weight is how often the item is chosen(higher number is higher
+ * chance(lower is lower))
+ */
+ protected int itemWeight;
+
+ public WeightedRandomItem(int par1) {
+ this.itemWeight = par1;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WeightedRandomMinecart.java b/sp-server/src/main/java/net/minecraft/src/WeightedRandomMinecart.java
new file mode 100644
index 0000000..133b88e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WeightedRandomMinecart.java
@@ -0,0 +1,73 @@
+package net.minecraft.src;
+
+public class WeightedRandomMinecart extends WeightedRandomItem {
+ public final NBTTagCompound field_98222_b;
+ public final String minecartName;
+
+ final MobSpawnerBaseLogic field_98221_d;
+
+ public WeightedRandomMinecart(MobSpawnerBaseLogic par1MobSpawnerBaseLogic, NBTTagCompound par2NBTTagCompound) {
+ super(par2NBTTagCompound.getInteger("Weight"));
+ this.field_98221_d = par1MobSpawnerBaseLogic;
+ NBTTagCompound var3 = par2NBTTagCompound.getCompoundTag("Properties");
+ String var4 = par2NBTTagCompound.getString("Type");
+
+ if (var4.equals("Minecart")) {
+ if (var3 != null) {
+ switch (var3.getInteger("Type")) {
+ case 0:
+ var4 = "MinecartRideable";
+ break;
+
+ case 1:
+ var4 = "MinecartChest";
+ break;
+
+ case 2:
+ var4 = "MinecartFurnace";
+ }
+ } else {
+ var4 = "MinecartRideable";
+ }
+ }
+
+ this.field_98222_b = var3;
+ this.minecartName = var4;
+ }
+
+ public WeightedRandomMinecart(MobSpawnerBaseLogic par1MobSpawnerBaseLogic, NBTTagCompound par2NBTTagCompound,
+ String par3Str) {
+ super(1);
+ this.field_98221_d = par1MobSpawnerBaseLogic;
+
+ if (par3Str.equals("Minecart")) {
+ if (par2NBTTagCompound != null) {
+ switch (par2NBTTagCompound.getInteger("Type")) {
+ case 0:
+ par3Str = "MinecartRideable";
+ break;
+
+ case 1:
+ par3Str = "MinecartChest";
+ break;
+
+ case 2:
+ par3Str = "MinecartFurnace";
+ }
+ } else {
+ par3Str = "MinecartRideable";
+ }
+ }
+
+ this.field_98222_b = par2NBTTagCompound;
+ this.minecartName = par3Str;
+ }
+
+ public NBTTagCompound func_98220_a() {
+ NBTTagCompound var1 = new NBTTagCompound();
+ var1.setCompoundTag("Properties", this.field_98222_b);
+ var1.setString("Type", this.minecartName);
+ var1.setInteger("Weight", this.itemWeight);
+ return var1;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/World.java b/sp-server/src/main/java/net/minecraft/src/World.java
new file mode 100644
index 0000000..9e98202
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/World.java
@@ -0,0 +1,3173 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.function.Function;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public abstract class World implements IBlockAccess {
+ /**
+ * boolean; if true updates scheduled by scheduleBlockUpdate happen immediately
+ */
+ public boolean scheduledUpdatesAreImmediate = false;
+
+ /** A list of all Entities in all currently-loaded chunks */
+ public List loadedEntityList = new ArrayList();
+ protected List unloadedEntityList = new ArrayList();
+
+ /** A list of all TileEntities in all currently-loaded chunks */
+ public List loadedTileEntityList = new ArrayList();
+ private List addedTileEntityList = new ArrayList();
+
+ /** Entities marked for removal. */
+ private List entityRemoval = new ArrayList();
+
+ /** Array list of players in the world. */
+ public List playerEntities = new ArrayList();
+
+ /** a list of all the lightning entities */
+ public List weatherEffects = new ArrayList();
+ private long cloudColour = 16777215L;
+
+ /** How much light is subtracted from full daylight */
+ public int skylightSubtracted = 0;
+
+ /**
+ * Contains the current Linear Congruential Generator seed for block updates.
+ * Used with an A value of 3 and a C value of 0x3c6ef35f, producing a highly
+ * planar series of values ill-suited for choosing random blocks in a 16x128x16
+ * field.
+ */
+ protected int updateLCG = (new EaglercraftRandom()).nextInt();
+
+ /**
+ * magic number used to generate fast random numbers for 3d distribution within
+ * a chunk
+ */
+ protected final int DIST_HASH_MAGIC = 1013904223;
+ protected float prevRainingStrength;
+ protected float rainingStrength;
+ protected float prevThunderingStrength;
+ protected float thunderingStrength;
+
+ /**
+ * Set to 2 whenever a lightning bolt is generated in SSP. Decrements if > 0 in
+ * updateWeather(). Value appears to be unused.
+ */
+ public int lastLightningBolt = 0;
+
+ /** Whether monsters are enabled or not. (1 = on, 0 = off) */
+ public int difficultySetting;
+
+ /** RNG for World. */
+ public EaglercraftRandom rand = new EaglercraftRandom();
+
+ /** The WorldProvider instance that World uses. */
+ public final WorldProvider provider;
+ protected List worldAccesses = new ArrayList();
+
+ /** Handles chunk operations and caching */
+ protected IChunkProvider chunkProvider;
+ protected final ISaveHandler saveHandler;
+
+ /**
+ * holds information about a world (size on disk, time, spawn point, seed, ...)
+ */
+ protected WorldInfo worldInfo;
+
+ /**
+ * if set, this flag forces a request to load a chunk to load the chunk rather
+ * than defaulting to the world's chunkprovider's dummy if possible
+ */
+ public boolean findingSpawnPoint;
+ public MapStorage mapStorage;
+ public final VillageCollection villageCollectionObj;
+ protected final VillageSiege villageSiegeObj = new VillageSiege(this);
+
+ /** The world-local pool of vectors */
+ private final Vec3Pool vecPool = new Vec3Pool(300, 2000);
+ private final Calendar theCalendar = Calendar.getInstance();
+ protected Scoreboard worldScoreboard = new Scoreboard();
+
+ /** The log agent for this world. */
+ private final ILogAgent worldLogAgent;
+ private ArrayList collidingBoundingBoxes = new ArrayList();
+ private boolean scanningTileEntities;
+
+ /** indicates if enemies are spawned or not */
+ protected boolean spawnHostileMobs = true;
+
+ /** A flag indicating whether we should spawn peaceful mobs. */
+ protected boolean spawnPeacefulMobs = true;
+
+ /** populated by chunks that are within 9 chunks of any player */
+ protected Set activeChunkSet = new HashSet();
+
+ /** number of ticks until the next random ambients play */
+ private int ambientTickCountdown;
+
+ /**
+ * is a temporary list of blocks and light values used when updating light
+ * levels. Holds up to 32x32x32 blocks (the maximum influence of a light
+ * source.) Every element is a packed bit value:
+ * 0000000000LLLLzzzzzzyyyyyyxxxxxx. The 4-bit L is a light level used when
+ * darkening blocks. 6-bit numbers x, y and z represent the block's offset from
+ * the original block, plus 32 (i.e. value of 31 would mean a -1 offset
+ */
+ int[] lightUpdateBlockList;
+
+ /** This is set to true for client worlds, and false for server worlds. */
+ public boolean isRemote;
+
+ /**
+ * Gets the biome for a given set of x/z coordinates
+ */
+ public BiomeGenBase getBiomeGenForCoords(int par1, int par2) {
+ if (this.blockExists(par1, 0, par2)) {
+ Chunk var3 = this.getChunkFromBlockCoords(par1, par2);
+
+ if (var3 != null) {
+ return var3.getBiomeGenForWorldCoords(par1 & 15, par2 & 15, this.provider.worldChunkMgr);
+ }
+ }
+
+ return this.provider.worldChunkMgr.getBiomeGenAt(par1, par2);
+ }
+
+ public WorldChunkManager getWorldChunkManager() {
+ return this.provider.worldChunkMgr;
+ }
+
+ public World(ISaveHandler par1ISaveHandler, String par2Str, WorldSettings par3WorldSettings,
+ WorldProvider par4WorldProvider, ILogAgent par6ILogAgent) {
+ this.ambientTickCountdown = this.rand.nextInt(12000);
+ this.lightUpdateBlockList = new int[32768];
+ this.isRemote = false;
+ this.saveHandler = par1ISaveHandler;
+ this.mapStorage = new MapStorage(par1ISaveHandler);
+ this.worldLogAgent = par6ILogAgent;
+ this.worldInfo = par1ISaveHandler.loadWorldInfo();
+
+ if (par4WorldProvider != null) {
+ this.provider = par4WorldProvider;
+ } else if (this.worldInfo != null && this.worldInfo.getDimension() != 0) {
+ this.provider = WorldProvider.getProviderForDimension(this.worldInfo.getDimension());
+ } else {
+ this.provider = WorldProvider.getProviderForDimension(0);
+ }
+
+ if (this.worldInfo == null) {
+ this.worldInfo = new WorldInfo(par3WorldSettings, par2Str);
+ } else {
+ this.worldInfo.setWorldName(par2Str);
+ }
+
+ this.provider.registerWorld(this);
+ this.chunkProvider = this.createChunkProvider();
+
+ if (!this.worldInfo.isInitialized()) {
+ this.initialize(par3WorldSettings);
+ this.worldInfo.setServerInitialized(true);
+ }
+
+ VillageCollection var7 = (VillageCollection) this.mapStorage.loadData((s) -> new VillageCollection(s), "villages");
+
+ if (var7 == null) {
+ this.villageCollectionObj = new VillageCollection(this);
+ this.mapStorage.setData("villages", this.villageCollectionObj);
+ } else {
+ this.villageCollectionObj = var7;
+ this.villageCollectionObj.func_82566_a(this);
+ }
+
+ this.calculateInitialSkylight();
+ this.calculateInitialWeather();
+ }
+
+ /**
+ * Creates the chunk provider for this world. Called in the constructor.
+ * Retrieves provider from worldProvider?
+ */
+ protected abstract IChunkProvider createChunkProvider();
+
+ protected void initialize(WorldSettings par1WorldSettings) {
+ this.worldInfo.setServerInitialized(true);
+ }
+
+ /**
+ * Returns the block ID of the first block at this (x,z) location with air above
+ * it, searching from sea level upwards.
+ */
+ public int getFirstUncoveredBlock(int par1, int par2) {
+ int var3;
+
+ for (var3 = 63; !this.isAirBlock(par1, var3 + 1, par2); ++var3) {
+ ;
+ }
+
+ return this.getBlockId(par1, var3, par2);
+ }
+
+ /**
+ * Returns the block ID at coords x,y,z
+ */
+ public int getBlockId(int par1, int par2, int par3) {
+ if (par1 >= -30000000 && par3 >= -30000000 && par1 < 30000000 && par3 < 30000000) {
+ if (par2 < 0) {
+ return 0;
+ } else if (par2 >= 256) {
+ return 0;
+ } else {
+ Chunk var4 = this.getChunkFromChunkCoords(par1 >> 4, par3 >> 4);
+ return var4.getBlockID(par1 & 15, par2, par3 & 15);
+ }
+ } else {
+ return 0;
+ }
+ }
+
+ /**
+ * Returns true if the block at the specified coordinates is empty
+ */
+ public boolean isAirBlock(int par1, int par2, int par3) {
+ return this.getBlockId(par1, par2, par3) == 0;
+ }
+
+ /**
+ * Checks if a block at a given position should have a tile entity.
+ */
+ public boolean blockHasTileEntity(int par1, int par2, int par3) {
+ int var4 = this.getBlockId(par1, par2, par3);
+ return Block.blocksList[var4] != null && Block.blocksList[var4].hasTileEntity();
+ }
+
+ /**
+ * Returns the render type of the block at the given coordinate.
+ */
+ public int blockGetRenderType(int par1, int par2, int par3) {
+ int var4 = this.getBlockId(par1, par2, par3);
+ return Block.blocksList[var4] != null ? Block.blocksList[var4].getRenderType() : -1;
+ }
+
+ /**
+ * Returns whether a block exists at world coordinates x, y, z
+ */
+ public boolean blockExists(int par1, int par2, int par3) {
+ return par2 >= 0 && par2 < 256 ? this.chunkExists(par1 >> 4, par3 >> 4) : false;
+ }
+
+ /**
+ * Checks if any of the chunks within distance (argument 4) blocks of the given
+ * block exist
+ */
+ public boolean doChunksNearChunkExist(int par1, int par2, int par3, int par4) {
+ return this.checkChunksExist(par1 - par4, par2 - par4, par3 - par4, par1 + par4, par2 + par4, par3 + par4);
+ }
+
+ /**
+ * Checks between a min and max all the chunks inbetween actually exist. Args:
+ * minX, minY, minZ, maxX, maxY, maxZ
+ */
+ public boolean checkChunksExist(int par1, int par2, int par3, int par4, int par5, int par6) {
+ if (par5 >= 0 && par2 < 256) {
+ par1 >>= 4;
+ par3 >>= 4;
+ par4 >>= 4;
+ par6 >>= 4;
+
+ for (int var7 = par1; var7 <= par4; ++var7) {
+ for (int var8 = par3; var8 <= par6; ++var8) {
+ if (!this.chunkExists(var7, var8)) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Returns whether a chunk exists at chunk coordinates x, y
+ */
+ protected boolean chunkExists(int par1, int par2) {
+ return this.chunkProvider.chunkExists(par1, par2);
+ }
+
+ /**
+ * Returns a chunk looked up by block coordinates. Args: x, z
+ */
+ public Chunk getChunkFromBlockCoords(int par1, int par2) {
+ return this.getChunkFromChunkCoords(par1 >> 4, par2 >> 4);
+ }
+
+ /**
+ * Returns back a chunk looked up by chunk coordinates Args: x, y
+ */
+ public Chunk getChunkFromChunkCoords(int par1, int par2) {
+ return this.chunkProvider.provideChunk(par1, par2);
+ }
+
+ /**
+ * Sets the block ID and metadata at a given location. Args: X, Y, Z, new block
+ * ID, new metadata, flags. Flag 1 will cause a block update. Flag 2 will send
+ * the change to clients (you almost always want this). Flag 4 prevents the
+ * block from being re-rendered, if this is a client world. Flags can be added
+ * together.
+ */
+ public boolean setBlock(int par1, int par2, int par3, int par4, int par5, int par6) {
+ if (par1 >= -30000000 && par3 >= -30000000 && par1 < 30000000 && par3 < 30000000) {
+ if (par2 < 0) {
+ return false;
+ } else if (par2 >= 256) {
+ return false;
+ } else {
+ Chunk var7 = this.getChunkFromChunkCoords(par1 >> 4, par3 >> 4);
+ int var8 = 0;
+
+ if ((par6 & 1) != 0) {
+ var8 = var7.getBlockID(par1 & 15, par2, par3 & 15);
+ }
+
+ boolean var9 = var7.setBlockIDWithMetadata(par1 & 15, par2, par3 & 15, par4, par5);
+ this.updateAllLightTypes(par1, par2, par3);
+
+ if (var9) {
+ if ((par6 & 2) != 0 && (!this.isRemote || (par6 & 4) == 0)) {
+ this.markBlockForUpdate(par1, par2, par3);
+ }
+
+ if (!this.isRemote && (par6 & 1) != 0) {
+ this.notifyBlockChange(par1, par2, par3, var8);
+ Block var10 = Block.blocksList[par4];
+
+ if (var10 != null && var10.hasComparatorInputOverride()) {
+ this.func_96440_m(par1, par2, par3, par4);
+ }
+ }
+ }
+
+ return var9;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Returns the block's material.
+ */
+ public Material getBlockMaterial(int par1, int par2, int par3) {
+ int var4 = this.getBlockId(par1, par2, par3);
+ return var4 == 0 ? Material.air : Block.blocksList[var4].blockMaterial;
+ }
+
+ /**
+ * Returns the block metadata at coords x,y,z
+ */
+ public int getBlockMetadata(int par1, int par2, int par3) {
+ if (par1 >= -30000000 && par3 >= -30000000 && par1 < 30000000 && par3 < 30000000) {
+ if (par2 < 0) {
+ return 0;
+ } else if (par2 >= 256) {
+ return 0;
+ } else {
+ Chunk var4 = this.getChunkFromChunkCoords(par1 >> 4, par3 >> 4);
+ par1 &= 15;
+ par3 &= 15;
+ return var4.getBlockMetadata(par1, par2, par3);
+ }
+ } else {
+ return 0;
+ }
+ }
+
+ /**
+ * Sets the blocks metadata and if set will then notify blocks that this block
+ * changed, depending on the flag. Args: x, y, z, metadata, flag. See setBlock
+ * for flag description
+ */
+ public boolean setBlockMetadata(int par1, int par2, int par3, int par4, int par5) {
+ if (par1 >= -30000000 && par3 >= -30000000 && par1 < 30000000 && par3 < 30000000) {
+ if (par2 < 0) {
+ return false;
+ } else if (par2 >= 256) {
+ return false;
+ } else {
+ Chunk var6 = this.getChunkFromChunkCoords(par1 >> 4, par3 >> 4);
+ int var7 = par1 & 15;
+ int var8 = par3 & 15;
+ boolean var9 = var6.setBlockMetadata(var7, par2, var8, par4);
+
+ if (var9) {
+ int var10 = var6.getBlockID(var7, par2, var8);
+
+ if ((par5 & 2) != 0 && (!this.isRemote || (par5 & 4) == 0)) {
+ this.markBlockForUpdate(par1, par2, par3);
+ }
+
+ if (!this.isRemote && (par5 & 1) != 0) {
+ this.notifyBlockChange(par1, par2, par3, var10);
+ Block var11 = Block.blocksList[var10];
+
+ if (var11 != null && var11.hasComparatorInputOverride()) {
+ this.func_96440_m(par1, par2, par3, var10);
+ }
+ }
+ }
+
+ return var9;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Sets a block to 0 and notifies relevant systems with the block change Args:
+ * x, y, z
+ */
+ public boolean setBlockToAir(int par1, int par2, int par3) {
+ return this.setBlock(par1, par2, par3, 0, 0, 3);
+ }
+
+ /**
+ * Destroys a block and optionally drops items. Args: X, Y, Z, dropItems
+ */
+ public boolean destroyBlock(int par1, int par2, int par3, boolean par4) {
+ int var5 = this.getBlockId(par1, par2, par3);
+
+ if (var5 > 0) {
+ int var6 = this.getBlockMetadata(par1, par2, par3);
+ this.playAuxSFX(2001, par1, par2, par3, var5 + (var6 << 12));
+
+ if (par4) {
+ Block.blocksList[var5].dropBlockAsItem(this, par1, par2, par3, var6, 0);
+ }
+
+ return this.setBlock(par1, par2, par3, 0, 0, 3);
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Sets a block and notifies relevant systems with the block change Args: x, y,
+ * z, blockID
+ */
+ public boolean setBlock(int par1, int par2, int par3, int par4) {
+ return this.setBlock(par1, par2, par3, par4, 0, 3);
+ }
+
+ /**
+ * On the client, re-renders the block. On the server, sends the block to the
+ * client (which will re-render it), including the tile entity description
+ * packet if applicable. Args: x, y, z
+ */
+ public void markBlockForUpdate(int par1, int par2, int par3) {
+ for (int var4 = 0; var4 < this.worldAccesses.size(); ++var4) {
+ ((IWorldAccess) this.worldAccesses.get(var4)).markBlockForUpdate(par1, par2, par3);
+ }
+ }
+
+ /**
+ * The block type change and need to notify other systems Args: x, y, z, blockID
+ */
+ public void notifyBlockChange(int par1, int par2, int par3, int par4) {
+ this.notifyBlocksOfNeighborChange(par1, par2, par3, par4);
+ }
+
+ /**
+ * marks a vertical line of blocks as dirty
+ */
+ public void markBlocksDirtyVertical(int par1, int par2, int par3, int par4) {
+ int var5;
+
+ if (par3 > par4) {
+ var5 = par4;
+ par4 = par3;
+ par3 = var5;
+ }
+
+ if (!this.provider.hasNoSky) {
+ for (var5 = par3; var5 <= par4; ++var5) {
+ this.updateLightByType(EnumSkyBlock.Sky, par1, var5, par2);
+ }
+ }
+
+ this.markBlockRangeForRenderUpdate(par1, par3, par2, par1, par4, par2);
+ }
+
+ /**
+ * On the client, re-renders all blocks in this range, inclusive. On the server,
+ * does nothing. Args: min x, min y, min z, max x, max y, max z
+ */
+ public void markBlockRangeForRenderUpdate(int par1, int par2, int par3, int par4, int par5, int par6) {
+ for (int var7 = 0; var7 < this.worldAccesses.size(); ++var7) {
+ ((IWorldAccess) this.worldAccesses.get(var7)).markBlockRangeForRenderUpdate(par1, par2, par3, par4, par5,
+ par6);
+ }
+ }
+
+ /**
+ * Notifies neighboring blocks that this specified block changed Args: x, y, z,
+ * blockID
+ */
+ public void notifyBlocksOfNeighborChange(int par1, int par2, int par3, int par4) {
+ this.notifyBlockOfNeighborChange(par1 - 1, par2, par3, par4);
+ this.notifyBlockOfNeighborChange(par1 + 1, par2, par3, par4);
+ this.notifyBlockOfNeighborChange(par1, par2 - 1, par3, par4);
+ this.notifyBlockOfNeighborChange(par1, par2 + 1, par3, par4);
+ this.notifyBlockOfNeighborChange(par1, par2, par3 - 1, par4);
+ this.notifyBlockOfNeighborChange(par1, par2, par3 + 1, par4);
+ }
+
+ /**
+ * Calls notifyBlockOfNeighborChange on adjacent blocks, except the one on the
+ * given side. Args: X, Y, Z, changingBlockID, side
+ */
+ public void notifyBlocksOfNeighborChange(int par1, int par2, int par3, int par4, int par5) {
+ if (par5 != 4) {
+ this.notifyBlockOfNeighborChange(par1 - 1, par2, par3, par4);
+ }
+
+ if (par5 != 5) {
+ this.notifyBlockOfNeighborChange(par1 + 1, par2, par3, par4);
+ }
+
+ if (par5 != 0) {
+ this.notifyBlockOfNeighborChange(par1, par2 - 1, par3, par4);
+ }
+
+ if (par5 != 1) {
+ this.notifyBlockOfNeighborChange(par1, par2 + 1, par3, par4);
+ }
+
+ if (par5 != 2) {
+ this.notifyBlockOfNeighborChange(par1, par2, par3 - 1, par4);
+ }
+
+ if (par5 != 3) {
+ this.notifyBlockOfNeighborChange(par1, par2, par3 + 1, par4);
+ }
+ }
+
+ /**
+ * Notifies a block that one of its neighbor change to the specified type Args:
+ * x, y, z, blockID
+ */
+ public void notifyBlockOfNeighborChange(int par1, int par2, int par3, int par4) {
+ if (!this.isRemote) {
+ int var5 = this.getBlockId(par1, par2, par3);
+ Block var6 = Block.blocksList[var5];
+
+ if (var6 != null) {
+ var6.onNeighborBlockChange(this, par1, par2, par3, par4);
+ }
+ }
+ }
+
+ /**
+ * Returns true if the given block will receive a scheduled tick in the future.
+ * Args: X, Y, Z, blockID
+ */
+ public boolean isBlockTickScheduled(int par1, int par2, int par3, int par4) {
+ return false;
+ }
+
+ /**
+ * Checks if the specified block is able to see the sky
+ */
+ public boolean canBlockSeeTheSky(int par1, int par2, int par3) {
+ return this.getChunkFromChunkCoords(par1 >> 4, par3 >> 4).canBlockSeeTheSky(par1 & 15, par2, par3 & 15);
+ }
+
+ /**
+ * gets the block's light value - without the _do function's checks.
+ */
+ public int getFullBlockLightValue(int par1, int par2, int par3) {
+ if (par2 < 0) {
+ return 0;
+ } else {
+ if (par2 >= 256) {
+ par2 = 255;
+ }
+
+ return this.getChunkFromChunkCoords(par1 >> 4, par3 >> 4).getBlockLightValue(par1 & 15, par2, par3 & 15, 0);
+ }
+ }
+
+ /**
+ * Gets the light value of a block location
+ */
+ public int getBlockLightValue(int par1, int par2, int par3) {
+ return this.getBlockLightValue_do(par1, par2, par3, true);
+ }
+
+ /**
+ * Gets the light value of a block location. This is the actual function that
+ * gets the value and has a bool flag that indicates if its a half step block to
+ * get the maximum light value of a direct neighboring block (left, right,
+ * forward, back, and up)
+ */
+ public int getBlockLightValue_do(int par1, int par2, int par3, boolean par4) {
+ if (par1 >= -30000000 && par3 >= -30000000 && par1 < 30000000 && par3 < 30000000) {
+ if (par4) {
+ int var5 = this.getBlockId(par1, par2, par3);
+
+ if (Block.useNeighborBrightness[var5]) {
+ int var6 = this.getBlockLightValue_do(par1, par2 + 1, par3, false);
+ int var7 = this.getBlockLightValue_do(par1 + 1, par2, par3, false);
+ int var8 = this.getBlockLightValue_do(par1 - 1, par2, par3, false);
+ int var9 = this.getBlockLightValue_do(par1, par2, par3 + 1, false);
+ int var10 = this.getBlockLightValue_do(par1, par2, par3 - 1, false);
+
+ if (var7 > var6) {
+ var6 = var7;
+ }
+
+ if (var8 > var6) {
+ var6 = var8;
+ }
+
+ if (var9 > var6) {
+ var6 = var9;
+ }
+
+ if (var10 > var6) {
+ var6 = var10;
+ }
+
+ return var6;
+ }
+ }
+
+ if (par2 < 0) {
+ return 0;
+ } else {
+ if (par2 >= 256) {
+ par2 = 255;
+ }
+
+ Chunk var11 = this.getChunkFromChunkCoords(par1 >> 4, par3 >> 4);
+ par1 &= 15;
+ par3 &= 15;
+ return var11.getBlockLightValue(par1, par2, par3, this.skylightSubtracted);
+ }
+ } else {
+ return 15;
+ }
+ }
+
+ /**
+ * Returns the y coordinate with a block in it at this x, z coordinate
+ */
+ public int getHeightValue(int par1, int par2) {
+ if (par1 >= -30000000 && par2 >= -30000000 && par1 < 30000000 && par2 < 30000000) {
+ if (!this.chunkExists(par1 >> 4, par2 >> 4)) {
+ return 0;
+ } else {
+ Chunk var3 = this.getChunkFromChunkCoords(par1 >> 4, par2 >> 4);
+ return var3.getHeightValue(par1 & 15, par2 & 15);
+ }
+ } else {
+ return 0;
+ }
+ }
+
+ /**
+ * Gets the heightMapMinimum field of the given chunk, or 0 if the chunk is not
+ * loaded. Coords are in blocks. Args: X, Z
+ */
+ public int getChunkHeightMapMinimum(int par1, int par2) {
+ if (par1 >= -30000000 && par2 >= -30000000 && par1 < 30000000 && par2 < 30000000) {
+ if (!this.chunkExists(par1 >> 4, par2 >> 4)) {
+ return 0;
+ } else {
+ Chunk var3 = this.getChunkFromChunkCoords(par1 >> 4, par2 >> 4);
+ return var3.heightMapMinimum;
+ }
+ } else {
+ return 0;
+ }
+ }
+
+ /**
+ * Returns saved light value without taking into account the time of day. Either
+ * looks in the sky light map or block light map based on the enumSkyBlock arg.
+ */
+ public int getSavedLightValue(EnumSkyBlock par1EnumSkyBlock, int par2, int par3, int par4) {
+ if (par3 < 0) {
+ par3 = 0;
+ }
+
+ if (par3 >= 256) {
+ par3 = 255;
+ }
+
+ if (par2 >= -30000000 && par4 >= -30000000 && par2 < 30000000 && par4 < 30000000) {
+ int var5 = par2 >> 4;
+ int var6 = par4 >> 4;
+
+ if (!this.chunkExists(var5, var6)) {
+ return par1EnumSkyBlock.defaultLightValue;
+ } else {
+ Chunk var7 = this.getChunkFromChunkCoords(var5, var6);
+ return var7.getSavedLightValue(par1EnumSkyBlock, par2 & 15, par3, par4 & 15);
+ }
+ } else {
+ return par1EnumSkyBlock.defaultLightValue;
+ }
+ }
+
+ /**
+ * Sets the light value either into the sky map or block map depending on if
+ * enumSkyBlock is set to sky or block. Args: enumSkyBlock, x, y, z, lightValue
+ */
+ public void setLightValue(EnumSkyBlock par1EnumSkyBlock, int par2, int par3, int par4, int par5) {
+ if (par2 >= -30000000 && par4 >= -30000000 && par2 < 30000000 && par4 < 30000000) {
+ if (par3 >= 0) {
+ if (par3 < 256) {
+ if (this.chunkExists(par2 >> 4, par4 >> 4)) {
+ Chunk var6 = this.getChunkFromChunkCoords(par2 >> 4, par4 >> 4);
+ var6.setLightValue(par1EnumSkyBlock, par2 & 15, par3, par4 & 15, par5);
+
+ for (int var7 = 0; var7 < this.worldAccesses.size(); ++var7) {
+ ((IWorldAccess) this.worldAccesses.get(var7)).markBlockForRenderUpdate(par2, par3, par4);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * On the client, re-renders this block. On the server, does nothing. Used for
+ * lighting updates.
+ */
+ public void markBlockForRenderUpdate(int par1, int par2, int par3) {
+ for (int var4 = 0; var4 < this.worldAccesses.size(); ++var4) {
+ ((IWorldAccess) this.worldAccesses.get(var4)).markBlockForRenderUpdate(par1, par2, par3);
+ }
+ }
+
+ /**
+ * Returns how bright the block is shown as which is the block's light value
+ * looked up in a lookup table (light values aren't linear for brightness).
+ * Args: x, y, z
+ */
+ public float getLightBrightness(int par1, int par2, int par3) {
+ return this.provider.lightBrightnessTable[this.getBlockLightValue(par1, par2, par3)];
+ }
+
+ /**
+ * Checks whether its daytime by seeing if the light subtracted from the
+ * skylight is less than 4
+ */
+ public boolean isDaytime() {
+ return this.skylightSubtracted < 4;
+ }
+
+ /**
+ * ray traces all blocks, including non-collideable ones
+ */
+ public MovingObjectPosition rayTraceBlocks(Vec3 par1Vec3, Vec3 par2Vec3) {
+ return this.rayTraceBlocks_do_do(par1Vec3, par2Vec3, false, false);
+ }
+
+ public MovingObjectPosition rayTraceBlocks_do(Vec3 par1Vec3, Vec3 par2Vec3, boolean par3) {
+ return this.rayTraceBlocks_do_do(par1Vec3, par2Vec3, par3, false);
+ }
+
+ public MovingObjectPosition rayTraceBlocks_do_do(Vec3 par1Vec3, Vec3 par2Vec3, boolean par3, boolean par4) {
+ if (!Double.isNaN(par1Vec3.xCoord) && !Double.isNaN(par1Vec3.yCoord) && !Double.isNaN(par1Vec3.zCoord)) {
+ if (!Double.isNaN(par2Vec3.xCoord) && !Double.isNaN(par2Vec3.yCoord) && !Double.isNaN(par2Vec3.zCoord)) {
+ int var5 = MathHelper.floor_double(par2Vec3.xCoord);
+ int var6 = MathHelper.floor_double(par2Vec3.yCoord);
+ int var7 = MathHelper.floor_double(par2Vec3.zCoord);
+ int var8 = MathHelper.floor_double(par1Vec3.xCoord);
+ int var9 = MathHelper.floor_double(par1Vec3.yCoord);
+ int var10 = MathHelper.floor_double(par1Vec3.zCoord);
+ int var11 = this.getBlockId(var8, var9, var10);
+ int var12 = this.getBlockMetadata(var8, var9, var10);
+ Block var13 = Block.blocksList[var11];
+
+ if ((!par4 || var13 == null || var13.getCollisionBoundingBoxFromPool(this, var8, var9, var10) != null)
+ && var11 > 0 && var13.canCollideCheck(var12, par3)) {
+ MovingObjectPosition var14 = var13.collisionRayTrace(this, var8, var9, var10, par1Vec3, par2Vec3);
+
+ if (var14 != null) {
+ return var14;
+ }
+ }
+
+ var11 = 200;
+
+ while (var11-- >= 0) {
+ if (Double.isNaN(par1Vec3.xCoord) || Double.isNaN(par1Vec3.yCoord)
+ || Double.isNaN(par1Vec3.zCoord)) {
+ return null;
+ }
+
+ if (var8 == var5 && var9 == var6 && var10 == var7) {
+ return null;
+ }
+
+ boolean var39 = true;
+ boolean var40 = true;
+ boolean var41 = true;
+ double var15 = 999.0D;
+ double var17 = 999.0D;
+ double var19 = 999.0D;
+
+ if (var5 > var8) {
+ var15 = (double) var8 + 1.0D;
+ } else if (var5 < var8) {
+ var15 = (double) var8 + 0.0D;
+ } else {
+ var39 = false;
+ }
+
+ if (var6 > var9) {
+ var17 = (double) var9 + 1.0D;
+ } else if (var6 < var9) {
+ var17 = (double) var9 + 0.0D;
+ } else {
+ var40 = false;
+ }
+
+ if (var7 > var10) {
+ var19 = (double) var10 + 1.0D;
+ } else if (var7 < var10) {
+ var19 = (double) var10 + 0.0D;
+ } else {
+ var41 = false;
+ }
+
+ double var21 = 999.0D;
+ double var23 = 999.0D;
+ double var25 = 999.0D;
+ double var27 = par2Vec3.xCoord - par1Vec3.xCoord;
+ double var29 = par2Vec3.yCoord - par1Vec3.yCoord;
+ double var31 = par2Vec3.zCoord - par1Vec3.zCoord;
+
+ if (var39) {
+ var21 = (var15 - par1Vec3.xCoord) / var27;
+ }
+
+ if (var40) {
+ var23 = (var17 - par1Vec3.yCoord) / var29;
+ }
+
+ if (var41) {
+ var25 = (var19 - par1Vec3.zCoord) / var31;
+ }
+
+ boolean var33 = false;
+ byte var42;
+
+ if (var21 < var23 && var21 < var25) {
+ if (var5 > var8) {
+ var42 = 4;
+ } else {
+ var42 = 5;
+ }
+
+ par1Vec3.xCoord = var15;
+ par1Vec3.yCoord += var29 * var21;
+ par1Vec3.zCoord += var31 * var21;
+ } else if (var23 < var25) {
+ if (var6 > var9) {
+ var42 = 0;
+ } else {
+ var42 = 1;
+ }
+
+ par1Vec3.xCoord += var27 * var23;
+ par1Vec3.yCoord = var17;
+ par1Vec3.zCoord += var31 * var23;
+ } else {
+ if (var7 > var10) {
+ var42 = 2;
+ } else {
+ var42 = 3;
+ }
+
+ par1Vec3.xCoord += var27 * var25;
+ par1Vec3.yCoord += var29 * var25;
+ par1Vec3.zCoord = var19;
+ }
+
+ Vec3 var34 = this.getWorldVec3Pool().getVecFromPool(par1Vec3.xCoord, par1Vec3.yCoord,
+ par1Vec3.zCoord);
+ var8 = (int) (var34.xCoord = (double) MathHelper.floor_double(par1Vec3.xCoord));
+
+ if (var42 == 5) {
+ --var8;
+ ++var34.xCoord;
+ }
+
+ var9 = (int) (var34.yCoord = (double) MathHelper.floor_double(par1Vec3.yCoord));
+
+ if (var42 == 1) {
+ --var9;
+ ++var34.yCoord;
+ }
+
+ var10 = (int) (var34.zCoord = (double) MathHelper.floor_double(par1Vec3.zCoord));
+
+ if (var42 == 3) {
+ --var10;
+ ++var34.zCoord;
+ }
+
+ int var35 = this.getBlockId(var8, var9, var10);
+ int var36 = this.getBlockMetadata(var8, var9, var10);
+ Block var37 = Block.blocksList[var35];
+
+ if ((!par4 || var37 == null
+ || var37.getCollisionBoundingBoxFromPool(this, var8, var9, var10) != null) && var35 > 0
+ && var37.canCollideCheck(var36, par3)) {
+ MovingObjectPosition var38 = var37.collisionRayTrace(this, var8, var9, var10, par1Vec3,
+ par2Vec3);
+
+ if (var38 != null) {
+ return var38;
+ }
+ }
+ }
+
+ return null;
+ } else {
+ return null;
+ }
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Plays a sound at the entity's position. Args: entity, sound, volume (relative
+ * to 1.0), and frequency (or pitch, also relative to 1.0).
+ */
+ public void playSoundAtEntity(Entity par1Entity, String par2Str, float par3, float par4) {
+ if (par1Entity != null && par2Str != null) {
+ for (int var5 = 0; var5 < this.worldAccesses.size(); ++var5) {
+ ((IWorldAccess) this.worldAccesses.get(var5)).playSound(par2Str, par1Entity.posX,
+ par1Entity.posY - (double) par1Entity.yOffset, par1Entity.posZ, par3, par4);
+ }
+ }
+ }
+
+ /**
+ * Plays sound to all near players except the player reference given
+ */
+ public void playSoundToNearExcept(EntityPlayer par1EntityPlayer, String par2Str, float par3, float par4) {
+ if (par1EntityPlayer != null && par2Str != null) {
+ for (int var5 = 0; var5 < this.worldAccesses.size(); ++var5) {
+ ((IWorldAccess) this.worldAccesses.get(var5)).playSoundToNearExcept(par1EntityPlayer, par2Str,
+ par1EntityPlayer.posX, par1EntityPlayer.posY - (double) par1EntityPlayer.yOffset,
+ par1EntityPlayer.posZ, par3, par4);
+ }
+ }
+ }
+
+ /**
+ * Play a sound effect. Many many parameters for this function. Not sure what
+ * they do, but a classic call is : (double)i + 0.5D, (double)j + 0.5D,
+ * (double)k + 0.5D, 'random.door_open', 1.0F, world.rand.nextFloat() * 0.1F +
+ * 0.9F with i,j,k position of the block.
+ */
+ public void playSoundEffect(double par1, double par3, double par5, String par7Str, float par8, float par9) {
+ if (par7Str != null) {
+ for (int var10 = 0; var10 < this.worldAccesses.size(); ++var10) {
+ ((IWorldAccess) this.worldAccesses.get(var10)).playSound(par7Str, par1, par3, par5, par8, par9);
+ }
+ }
+ }
+
+ /**
+ * par8 is loudness, all pars passed to minecraftInstance.sndManager.playSound
+ */
+ public void playSound(double par1, double par3, double par5, String par7Str, float par8, float par9,
+ boolean par10) {
+ }
+
+ /**
+ * Plays a record at the specified coordinates of the specified name. Args:
+ * recordName, x, y, z
+ */
+ public void playRecord(String par1Str, int par2, int par3, int par4) {
+ for (int var5 = 0; var5 < this.worldAccesses.size(); ++var5) {
+ ((IWorldAccess) this.worldAccesses.get(var5)).playRecord(par1Str, par2, par3, par4);
+ }
+ }
+
+ /**
+ * Spawns a particle. Args particleName, x, y, z, velX, velY, velZ
+ */
+ public void spawnParticle(String par1Str, double par2, double par4, double par6, double par8, double par10,
+ double par12) {
+ for (int var14 = 0; var14 < this.worldAccesses.size(); ++var14) {
+ ((IWorldAccess) this.worldAccesses.get(var14)).spawnParticle(par1Str, par2, par4, par6, par8, par10, par12);
+ }
+ }
+
+ /**
+ * adds a lightning bolt to the list of lightning bolts in this world.
+ */
+ public boolean addWeatherEffect(Entity par1Entity) {
+ this.weatherEffects.add(par1Entity);
+ return true;
+ }
+
+ /**
+ * Called when an entity is spawned in the world. This includes players.
+ */
+ public boolean spawnEntityInWorld(Entity par1Entity) {
+ int var2 = MathHelper.floor_double(par1Entity.posX / 16.0D);
+ int var3 = MathHelper.floor_double(par1Entity.posZ / 16.0D);
+ boolean var4 = par1Entity.field_98038_p;
+
+ if (par1Entity instanceof EntityPlayer) {
+ var4 = true;
+ }
+
+ if (!var4 && !this.chunkExists(var2, var3)) {
+ return false;
+ } else {
+ if (par1Entity instanceof EntityPlayer) {
+ EntityPlayer var5 = (EntityPlayer) par1Entity;
+ this.playerEntities.add(var5);
+ this.updateAllPlayersSleepingFlag();
+ }
+
+ this.getChunkFromChunkCoords(var2, var3).addEntity(par1Entity);
+ this.loadedEntityList.add(par1Entity);
+ this.obtainEntitySkin(par1Entity);
+ return true;
+ }
+ }
+
+ /**
+ * Start the skin for this entity downloading, if necessary, and increment its
+ * reference counter
+ */
+ protected void obtainEntitySkin(Entity par1Entity) {
+ for (int var2 = 0; var2 < this.worldAccesses.size(); ++var2) {
+ ((IWorldAccess) this.worldAccesses.get(var2)).onEntityCreate(par1Entity);
+ }
+ }
+
+ /**
+ * Decrement the reference counter for this entity's skin image data
+ */
+ protected void releaseEntitySkin(Entity par1Entity) {
+ for (int var2 = 0; var2 < this.worldAccesses.size(); ++var2) {
+ ((IWorldAccess) this.worldAccesses.get(var2)).onEntityDestroy(par1Entity);
+ }
+ }
+
+ /**
+ * Schedule the entity for removal during the next tick. Marks the entity dead
+ * in anticipation.
+ */
+ public void removeEntity(Entity par1Entity) {
+ if (par1Entity.riddenByEntity != null) {
+ par1Entity.riddenByEntity.mountEntity((Entity) null);
+ }
+
+ if (par1Entity.ridingEntity != null) {
+ par1Entity.mountEntity((Entity) null);
+ }
+
+ par1Entity.setDead();
+
+ if (par1Entity instanceof EntityPlayer) {
+ this.playerEntities.remove(par1Entity);
+ this.updateAllPlayersSleepingFlag();
+ }
+ }
+
+ /**
+ * Do NOT use this method to remove normal entities- use normal removeEntity
+ */
+ public void removePlayerEntityDangerously(Entity par1Entity) {
+ par1Entity.setDead();
+
+ if (par1Entity instanceof EntityPlayer) {
+ this.playerEntities.remove(par1Entity);
+ this.updateAllPlayersSleepingFlag();
+ }
+
+ int var2 = par1Entity.chunkCoordX;
+ int var3 = par1Entity.chunkCoordZ;
+
+ if (par1Entity.addedToChunk && this.chunkExists(var2, var3)) {
+ this.getChunkFromChunkCoords(var2, var3).removeEntity(par1Entity);
+ }
+
+ this.loadedEntityList.remove(par1Entity);
+ this.releaseEntitySkin(par1Entity);
+ }
+
+ /**
+ * Adds a IWorldAccess to the list of worldAccesses
+ */
+ public void addWorldAccess(IWorldAccess par1IWorldAccess) {
+ this.worldAccesses.add(par1IWorldAccess);
+ }
+
+ /**
+ * Returns a list of bounding boxes that collide with aabb excluding the passed
+ * in entity's collision. Args: entity, aabb
+ */
+ public List getCollidingBoundingBoxes(Entity par1Entity, AxisAlignedBB par2AxisAlignedBB) {
+ this.collidingBoundingBoxes.clear();
+ int var3 = MathHelper.floor_double(par2AxisAlignedBB.minX);
+ int var4 = MathHelper.floor_double(par2AxisAlignedBB.maxX + 1.0D);
+ int var5 = MathHelper.floor_double(par2AxisAlignedBB.minY);
+ int var6 = MathHelper.floor_double(par2AxisAlignedBB.maxY + 1.0D);
+ int var7 = MathHelper.floor_double(par2AxisAlignedBB.minZ);
+ int var8 = MathHelper.floor_double(par2AxisAlignedBB.maxZ + 1.0D);
+
+ for (int var9 = var3; var9 < var4; ++var9) {
+ for (int var10 = var7; var10 < var8; ++var10) {
+ if (this.blockExists(var9, 64, var10)) {
+ for (int var11 = var5 - 1; var11 < var6; ++var11) {
+ Block var12 = Block.blocksList[this.getBlockId(var9, var11, var10)];
+
+ if (var12 != null) {
+ var12.addCollisionBoxesToList(this, var9, var11, var10, par2AxisAlignedBB,
+ this.collidingBoundingBoxes, par1Entity);
+ }
+ }
+ }
+ }
+ }
+
+ double var14 = 0.25D;
+ List var15 = this.getEntitiesWithinAABBExcludingEntity(par1Entity,
+ par2AxisAlignedBB.expand(var14, var14, var14));
+
+ for (int var16 = 0; var16 < var15.size(); ++var16) {
+ AxisAlignedBB var13 = ((Entity) var15.get(var16)).getBoundingBox();
+
+ if (var13 != null && var13.intersectsWith(par2AxisAlignedBB)) {
+ this.collidingBoundingBoxes.add(var13);
+ }
+
+ var13 = par1Entity.getCollisionBox((Entity) var15.get(var16));
+
+ if (var13 != null && var13.intersectsWith(par2AxisAlignedBB)) {
+ this.collidingBoundingBoxes.add(var13);
+ }
+ }
+
+ return this.collidingBoundingBoxes;
+ }
+
+ /**
+ * calculates and returns a list of colliding bounding boxes within a given AABB
+ */
+ public List getCollidingBlockBounds(AxisAlignedBB par1AxisAlignedBB) {
+ this.collidingBoundingBoxes.clear();
+ int var2 = MathHelper.floor_double(par1AxisAlignedBB.minX);
+ int var3 = MathHelper.floor_double(par1AxisAlignedBB.maxX + 1.0D);
+ int var4 = MathHelper.floor_double(par1AxisAlignedBB.minY);
+ int var5 = MathHelper.floor_double(par1AxisAlignedBB.maxY + 1.0D);
+ int var6 = MathHelper.floor_double(par1AxisAlignedBB.minZ);
+ int var7 = MathHelper.floor_double(par1AxisAlignedBB.maxZ + 1.0D);
+
+ for (int var8 = var2; var8 < var3; ++var8) {
+ for (int var9 = var6; var9 < var7; ++var9) {
+ if (this.blockExists(var8, 64, var9)) {
+ for (int var10 = var4 - 1; var10 < var5; ++var10) {
+ Block var11 = Block.blocksList[this.getBlockId(var8, var10, var9)];
+
+ if (var11 != null) {
+ var11.addCollisionBoxesToList(this, var8, var10, var9, par1AxisAlignedBB,
+ this.collidingBoundingBoxes, (Entity) null);
+ }
+ }
+ }
+ }
+ }
+
+ return this.collidingBoundingBoxes;
+ }
+
+ /**
+ * Returns the amount of skylight subtracted for the current time
+ */
+ public int calculateSkylightSubtracted(float par1) {
+ float var2 = this.getCelestialAngle(par1);
+ float var3 = 1.0F - (MathHelper.cos(var2 * (float) Math.PI * 2.0F) * 2.0F + 0.5F);
+
+ if (var3 < 0.0F) {
+ var3 = 0.0F;
+ }
+
+ if (var3 > 1.0F) {
+ var3 = 1.0F;
+ }
+
+ var3 = 1.0F - var3;
+ var3 = (float) ((double) var3 * (1.0D - (double) (this.getRainStrength(par1) * 5.0F) / 16.0D));
+ var3 = (float) ((double) var3 * (1.0D - (double) (this.getWeightedThunderStrength(par1) * 5.0F) / 16.0D));
+ var3 = 1.0F - var3;
+ return (int) (var3 * 11.0F);
+ }
+
+ /**
+ * calls calculateCelestialAngle
+ */
+ public float getCelestialAngle(float par1) {
+ return this.provider.calculateCelestialAngle(this.worldInfo.getWorldTime(), par1);
+ }
+
+ public int getMoonPhase() {
+ return this.provider.func_76559_b(this.worldInfo.getWorldTime());
+ }
+
+ /**
+ * Return getCelestialAngle()*2*PI
+ */
+ public float getCelestialAngleRadians(float par1) {
+ float var2 = this.getCelestialAngle(par1);
+ return var2 * (float) Math.PI * 2.0F;
+ }
+
+ /**
+ * Gets the height to which rain/snow will fall. Calculates it if not already
+ * stored.
+ */
+ public int getPrecipitationHeight(int par1, int par2) {
+ return this.getChunkFromBlockCoords(par1, par2).getPrecipitationHeight(par1 & 15, par2 & 15);
+ }
+
+ /**
+ * Finds the highest block on the x, z coordinate that is solid and returns its
+ * y coord. Args x, z
+ */
+ public int getTopSolidOrLiquidBlock(int par1, int par2) {
+ Chunk var3 = this.getChunkFromBlockCoords(par1, par2);
+ int var4 = var3.getTopFilledSegment() + 15;
+ par1 &= 15;
+
+ for (par2 &= 15; var4 > 0; --var4) {
+ int var5 = var3.getBlockID(par1, var4, par2);
+
+ if (var5 != 0 && Block.blocksList[var5].blockMaterial.blocksMovement()
+ && Block.blocksList[var5].blockMaterial != Material.leaves) {
+ return var4 + 1;
+ }
+ }
+
+ return -1;
+ }
+
+ /**
+ * Used to schedule a call to the updateTick method on the specified block.
+ */
+ public void scheduleBlockUpdate(int par1, int par2, int par3, int par4, int par5) {
+ }
+
+ public void func_82740_a(int par1, int par2, int par3, int par4, int par5, int par6) {
+ }
+
+ /**
+ * Schedules a block update from the saved information in a chunk. Called when
+ * the chunk is loaded.
+ */
+ public void scheduleBlockUpdateFromLoad(int par1, int par2, int par3, int par4, int par5, int par6) {
+ }
+
+ /**
+ * Updates (and cleans up) entities and tile entities
+ */
+ public void updateEntities() {
+ int var1;
+ Entity var2;
+
+ for (var1 = 0; var1 < this.weatherEffects.size(); ++var1) {
+ var2 = (Entity) this.weatherEffects.get(var1);
+
+ ++var2.ticksExisted;
+ var2.onUpdate();
+
+ if (var2.isDead) {
+ this.weatherEffects.remove(var1--);
+ }
+ }
+
+ this.loadedEntityList.removeAll(this.unloadedEntityList);
+ int var3;
+ int var13;
+
+ for (var1 = 0; var1 < this.unloadedEntityList.size(); ++var1) {
+ var2 = (Entity) this.unloadedEntityList.get(var1);
+ var3 = var2.chunkCoordX;
+ var13 = var2.chunkCoordZ;
+
+ if (var2.addedToChunk && this.chunkExists(var3, var13)) {
+ this.getChunkFromChunkCoords(var3, var13).removeEntity(var2);
+ }
+ }
+
+ for (var1 = 0; var1 < this.unloadedEntityList.size(); ++var1) {
+ this.releaseEntitySkin((Entity) this.unloadedEntityList.get(var1));
+ }
+
+ this.unloadedEntityList.clear();
+
+ for (var1 = 0; var1 < this.loadedEntityList.size(); ++var1) {
+ var2 = (Entity) this.loadedEntityList.get(var1);
+
+ if (var2.ridingEntity != null) {
+ if (!var2.ridingEntity.isDead && var2.ridingEntity.riddenByEntity == var2) {
+ continue;
+ }
+
+ var2.ridingEntity.riddenByEntity = null;
+ var2.ridingEntity = null;
+ }
+
+ if (!var2.isDead) {
+ this.updateEntity(var2);
+ }
+
+ if (var2.isDead) {
+ var3 = var2.chunkCoordX;
+ var13 = var2.chunkCoordZ;
+
+ if (var2.addedToChunk && this.chunkExists(var3, var13)) {
+ this.getChunkFromChunkCoords(var3, var13).removeEntity(var2);
+ }
+
+ this.loadedEntityList.remove(var1--);
+ this.releaseEntitySkin(var2);
+ }
+ }
+
+ this.scanningTileEntities = true;
+ Iterator var14 = this.loadedTileEntityList.iterator();
+
+ while (var14.hasNext()) {
+ TileEntity var9 = (TileEntity) var14.next();
+
+ if (!var9.isInvalid() && var9.func_70309_m() && this.blockExists(var9.xCoord, var9.yCoord, var9.zCoord)) {
+ var9.updateEntity();
+ }
+
+ if (var9.isInvalid()) {
+ var14.remove();
+
+ if (this.chunkExists(var9.xCoord >> 4, var9.zCoord >> 4)) {
+ Chunk var11 = this.getChunkFromChunkCoords(var9.xCoord >> 4, var9.zCoord >> 4);
+
+ if (var11 != null) {
+ var11.removeChunkBlockTileEntity(var9.xCoord & 15, var9.yCoord, var9.zCoord & 15);
+ }
+ }
+ }
+ }
+
+ this.scanningTileEntities = false;
+
+ if (!this.entityRemoval.isEmpty()) {
+ this.loadedTileEntityList.removeAll(this.entityRemoval);
+ this.entityRemoval.clear();
+ }
+
+ if (!this.addedTileEntityList.isEmpty()) {
+ for (int var10 = 0; var10 < this.addedTileEntityList.size(); ++var10) {
+ TileEntity var12 = (TileEntity) this.addedTileEntityList.get(var10);
+
+ if (!var12.isInvalid()) {
+ if (!this.loadedTileEntityList.contains(var12)) {
+ this.loadedTileEntityList.add(var12);
+ }
+
+ if (this.chunkExists(var12.xCoord >> 4, var12.zCoord >> 4)) {
+ Chunk var15 = this.getChunkFromChunkCoords(var12.xCoord >> 4, var12.zCoord >> 4);
+
+ if (var15 != null) {
+ var15.setChunkBlockTileEntity(var12.xCoord & 15, var12.yCoord, var12.zCoord & 15, var12);
+ }
+ }
+
+ this.markBlockForUpdate(var12.xCoord, var12.yCoord, var12.zCoord);
+ }
+ }
+
+ this.addedTileEntityList.clear();
+ }
+ }
+
+ public void addTileEntity(Collection par1Collection) {
+ if (this.scanningTileEntities) {
+ this.addedTileEntityList.addAll(par1Collection);
+ } else {
+ this.loadedTileEntityList.addAll(par1Collection);
+ }
+ }
+
+ /**
+ * Will update the entity in the world if the chunk the entity is in is
+ * currently loaded. Args: entity
+ */
+ public void updateEntity(Entity par1Entity) {
+ this.updateEntityWithOptionalForce(par1Entity, true);
+ }
+
+ /**
+ * Will update the entity in the world if the chunk the entity is in is
+ * currently loaded or its forced to update. Args: entity, forceUpdate
+ */
+ public void updateEntityWithOptionalForce(Entity par1Entity, boolean par2) {
+ int var3 = MathHelper.floor_double(par1Entity.posX);
+ int var4 = MathHelper.floor_double(par1Entity.posZ);
+ byte var5 = 32;
+
+ if (!par2 || this.checkChunksExist(var3 - var5, 0, var4 - var5, var3 + var5, 0, var4 + var5)) {
+ par1Entity.lastTickPosX = par1Entity.posX;
+ par1Entity.lastTickPosY = par1Entity.posY;
+ par1Entity.lastTickPosZ = par1Entity.posZ;
+ par1Entity.prevRotationYaw = par1Entity.rotationYaw;
+ par1Entity.prevRotationPitch = par1Entity.rotationPitch;
+
+ if (par2 && par1Entity.addedToChunk) {
+ if (par1Entity.ridingEntity != null) {
+ par1Entity.updateRidden();
+ } else {
+ ++par1Entity.ticksExisted;
+ par1Entity.onUpdate();
+ }
+ }
+
+ if (Double.isNaN(par1Entity.posX) || Double.isInfinite(par1Entity.posX)) {
+ par1Entity.posX = par1Entity.lastTickPosX;
+ }
+
+ if (Double.isNaN(par1Entity.posY) || Double.isInfinite(par1Entity.posY)) {
+ par1Entity.posY = par1Entity.lastTickPosY;
+ }
+
+ if (Double.isNaN(par1Entity.posZ) || Double.isInfinite(par1Entity.posZ)) {
+ par1Entity.posZ = par1Entity.lastTickPosZ;
+ }
+
+ if (Double.isNaN((double) par1Entity.rotationPitch)
+ || Double.isInfinite((double) par1Entity.rotationPitch)) {
+ par1Entity.rotationPitch = par1Entity.prevRotationPitch;
+ }
+
+ if (Double.isNaN((double) par1Entity.rotationYaw) || Double.isInfinite((double) par1Entity.rotationYaw)) {
+ par1Entity.rotationYaw = par1Entity.prevRotationYaw;
+ }
+
+ int var6 = MathHelper.floor_double(par1Entity.posX / 16.0D);
+ int var7 = MathHelper.floor_double(par1Entity.posY / 16.0D);
+ int var8 = MathHelper.floor_double(par1Entity.posZ / 16.0D);
+
+ if (!par1Entity.addedToChunk || par1Entity.chunkCoordX != var6 || par1Entity.chunkCoordY != var7
+ || par1Entity.chunkCoordZ != var8) {
+ if (par1Entity.addedToChunk && this.chunkExists(par1Entity.chunkCoordX, par1Entity.chunkCoordZ)) {
+ this.getChunkFromChunkCoords(par1Entity.chunkCoordX, par1Entity.chunkCoordZ)
+ .removeEntityAtIndex(par1Entity, par1Entity.chunkCoordY);
+ }
+
+ if (this.chunkExists(var6, var8)) {
+ par1Entity.addedToChunk = true;
+ this.getChunkFromChunkCoords(var6, var8).addEntity(par1Entity);
+ } else {
+ par1Entity.addedToChunk = false;
+ }
+ }
+
+ if (par2 && par1Entity.addedToChunk && par1Entity.riddenByEntity != null) {
+ if (!par1Entity.riddenByEntity.isDead && par1Entity.riddenByEntity.ridingEntity == par1Entity) {
+ this.updateEntity(par1Entity.riddenByEntity);
+ } else {
+ par1Entity.riddenByEntity.ridingEntity = null;
+ par1Entity.riddenByEntity = null;
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns true if there are no solid, live entities in the specified
+ * AxisAlignedBB
+ */
+ public boolean checkNoEntityCollision(AxisAlignedBB par1AxisAlignedBB) {
+ return this.checkNoEntityCollision(par1AxisAlignedBB, (Entity) null);
+ }
+
+ /**
+ * Returns true if there are no solid, live entities in the specified
+ * AxisAlignedBB, excluding the given entity
+ */
+ public boolean checkNoEntityCollision(AxisAlignedBB par1AxisAlignedBB, Entity par2Entity) {
+ List var3 = this.getEntitiesWithinAABBExcludingEntity((Entity) null, par1AxisAlignedBB);
+
+ for (int var4 = 0; var4 < var3.size(); ++var4) {
+ Entity var5 = (Entity) var3.get(var4);
+
+ if (!var5.isDead && var5.preventEntitySpawning && var5 != par2Entity) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns true if there are any blocks in the region constrained by an
+ * AxisAlignedBB
+ */
+ public boolean checkBlockCollision(AxisAlignedBB par1AxisAlignedBB) {
+ int var2 = MathHelper.floor_double(par1AxisAlignedBB.minX);
+ int var3 = MathHelper.floor_double(par1AxisAlignedBB.maxX + 1.0D);
+ int var4 = MathHelper.floor_double(par1AxisAlignedBB.minY);
+ int var5 = MathHelper.floor_double(par1AxisAlignedBB.maxY + 1.0D);
+ int var6 = MathHelper.floor_double(par1AxisAlignedBB.minZ);
+ int var7 = MathHelper.floor_double(par1AxisAlignedBB.maxZ + 1.0D);
+
+ if (par1AxisAlignedBB.minX < 0.0D) {
+ --var2;
+ }
+
+ if (par1AxisAlignedBB.minY < 0.0D) {
+ --var4;
+ }
+
+ if (par1AxisAlignedBB.minZ < 0.0D) {
+ --var6;
+ }
+
+ for (int var8 = var2; var8 < var3; ++var8) {
+ for (int var9 = var4; var9 < var5; ++var9) {
+ for (int var10 = var6; var10 < var7; ++var10) {
+ Block var11 = Block.blocksList[this.getBlockId(var8, var9, var10)];
+
+ if (var11 != null) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns if any of the blocks within the aabb are liquids. Args: aabb
+ */
+ public boolean isAnyLiquid(AxisAlignedBB par1AxisAlignedBB) {
+ int var2 = MathHelper.floor_double(par1AxisAlignedBB.minX);
+ int var3 = MathHelper.floor_double(par1AxisAlignedBB.maxX + 1.0D);
+ int var4 = MathHelper.floor_double(par1AxisAlignedBB.minY);
+ int var5 = MathHelper.floor_double(par1AxisAlignedBB.maxY + 1.0D);
+ int var6 = MathHelper.floor_double(par1AxisAlignedBB.minZ);
+ int var7 = MathHelper.floor_double(par1AxisAlignedBB.maxZ + 1.0D);
+
+ if (par1AxisAlignedBB.minX < 0.0D) {
+ --var2;
+ }
+
+ if (par1AxisAlignedBB.minY < 0.0D) {
+ --var4;
+ }
+
+ if (par1AxisAlignedBB.minZ < 0.0D) {
+ --var6;
+ }
+
+ for (int var8 = var2; var8 < var3; ++var8) {
+ for (int var9 = var4; var9 < var5; ++var9) {
+ for (int var10 = var6; var10 < var7; ++var10) {
+ Block var11 = Block.blocksList[this.getBlockId(var8, var9, var10)];
+
+ if (var11 != null && var11.blockMaterial.isLiquid()) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns whether or not the given bounding box is on fire or not
+ */
+ public boolean isBoundingBoxBurning(AxisAlignedBB par1AxisAlignedBB) {
+ int var2 = MathHelper.floor_double(par1AxisAlignedBB.minX);
+ int var3 = MathHelper.floor_double(par1AxisAlignedBB.maxX + 1.0D);
+ int var4 = MathHelper.floor_double(par1AxisAlignedBB.minY);
+ int var5 = MathHelper.floor_double(par1AxisAlignedBB.maxY + 1.0D);
+ int var6 = MathHelper.floor_double(par1AxisAlignedBB.minZ);
+ int var7 = MathHelper.floor_double(par1AxisAlignedBB.maxZ + 1.0D);
+
+ if (this.checkChunksExist(var2, var4, var6, var3, var5, var7)) {
+ for (int var8 = var2; var8 < var3; ++var8) {
+ for (int var9 = var4; var9 < var5; ++var9) {
+ for (int var10 = var6; var10 < var7; ++var10) {
+ int var11 = this.getBlockId(var8, var9, var10);
+
+ if (var11 == Block.fire.blockID || var11 == Block.lavaMoving.blockID
+ || var11 == Block.lavaStill.blockID) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * handles the acceleration of an object whilst in water. Not sure if it is used
+ * elsewhere.
+ */
+ public boolean handleMaterialAcceleration(AxisAlignedBB par1AxisAlignedBB, Material par2Material,
+ Entity par3Entity) {
+ int var4 = MathHelper.floor_double(par1AxisAlignedBB.minX);
+ int var5 = MathHelper.floor_double(par1AxisAlignedBB.maxX + 1.0D);
+ int var6 = MathHelper.floor_double(par1AxisAlignedBB.minY);
+ int var7 = MathHelper.floor_double(par1AxisAlignedBB.maxY + 1.0D);
+ int var8 = MathHelper.floor_double(par1AxisAlignedBB.minZ);
+ int var9 = MathHelper.floor_double(par1AxisAlignedBB.maxZ + 1.0D);
+
+ if (!this.checkChunksExist(var4, var6, var8, var5, var7, var9)) {
+ return false;
+ } else {
+ boolean var10 = false;
+ Vec3 var11 = this.getWorldVec3Pool().getVecFromPool(0.0D, 0.0D, 0.0D);
+
+ for (int var12 = var4; var12 < var5; ++var12) {
+ for (int var13 = var6; var13 < var7; ++var13) {
+ for (int var14 = var8; var14 < var9; ++var14) {
+ Block var15 = Block.blocksList[this.getBlockId(var12, var13, var14)];
+
+ if (var15 != null && var15.blockMaterial == par2Material) {
+ double var16 = (double) ((float) (var13 + 1)
+ - BlockFluid.getFluidHeightPercent(this.getBlockMetadata(var12, var13, var14)));
+
+ if ((double) var7 >= var16) {
+ var10 = true;
+ var15.velocityToAddToEntity(this, var12, var13, var14, par3Entity, var11);
+ }
+ }
+ }
+ }
+ }
+
+ if (var11.lengthVector() > 0.0D && par3Entity.func_96092_aw()) {
+ var11 = var11.normalize();
+ double var18 = 0.014D;
+ par3Entity.motionX += var11.xCoord * var18;
+ par3Entity.motionY += var11.yCoord * var18;
+ par3Entity.motionZ += var11.zCoord * var18;
+ }
+
+ return var10;
+ }
+ }
+
+ /**
+ * Returns true if the given bounding box contains the given material
+ */
+ public boolean isMaterialInBB(AxisAlignedBB par1AxisAlignedBB, Material par2Material) {
+ int var3 = MathHelper.floor_double(par1AxisAlignedBB.minX);
+ int var4 = MathHelper.floor_double(par1AxisAlignedBB.maxX + 1.0D);
+ int var5 = MathHelper.floor_double(par1AxisAlignedBB.minY);
+ int var6 = MathHelper.floor_double(par1AxisAlignedBB.maxY + 1.0D);
+ int var7 = MathHelper.floor_double(par1AxisAlignedBB.minZ);
+ int var8 = MathHelper.floor_double(par1AxisAlignedBB.maxZ + 1.0D);
+
+ for (int var9 = var3; var9 < var4; ++var9) {
+ for (int var10 = var5; var10 < var6; ++var10) {
+ for (int var11 = var7; var11 < var8; ++var11) {
+ Block var12 = Block.blocksList[this.getBlockId(var9, var10, var11)];
+
+ if (var12 != null && var12.blockMaterial == par2Material) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * checks if the given AABB is in the material given. Used while swimming.
+ */
+ public boolean isAABBInMaterial(AxisAlignedBB par1AxisAlignedBB, Material par2Material) {
+ int var3 = MathHelper.floor_double(par1AxisAlignedBB.minX);
+ int var4 = MathHelper.floor_double(par1AxisAlignedBB.maxX + 1.0D);
+ int var5 = MathHelper.floor_double(par1AxisAlignedBB.minY);
+ int var6 = MathHelper.floor_double(par1AxisAlignedBB.maxY + 1.0D);
+ int var7 = MathHelper.floor_double(par1AxisAlignedBB.minZ);
+ int var8 = MathHelper.floor_double(par1AxisAlignedBB.maxZ + 1.0D);
+
+ for (int var9 = var3; var9 < var4; ++var9) {
+ for (int var10 = var5; var10 < var6; ++var10) {
+ for (int var11 = var7; var11 < var8; ++var11) {
+ Block var12 = Block.blocksList[this.getBlockId(var9, var10, var11)];
+
+ if (var12 != null && var12.blockMaterial == par2Material) {
+ int var13 = this.getBlockMetadata(var9, var10, var11);
+ double var14 = (double) (var10 + 1);
+
+ if (var13 < 8) {
+ var14 = (double) (var10 + 1) - (double) var13 / 8.0D;
+ }
+
+ if (var14 >= par1AxisAlignedBB.minY) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Creates an explosion. Args: entity, x, y, z, strength
+ */
+ public Explosion createExplosion(Entity par1Entity, double par2, double par4, double par6, float par8,
+ boolean par9) {
+ return this.newExplosion(par1Entity, par2, par4, par6, par8, false, par9);
+ }
+
+ /**
+ * returns a new explosion. Does initiation (at time of writing Explosion is not
+ * finished)
+ */
+ public Explosion newExplosion(Entity par1Entity, double par2, double par4, double par6, float par8, boolean par9,
+ boolean par10) {
+ Explosion var11 = new Explosion(this, par1Entity, par2, par4, par6, par8);
+ var11.isFlaming = par9;
+ var11.isSmoking = par10;
+ var11.doExplosionA();
+ var11.doExplosionB(true);
+ return var11;
+ }
+
+ /**
+ * Gets the percentage of real blocks within within a bounding box, along a
+ * specified vector.
+ */
+ public float getBlockDensity(Vec3 par1Vec3, AxisAlignedBB par2AxisAlignedBB) {
+ double var3 = 1.0D / ((par2AxisAlignedBB.maxX - par2AxisAlignedBB.minX) * 2.0D + 1.0D);
+ double var5 = 1.0D / ((par2AxisAlignedBB.maxY - par2AxisAlignedBB.minY) * 2.0D + 1.0D);
+ double var7 = 1.0D / ((par2AxisAlignedBB.maxZ - par2AxisAlignedBB.minZ) * 2.0D + 1.0D);
+ int var9 = 0;
+ int var10 = 0;
+
+ for (float var11 = 0.0F; var11 <= 1.0F; var11 = (float) ((double) var11 + var3)) {
+ for (float var12 = 0.0F; var12 <= 1.0F; var12 = (float) ((double) var12 + var5)) {
+ for (float var13 = 0.0F; var13 <= 1.0F; var13 = (float) ((double) var13 + var7)) {
+ double var14 = par2AxisAlignedBB.minX
+ + (par2AxisAlignedBB.maxX - par2AxisAlignedBB.minX) * (double) var11;
+ double var16 = par2AxisAlignedBB.minY
+ + (par2AxisAlignedBB.maxY - par2AxisAlignedBB.minY) * (double) var12;
+ double var18 = par2AxisAlignedBB.minZ
+ + (par2AxisAlignedBB.maxZ - par2AxisAlignedBB.minZ) * (double) var13;
+
+ if (this.rayTraceBlocks(this.getWorldVec3Pool().getVecFromPool(var14, var16, var18),
+ par1Vec3) == null) {
+ ++var9;
+ }
+
+ ++var10;
+ }
+ }
+ }
+
+ return (float) var9 / (float) var10;
+ }
+
+ /**
+ * If the block in the given direction of the given coordinate is fire,
+ * extinguish it. Args: Player, X,Y,Z, blockDirection
+ */
+ public boolean extinguishFire(EntityPlayer par1EntityPlayer, int par2, int par3, int par4, int par5) {
+ if (par5 == 0) {
+ --par3;
+ }
+
+ if (par5 == 1) {
+ ++par3;
+ }
+
+ if (par5 == 2) {
+ --par4;
+ }
+
+ if (par5 == 3) {
+ ++par4;
+ }
+
+ if (par5 == 4) {
+ --par2;
+ }
+
+ if (par5 == 5) {
+ ++par2;
+ }
+
+ if (this.getBlockId(par2, par3, par4) == Block.fire.blockID) {
+ this.playAuxSFXAtEntity(par1EntityPlayer, 1004, par2, par3, par4, 0);
+ this.setBlockToAir(par2, par3, par4);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Returns the TileEntity associated with a given block in X,Y,Z coordinates, or
+ * null if no TileEntity exists
+ */
+ public TileEntity getBlockTileEntity(int par1, int par2, int par3) {
+ if (par2 >= 0 && par2 < 256) {
+ TileEntity var4 = null;
+ int var5;
+ TileEntity var6;
+
+ if (this.scanningTileEntities) {
+ for (var5 = 0; var5 < this.addedTileEntityList.size(); ++var5) {
+ var6 = (TileEntity) this.addedTileEntityList.get(var5);
+
+ if (!var6.isInvalid() && var6.xCoord == par1 && var6.yCoord == par2 && var6.zCoord == par3) {
+ var4 = var6;
+ break;
+ }
+ }
+ }
+
+ if (var4 == null) {
+ Chunk var7 = this.getChunkFromChunkCoords(par1 >> 4, par3 >> 4);
+
+ if (var7 != null) {
+ var4 = var7.getChunkBlockTileEntity(par1 & 15, par2, par3 & 15);
+ }
+ }
+
+ if (var4 == null) {
+ for (var5 = 0; var5 < this.addedTileEntityList.size(); ++var5) {
+ var6 = (TileEntity) this.addedTileEntityList.get(var5);
+
+ if (!var6.isInvalid() && var6.xCoord == par1 && var6.yCoord == par2 && var6.zCoord == par3) {
+ var4 = var6;
+ break;
+ }
+ }
+ }
+
+ return var4;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Sets the TileEntity for a given block in X, Y, Z coordinates
+ */
+ public void setBlockTileEntity(int par1, int par2, int par3, TileEntity par4TileEntity) {
+ if (par4TileEntity != null && !par4TileEntity.isInvalid()) {
+ if (this.scanningTileEntities) {
+ par4TileEntity.xCoord = par1;
+ par4TileEntity.yCoord = par2;
+ par4TileEntity.zCoord = par3;
+ Iterator var5 = this.addedTileEntityList.iterator();
+
+ while (var5.hasNext()) {
+ TileEntity var6 = (TileEntity) var5.next();
+
+ if (var6.xCoord == par1 && var6.yCoord == par2 && var6.zCoord == par3) {
+ var6.invalidate();
+ var5.remove();
+ }
+ }
+
+ this.addedTileEntityList.add(par4TileEntity);
+ } else {
+ this.loadedTileEntityList.add(par4TileEntity);
+ Chunk var7 = this.getChunkFromChunkCoords(par1 >> 4, par3 >> 4);
+
+ if (var7 != null) {
+ var7.setChunkBlockTileEntity(par1 & 15, par2, par3 & 15, par4TileEntity);
+ }
+ }
+ }
+ }
+
+ /**
+ * Removes the TileEntity for a given block in X,Y,Z coordinates
+ */
+ public void removeBlockTileEntity(int par1, int par2, int par3) {
+ TileEntity var4 = this.getBlockTileEntity(par1, par2, par3);
+
+ if (var4 != null && this.scanningTileEntities) {
+ var4.invalidate();
+ this.addedTileEntityList.remove(var4);
+ } else {
+ if (var4 != null) {
+ this.addedTileEntityList.remove(var4);
+ this.loadedTileEntityList.remove(var4);
+ }
+
+ Chunk var5 = this.getChunkFromChunkCoords(par1 >> 4, par3 >> 4);
+
+ if (var5 != null) {
+ var5.removeChunkBlockTileEntity(par1 & 15, par2, par3 & 15);
+ }
+ }
+ }
+
+ /**
+ * Adds TileEntity to despawn list
+ */
+ public void markTileEntityForDespawn(TileEntity par1TileEntity) {
+ this.entityRemoval.add(par1TileEntity);
+ }
+
+ /**
+ * Returns true if the block at the specified coordinates is an opaque cube.
+ * Args: x, y, z
+ */
+ public boolean isBlockOpaqueCube(int par1, int par2, int par3) {
+ Block var4 = Block.blocksList[this.getBlockId(par1, par2, par3)];
+ return var4 == null ? false : var4.isOpaqueCube();
+ }
+
+ /**
+ * Returns true if the block at the specified coordinates is an opaque cube.
+ * Args: x, y, z
+ */
+ public boolean isBlockNormalCube(int par1, int par2, int par3) {
+ return Block.isNormalCube(this.getBlockId(par1, par2, par3));
+ }
+
+ public boolean func_85174_u(int par1, int par2, int par3) {
+ int var4 = this.getBlockId(par1, par2, par3);
+
+ if (var4 != 0 && Block.blocksList[var4] != null) {
+ AxisAlignedBB var5 = Block.blocksList[var4].getCollisionBoundingBoxFromPool(this, par1, par2, par3);
+ return var5 != null && var5.getAverageEdgeLength() >= 1.0D;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Returns true if the block at the given coordinate has a solid (buildable) top
+ * surface.
+ */
+ public boolean doesBlockHaveSolidTopSurface(int par1, int par2, int par3) {
+ Block var4 = Block.blocksList[this.getBlockId(par1, par2, par3)];
+ return this.isBlockTopFacingSurfaceSolid(var4, this.getBlockMetadata(par1, par2, par3));
+ }
+
+ /**
+ * Performs check to see if the block is a normal, solid block, or if the
+ * metadata of the block indicates that its facing puts its solid side upwards.
+ * (inverted stairs, for example)
+ */
+ public boolean isBlockTopFacingSurfaceSolid(Block par1Block, int par2) {
+ return par1Block == null ? false
+ : (par1Block.blockMaterial.isOpaque() && par1Block.renderAsNormalBlock() ? true
+ : (par1Block instanceof BlockStairs ? (par2 & 4) == 4
+ : (par1Block instanceof BlockHalfSlab ? (par2 & 8) == 8
+ : (par1Block instanceof BlockHopper ? true
+ : (par1Block instanceof BlockSnow ? (par2 & 7) == 7 : false)))));
+ }
+
+ /**
+ * Checks if the block is a solid, normal cube. If the chunk does not exist, or
+ * is not loaded, it returns the boolean parameter.
+ */
+ public boolean isBlockNormalCubeDefault(int par1, int par2, int par3, boolean par4) {
+ if (par1 >= -30000000 && par3 >= -30000000 && par1 < 30000000 && par3 < 30000000) {
+ Chunk var5 = this.chunkProvider.provideChunk(par1 >> 4, par3 >> 4);
+
+ if (var5 != null && !var5.isEmpty()) {
+ Block var6 = Block.blocksList[this.getBlockId(par1, par2, par3)];
+ return var6 == null ? false : var6.blockMaterial.isOpaque() && var6.renderAsNormalBlock();
+ } else {
+ return par4;
+ }
+ } else {
+ return par4;
+ }
+ }
+
+ /**
+ * Called on construction of the World class to setup the initial skylight
+ * values
+ */
+ public void calculateInitialSkylight() {
+ int var1 = this.calculateSkylightSubtracted(1.0F);
+
+ if (var1 != this.skylightSubtracted) {
+ this.skylightSubtracted = var1;
+ }
+ }
+
+ /**
+ * first boolean for hostile mobs and second for peaceful mobs
+ */
+ public void setAllowedSpawnTypes(boolean par1, boolean par2) {
+ this.spawnHostileMobs = par1;
+ this.spawnPeacefulMobs = par2;
+ }
+
+ /**
+ * Runs a single tick for the world
+ */
+ public void tick() {
+ this.updateWeather();
+ }
+
+ /**
+ * Called from World constructor to set rainingStrength and thunderingStrength
+ */
+ private void calculateInitialWeather() {
+ if (this.worldInfo.isRaining()) {
+ this.rainingStrength = 1.0F;
+
+ if (this.worldInfo.isThundering()) {
+ this.thunderingStrength = 1.0F;
+ }
+ }
+ }
+
+ /**
+ * Updates all weather states.
+ */
+ protected void updateWeather() {
+ if (!this.provider.hasNoSky) {
+ int var1 = this.worldInfo.getThunderTime();
+
+ if (var1 <= 0) {
+ if (this.worldInfo.isThundering()) {
+ this.worldInfo.setThunderTime(this.rand.nextInt(12000) + 3600);
+ } else {
+ this.worldInfo.setThunderTime(this.rand.nextInt(168000) + 12000);
+ }
+ } else {
+ --var1;
+ this.worldInfo.setThunderTime(var1);
+
+ if (var1 <= 0) {
+ this.worldInfo.setThundering(!this.worldInfo.isThundering());
+ }
+ }
+
+ int var2 = this.worldInfo.getRainTime();
+
+ if (var2 <= 0) {
+ if (this.worldInfo.isRaining()) {
+ this.worldInfo.setRainTime(this.rand.nextInt(12000) + 12000);
+ } else {
+ this.worldInfo.setRainTime(this.rand.nextInt(168000) + 12000);
+ }
+ } else {
+ --var2;
+ this.worldInfo.setRainTime(var2);
+
+ if (var2 <= 0) {
+ this.worldInfo.setRaining(!this.worldInfo.isRaining());
+ }
+ }
+
+ this.prevRainingStrength = this.rainingStrength;
+
+ if (this.worldInfo.isRaining()) {
+ this.rainingStrength = (float) ((double) this.rainingStrength + 0.01D);
+ } else {
+ this.rainingStrength = (float) ((double) this.rainingStrength - 0.01D);
+ }
+
+ if (this.rainingStrength < 0.0F) {
+ this.rainingStrength = 0.0F;
+ }
+
+ if (this.rainingStrength > 1.0F) {
+ this.rainingStrength = 1.0F;
+ }
+
+ this.prevThunderingStrength = this.thunderingStrength;
+
+ if (this.worldInfo.isThundering()) {
+ this.thunderingStrength = (float) ((double) this.thunderingStrength + 0.01D);
+ } else {
+ this.thunderingStrength = (float) ((double) this.thunderingStrength - 0.01D);
+ }
+
+ if (this.thunderingStrength < 0.0F) {
+ this.thunderingStrength = 0.0F;
+ }
+
+ if (this.thunderingStrength > 1.0F) {
+ this.thunderingStrength = 1.0F;
+ }
+ }
+ }
+
+ /**
+ * start precipitation in this world (2 ticks after command posted)
+ */
+ public void commandToggleDownfall() {
+ this.worldInfo.setRainTime(1);
+ }
+
+ protected void setActivePlayerChunksAndCheckLight() {
+ this.activeChunkSet.clear();
+ int var1;
+ EntityPlayerMP var2;
+ int var3;
+ int var4;
+
+ for (var1 = 0; var1 < this.playerEntities.size(); ++var1) {
+ var2 = (EntityPlayerMP) this.playerEntities.get(var1);
+ var3 = MathHelper.floor_double(var2.posX / 16.0D);
+ var4 = MathHelper.floor_double(var2.posZ / 16.0D);
+ int var5 = 7;
+
+ if(var2.renderDistance - 1 < var5) {
+ var5 = var2.renderDistance - 1;
+ if(var5 < 1) {
+ var5 = 1;
+ }
+ }
+
+ for (int var6 = -var5; var6 <= var5; ++var6) {
+ for (int var7 = -var5; var7 <= var5; ++var7) {
+ this.activeChunkSet.add(new ChunkCoordIntPair(var6 + var3, var7 + var4));
+ }
+ }
+ }
+
+ if (this.ambientTickCountdown > 0) {
+ --this.ambientTickCountdown;
+ }
+
+ if (!this.playerEntities.isEmpty()) {
+ var1 = this.rand.nextInt(this.playerEntities.size());
+ var2 = (EntityPlayerMP) this.playerEntities.get(var1);
+ var3 = MathHelper.floor_double(var2.posX) + this.rand.nextInt(11) - 5;
+ var4 = MathHelper.floor_double(var2.posY) + this.rand.nextInt(11) - 5;
+ int var8 = MathHelper.floor_double(var2.posZ) + this.rand.nextInt(11) - 5;
+ this.updateAllLightTypes(var3, var4, var8);
+ }
+ }
+
+ protected void moodSoundAndLightCheck(int par1, int par2, Chunk par3Chunk) {
+ if (this.ambientTickCountdown == 0 && !this.isRemote) {
+ this.updateLCG = this.updateLCG * 3 + 1013904223;
+ int var4 = this.updateLCG >> 2;
+ int var5 = var4 & 15;
+ int var6 = var4 >> 8 & 15;
+ int var7 = var4 >> 16 & 127;
+ int var8 = par3Chunk.getBlockID(var5, var7, var6);
+ var5 += par1;
+ var6 += par2;
+
+ if (var8 == 0 && this.getFullBlockLightValue(var5, var7, var6) <= this.rand.nextInt(8)
+ && this.getSavedLightValue(EnumSkyBlock.Sky, var5, var7, var6) <= 0) {
+ EntityPlayer var9 = this.getClosestPlayer((double) var5 + 0.5D, (double) var7 + 0.5D,
+ (double) var6 + 0.5D, 8.0D);
+
+ if (var9 != null && var9.getDistanceSq((double) var5 + 0.5D, (double) var7 + 0.5D,
+ (double) var6 + 0.5D) > 4.0D) {
+ this.playSoundEffect((double) var5 + 0.5D, (double) var7 + 0.5D, (double) var6 + 0.5D,
+ "ambient.cave.cave", 0.7F, 0.8F + this.rand.nextFloat() * 0.2F);
+ this.ambientTickCountdown = this.rand.nextInt(12000) + 6000;
+ }
+ }
+ }
+
+ par3Chunk.enqueueRelightChecks();
+ }
+
+ /**
+ * plays random cave ambient sounds and runs updateTick on random blocks within
+ * each chunk in the vacinity of a player
+ */
+ protected void tickBlocksAndAmbiance() {
+ this.setActivePlayerChunksAndCheckLight();
+ }
+
+ /**
+ * checks to see if a given block is both water and is cold enough to freeze
+ */
+ public boolean isBlockFreezable(int par1, int par2, int par3) {
+ return this.canBlockFreeze(par1, par2, par3, false);
+ }
+
+ /**
+ * checks to see if a given block is both water and has at least one immediately
+ * adjacent non-water block
+ */
+ public boolean isBlockFreezableNaturally(int par1, int par2, int par3) {
+ return this.canBlockFreeze(par1, par2, par3, true);
+ }
+
+ /**
+ * checks to see if a given block is both water, and cold enough to freeze - if
+ * the par4 boolean is set, this will only return true if there is a non-water
+ * block immediately adjacent to the specified block
+ */
+ public boolean canBlockFreeze(int par1, int par2, int par3, boolean par4) {
+ BiomeGenBase var5 = this.getBiomeGenForCoords(par1, par3);
+ float var6 = var5.getFloatTemperature();
+
+ if (var6 > 0.15F) {
+ return false;
+ } else {
+ if (par2 >= 0 && par2 < 256 && this.getSavedLightValue(EnumSkyBlock.Block, par1, par2, par3) < 10) {
+ int var7 = this.getBlockId(par1, par2, par3);
+
+ if ((var7 == Block.waterStill.blockID || var7 == Block.waterMoving.blockID)
+ && this.getBlockMetadata(par1, par2, par3) == 0) {
+ if (!par4) {
+ return true;
+ }
+
+ boolean var8 = true;
+
+ if (var8 && this.getBlockMaterial(par1 - 1, par2, par3) != Material.water) {
+ var8 = false;
+ }
+
+ if (var8 && this.getBlockMaterial(par1 + 1, par2, par3) != Material.water) {
+ var8 = false;
+ }
+
+ if (var8 && this.getBlockMaterial(par1, par2, par3 - 1) != Material.water) {
+ var8 = false;
+ }
+
+ if (var8 && this.getBlockMaterial(par1, par2, par3 + 1) != Material.water) {
+ var8 = false;
+ }
+
+ if (!var8) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+ }
+
+ /**
+ * Tests whether or not snow can be placed at a given location
+ */
+ public boolean canSnowAt(int par1, int par2, int par3) {
+ BiomeGenBase var4 = this.getBiomeGenForCoords(par1, par3);
+ float var5 = var4.getFloatTemperature();
+
+ if (var5 > 0.15F) {
+ return false;
+ } else {
+ if (par2 >= 0 && par2 < 256 && this.getSavedLightValue(EnumSkyBlock.Block, par1, par2, par3) < 10) {
+ int var6 = this.getBlockId(par1, par2 - 1, par3);
+ int var7 = this.getBlockId(par1, par2, par3);
+
+ if (var7 == 0 && Block.snow.canPlaceBlockAt(this, par1, par2, par3) && var6 != 0
+ && var6 != Block.ice.blockID && Block.blocksList[var6].blockMaterial.blocksMovement()) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+ }
+
+ public void updateAllLightTypes(int par1, int par2, int par3) {
+ if (!this.provider.hasNoSky) {
+ this.updateLightByType(EnumSkyBlock.Sky, par1, par2, par3);
+ }
+
+ this.updateLightByType(EnumSkyBlock.Block, par1, par2, par3);
+ }
+
+ private int computeLightValue(int par1, int par2, int par3, EnumSkyBlock par4EnumSkyBlock) {
+ if (par4EnumSkyBlock == EnumSkyBlock.Sky && this.canBlockSeeTheSky(par1, par2, par3)) {
+ return 15;
+ } else {
+ int var5 = this.getBlockId(par1, par2, par3);
+ int var6 = par4EnumSkyBlock == EnumSkyBlock.Sky ? 0 : Block.lightValue[var5];
+ int var7 = Block.lightOpacity[var5];
+
+ if (var7 >= 15 && Block.lightValue[var5] > 0) {
+ var7 = 1;
+ }
+
+ if (var7 < 1) {
+ var7 = 1;
+ }
+
+ if (var7 >= 15) {
+ return 0;
+ } else if (var6 >= 14) {
+ return var6;
+ } else {
+ for (int var8 = 0; var8 < 6; ++var8) {
+ int var9 = par1 + Facing.offsetsXForSide[var8];
+ int var10 = par2 + Facing.offsetsYForSide[var8];
+ int var11 = par3 + Facing.offsetsZForSide[var8];
+ int var12 = this.getSavedLightValue(par4EnumSkyBlock, var9, var10, var11) - var7;
+
+ if (var12 > var6) {
+ var6 = var12;
+ }
+
+ if (var6 >= 14) {
+ return var6;
+ }
+ }
+
+ return var6;
+ }
+ }
+ }
+
+ public void updateLightByType(EnumSkyBlock par1EnumSkyBlock, int par2, int par3, int par4) {
+ if (this.doChunksNearChunkExist(par2, par3, par4, 17)) {
+ int var5 = 0;
+ int var6 = 0;
+ int var7 = this.getSavedLightValue(par1EnumSkyBlock, par2, par3, par4);
+ int var8 = this.computeLightValue(par2, par3, par4, par1EnumSkyBlock);
+ int var9;
+ int var10;
+ int var11;
+ int var12;
+ int var13;
+ int var14;
+ int var15;
+ int var16;
+ int var17;
+
+ if (var8 > var7) {
+ this.lightUpdateBlockList[var6++] = 133152;
+ } else if (var8 < var7) {
+ this.lightUpdateBlockList[var6++] = 133152 | var7 << 18;
+
+ while (var5 < var6) {
+ var9 = this.lightUpdateBlockList[var5++];
+ var10 = (var9 & 63) - 32 + par2;
+ var11 = (var9 >> 6 & 63) - 32 + par3;
+ var12 = (var9 >> 12 & 63) - 32 + par4;
+ var13 = var9 >> 18 & 15;
+ var14 = this.getSavedLightValue(par1EnumSkyBlock, var10, var11, var12);
+
+ if (var14 == var13) {
+ this.setLightValue(par1EnumSkyBlock, var10, var11, var12, 0);
+
+ if (var13 > 0) {
+ var15 = MathHelper.abs_int(var10 - par2);
+ var16 = MathHelper.abs_int(var11 - par3);
+ var17 = MathHelper.abs_int(var12 - par4);
+
+ if (var15 + var16 + var17 < 17) {
+ for (int var18 = 0; var18 < 6; ++var18) {
+ int var19 = var10 + Facing.offsetsXForSide[var18];
+ int var20 = var11 + Facing.offsetsYForSide[var18];
+ int var21 = var12 + Facing.offsetsZForSide[var18];
+ int var22 = Math.max(1, Block.lightOpacity[this.getBlockId(var19, var20, var21)]);
+ var14 = this.getSavedLightValue(par1EnumSkyBlock, var19, var20, var21);
+
+ if (var14 == var13 - var22 && var6 < this.lightUpdateBlockList.length) {
+ this.lightUpdateBlockList[var6++] = var19 - par2 + 32 | var20 - par3 + 32 << 6
+ | var21 - par4 + 32 << 12 | var13 - var22 << 18;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ var5 = 0;
+ }
+
+ while (var5 < var6) {
+ var9 = this.lightUpdateBlockList[var5++];
+ var10 = (var9 & 63) - 32 + par2;
+ var11 = (var9 >> 6 & 63) - 32 + par3;
+ var12 = (var9 >> 12 & 63) - 32 + par4;
+ var13 = this.getSavedLightValue(par1EnumSkyBlock, var10, var11, var12);
+ var14 = this.computeLightValue(var10, var11, var12, par1EnumSkyBlock);
+
+ if (var14 != var13) {
+ this.setLightValue(par1EnumSkyBlock, var10, var11, var12, var14);
+
+ if (var14 > var13) {
+ var15 = Math.abs(var10 - par2);
+ var16 = Math.abs(var11 - par3);
+ var17 = Math.abs(var12 - par4);
+ boolean var23 = var6 < this.lightUpdateBlockList.length - 6;
+
+ if (var15 + var16 + var17 < 17 && var23) {
+ if (this.getSavedLightValue(par1EnumSkyBlock, var10 - 1, var11, var12) < var14) {
+ this.lightUpdateBlockList[var6++] = var10 - 1 - par2 + 32 + (var11 - par3 + 32 << 6)
+ + (var12 - par4 + 32 << 12);
+ }
+
+ if (this.getSavedLightValue(par1EnumSkyBlock, var10 + 1, var11, var12) < var14) {
+ this.lightUpdateBlockList[var6++] = var10 + 1 - par2 + 32 + (var11 - par3 + 32 << 6)
+ + (var12 - par4 + 32 << 12);
+ }
+
+ if (this.getSavedLightValue(par1EnumSkyBlock, var10, var11 - 1, var12) < var14) {
+ this.lightUpdateBlockList[var6++] = var10 - par2 + 32 + (var11 - 1 - par3 + 32 << 6)
+ + (var12 - par4 + 32 << 12);
+ }
+
+ if (this.getSavedLightValue(par1EnumSkyBlock, var10, var11 + 1, var12) < var14) {
+ this.lightUpdateBlockList[var6++] = var10 - par2 + 32 + (var11 + 1 - par3 + 32 << 6)
+ + (var12 - par4 + 32 << 12);
+ }
+
+ if (this.getSavedLightValue(par1EnumSkyBlock, var10, var11, var12 - 1) < var14) {
+ this.lightUpdateBlockList[var6++] = var10 - par2 + 32 + (var11 - par3 + 32 << 6)
+ + (var12 - 1 - par4 + 32 << 12);
+ }
+
+ if (this.getSavedLightValue(par1EnumSkyBlock, var10, var11, var12 + 1) < var14) {
+ this.lightUpdateBlockList[var6++] = var10 - par2 + 32 + (var11 - par3 + 32 << 6)
+ + (var12 + 1 - par4 + 32 << 12);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Runs through the list of updates to run and ticks them
+ */
+ public boolean tickUpdates(boolean par1) {
+ return false;
+ }
+
+ public List getPendingBlockUpdates(Chunk par1Chunk, boolean par2) {
+ return null;
+ }
+
+ /**
+ * Will get all entities within the specified AABB excluding the one passed into
+ * it. Args: entityToExclude, aabb
+ */
+ public List getEntitiesWithinAABBExcludingEntity(Entity par1Entity, AxisAlignedBB par2AxisAlignedBB) {
+ return this.getEntitiesWithinAABBExcludingEntity(par1Entity, par2AxisAlignedBB, (IEntitySelector) null);
+ }
+
+ public List getEntitiesWithinAABBExcludingEntity(Entity par1Entity, AxisAlignedBB par2AxisAlignedBB,
+ IEntitySelector par3IEntitySelector) {
+ ArrayList var4 = new ArrayList();
+ int var5 = MathHelper.floor_double((par2AxisAlignedBB.minX - 2.0D) / 16.0D);
+ int var6 = MathHelper.floor_double((par2AxisAlignedBB.maxX + 2.0D) / 16.0D);
+ int var7 = MathHelper.floor_double((par2AxisAlignedBB.minZ - 2.0D) / 16.0D);
+ int var8 = MathHelper.floor_double((par2AxisAlignedBB.maxZ + 2.0D) / 16.0D);
+
+ for (int var9 = var5; var9 <= var6; ++var9) {
+ for (int var10 = var7; var10 <= var8; ++var10) {
+ if (this.chunkExists(var9, var10)) {
+ this.getChunkFromChunkCoords(var9, var10).getEntitiesWithinAABBForEntity(par1Entity,
+ par2AxisAlignedBB, var4, par3IEntitySelector);
+ }
+ }
+ }
+
+ return var4;
+ }
+
+ /**
+ * Returns all entities of the specified class type which intersect with the
+ * AABB. Args: entityClass, aabb
+ */
+ public List getEntitiesWithinAABB(Class par1Class, AxisAlignedBB par2AxisAlignedBB) {
+ return this.selectEntitiesWithinAABB(par1Class, par2AxisAlignedBB, (IEntitySelector) null);
+ }
+
+ public List selectEntitiesWithinAABB(Class par1Class, AxisAlignedBB par2AxisAlignedBB,
+ IEntitySelector par3IEntitySelector) {
+ int var4 = MathHelper.floor_double((par2AxisAlignedBB.minX - 2.0D) / 16.0D);
+ int var5 = MathHelper.floor_double((par2AxisAlignedBB.maxX + 2.0D) / 16.0D);
+ int var6 = MathHelper.floor_double((par2AxisAlignedBB.minZ - 2.0D) / 16.0D);
+ int var7 = MathHelper.floor_double((par2AxisAlignedBB.maxZ + 2.0D) / 16.0D);
+ ArrayList var8 = new ArrayList();
+
+ for (int var9 = var4; var9 <= var5; ++var9) {
+ for (int var10 = var6; var10 <= var7; ++var10) {
+ if (this.chunkExists(var9, var10)) {
+ this.getChunkFromChunkCoords(var9, var10).getEntitiesOfTypeWithinAAAB(par1Class, par2AxisAlignedBB,
+ var8, par3IEntitySelector);
+ }
+ }
+ }
+
+ return var8;
+ }
+
+ public Entity findNearestEntityWithinAABB(Class par1Class, AxisAlignedBB par2AxisAlignedBB, Entity par3Entity) {
+ List var4 = this.getEntitiesWithinAABB(par1Class, par2AxisAlignedBB);
+ Entity var5 = null;
+ double var6 = Double.MAX_VALUE;
+
+ for (int var8 = 0; var8 < var4.size(); ++var8) {
+ Entity var9 = (Entity) var4.get(var8);
+
+ if (var9 != par3Entity) {
+ double var10 = par3Entity.getDistanceSqToEntity(var9);
+
+ if (var10 <= var6) {
+ var5 = var9;
+ var6 = var10;
+ }
+ }
+ }
+
+ return var5;
+ }
+
+ /**
+ * Returns the Entity with the given ID, or null if it doesn't exist in this
+ * World.
+ */
+ public abstract Entity getEntityByID(int var1);
+
+ /**
+ * marks the chunk that contains this tilentity as modified and then calls
+ * worldAccesses.doNothingWithTileEntity
+ */
+ public void updateTileEntityChunkAndDoNothing(int par1, int par2, int par3, TileEntity par4TileEntity) {
+ if (this.blockExists(par1, par2, par3)) {
+ this.getChunkFromBlockCoords(par1, par3).setChunkModified();
+ }
+ }
+
+ /**
+ * Counts how many entities of an entity class exist in the world. Args:
+ * entityClass
+ */
+ public int countEntities(Class par1Class) {
+ int var2 = 0;
+
+ for (int var3 = 0; var3 < this.loadedEntityList.size(); ++var3) {
+ Entity var4 = (Entity) this.loadedEntityList.get(var3);
+
+ if ((!(var4 instanceof EntityLiving) || !((EntityLiving) var4).func_104002_bU())
+ && par1Class.isAssignableFrom(var4.getClass())) {
+ ++var2;
+ }
+ }
+
+ return var2;
+ }
+
+ /**
+ * adds entities to the loaded entities list, and loads thier skins.
+ */
+ public void addLoadedEntities(List par1List) {
+ this.loadedEntityList.addAll(par1List);
+
+ for (int var2 = 0; var2 < par1List.size(); ++var2) {
+ this.obtainEntitySkin((Entity) par1List.get(var2));
+ }
+ }
+
+ /**
+ * adds entities to the list of unloaded entities
+ */
+ public void unloadEntities(List par1List) {
+ this.unloadedEntityList.addAll(par1List);
+ }
+
+ /**
+ * Returns true if the given Entity can be placed on the given side of the given
+ * block position.
+ */
+ public boolean canPlaceEntityOnSide(int par1, int par2, int par3, int par4, boolean par5, int par6,
+ Entity par7Entity, ItemStack par8ItemStack) {
+ int var9 = this.getBlockId(par2, par3, par4);
+ Block var10 = Block.blocksList[var9];
+ Block var11 = Block.blocksList[par1];
+ AxisAlignedBB var12 = var11.getCollisionBoundingBoxFromPool(this, par2, par3, par4);
+
+ if (par5) {
+ var12 = null;
+ }
+
+ if (var12 != null && !this.checkNoEntityCollision(var12, par7Entity)) {
+ return false;
+ } else {
+ if (var10 != null && (var10 == Block.waterMoving || var10 == Block.waterStill || var10 == Block.lavaMoving
+ || var10 == Block.lavaStill || var10 == Block.fire || var10.blockMaterial.isReplaceable())) {
+ var10 = null;
+ }
+
+ return var10 != null && var10.blockMaterial == Material.circuits && var11 == Block.anvil ? true
+ : par1 > 0 && var10 == null
+ && var11.canPlaceBlockOnSide(this, par2, par3, par4, par6, par8ItemStack);
+ }
+ }
+
+ public PathEntity getPathEntityToEntity(Entity par1Entity, Entity par2Entity, float par3, boolean par4,
+ boolean par5, boolean par6, boolean par7) {
+ int var8 = MathHelper.floor_double(par1Entity.posX);
+ int var9 = MathHelper.floor_double(par1Entity.posY + 1.0D);
+ int var10 = MathHelper.floor_double(par1Entity.posZ);
+ int var11 = (int) (par3 + 16.0F);
+ int var12 = var8 - var11;
+ int var13 = var9 - var11;
+ int var14 = var10 - var11;
+ int var15 = var8 + var11;
+ int var16 = var9 + var11;
+ int var17 = var10 + var11;
+ ChunkCache var18 = new ChunkCache(this, var12, var13, var14, var15, var16, var17, 0);
+ PathEntity var19 = (new PathFinder(var18, par4, par5, par6, par7)).createEntityPathTo(par1Entity, par2Entity,
+ par3);
+ return var19;
+ }
+
+ public PathEntity getEntityPathToXYZ(Entity par1Entity, int par2, int par3, int par4, float par5, boolean par6,
+ boolean par7, boolean par8, boolean par9) {
+ int var10 = MathHelper.floor_double(par1Entity.posX);
+ int var11 = MathHelper.floor_double(par1Entity.posY);
+ int var12 = MathHelper.floor_double(par1Entity.posZ);
+ int var13 = (int) (par5 + 8.0F);
+ int var14 = var10 - var13;
+ int var15 = var11 - var13;
+ int var16 = var12 - var13;
+ int var17 = var10 + var13;
+ int var18 = var11 + var13;
+ int var19 = var12 + var13;
+ ChunkCache var20 = new ChunkCache(this, var14, var15, var16, var17, var18, var19, 0);
+ PathEntity var21 = (new PathFinder(var20, par6, par7, par8, par9)).createEntityPathTo(par1Entity, par2, par3,
+ par4, par5);
+ return var21;
+ }
+
+ /**
+ * Is this block powering in the specified direction Args: x, y, z, direction
+ */
+ public int isBlockProvidingPowerTo(int par1, int par2, int par3, int par4) {
+ int var5 = this.getBlockId(par1, par2, par3);
+ return var5 == 0 ? 0 : Block.blocksList[var5].isProvidingStrongPower(this, par1, par2, par3, par4);
+ }
+
+ /**
+ * Returns the highest redstone signal strength powering the given block. Args:
+ * X, Y, Z.
+ */
+ public int getBlockPowerInput(int par1, int par2, int par3) {
+ byte var4 = 0;
+ int var5 = Math.max(var4, this.isBlockProvidingPowerTo(par1, par2 - 1, par3, 0));
+
+ if (var5 >= 15) {
+ return var5;
+ } else {
+ var5 = Math.max(var5, this.isBlockProvidingPowerTo(par1, par2 + 1, par3, 1));
+
+ if (var5 >= 15) {
+ return var5;
+ } else {
+ var5 = Math.max(var5, this.isBlockProvidingPowerTo(par1, par2, par3 - 1, 2));
+
+ if (var5 >= 15) {
+ return var5;
+ } else {
+ var5 = Math.max(var5, this.isBlockProvidingPowerTo(par1, par2, par3 + 1, 3));
+
+ if (var5 >= 15) {
+ return var5;
+ } else {
+ var5 = Math.max(var5, this.isBlockProvidingPowerTo(par1 - 1, par2, par3, 4));
+
+ if (var5 >= 15) {
+ return var5;
+ } else {
+ var5 = Math.max(var5, this.isBlockProvidingPowerTo(par1 + 1, par2, par3, 5));
+ return var5 >= 15 ? var5 : var5;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the indirect signal strength being outputted by the given block in
+ * the *opposite* of the given direction. Args: X, Y, Z, direction
+ */
+ public boolean getIndirectPowerOutput(int par1, int par2, int par3, int par4) {
+ return this.getIndirectPowerLevelTo(par1, par2, par3, par4) > 0;
+ }
+
+ /**
+ * Gets the power level from a certain block face. Args: x, y, z, direction
+ */
+ public int getIndirectPowerLevelTo(int par1, int par2, int par3, int par4) {
+ if (this.isBlockNormalCube(par1, par2, par3)) {
+ return this.getBlockPowerInput(par1, par2, par3);
+ } else {
+ int var5 = this.getBlockId(par1, par2, par3);
+ return var5 == 0 ? 0 : Block.blocksList[var5].isProvidingWeakPower(this, par1, par2, par3, par4);
+ }
+ }
+
+ /**
+ * Used to see if one of the blocks next to you or your block is getting power
+ * from a neighboring block. Used by items like TNT or Doors so they don't have
+ * redstone going straight into them. Args: x, y, z
+ */
+ public boolean isBlockIndirectlyGettingPowered(int par1, int par2, int par3) {
+ return this.getIndirectPowerLevelTo(par1, par2 - 1, par3, 0) > 0 ? true
+ : (this.getIndirectPowerLevelTo(par1, par2 + 1, par3, 1) > 0 ? true
+ : (this.getIndirectPowerLevelTo(par1, par2, par3 - 1, 2) > 0 ? true
+ : (this.getIndirectPowerLevelTo(par1, par2, par3 + 1, 3) > 0 ? true
+ : (this.getIndirectPowerLevelTo(par1 - 1, par2, par3, 4) > 0 ? true
+ : this.getIndirectPowerLevelTo(par1 + 1, par2, par3, 5) > 0))));
+ }
+
+ public int getStrongestIndirectPower(int par1, int par2, int par3) {
+ int var4 = 0;
+
+ for (int var5 = 0; var5 < 6; ++var5) {
+ int var6 = this.getIndirectPowerLevelTo(par1 + Facing.offsetsXForSide[var5],
+ par2 + Facing.offsetsYForSide[var5], par3 + Facing.offsetsZForSide[var5], var5);
+
+ if (var6 >= 15) {
+ return 15;
+ }
+
+ if (var6 > var4) {
+ var4 = var6;
+ }
+ }
+
+ return var4;
+ }
+
+ /**
+ * Gets the closest player to the entity within the specified distance (if
+ * distance is less than 0 then ignored). Args: entity, dist
+ */
+ public EntityPlayer getClosestPlayerToEntity(Entity par1Entity, double par2) {
+ return this.getClosestPlayer(par1Entity.posX, par1Entity.posY, par1Entity.posZ, par2);
+ }
+
+ /**
+ * Gets the closest player to the point within the specified distance (distance
+ * can be set to less than 0 to not limit the distance). Args: x, y, z, dist
+ */
+ public EntityPlayer getClosestPlayer(double par1, double par3, double par5, double par7) {
+ double var9 = -1.0D;
+ EntityPlayer var11 = null;
+
+ for (int var12 = 0; var12 < this.playerEntities.size(); ++var12) {
+ EntityPlayer var13 = (EntityPlayer) this.playerEntities.get(var12);
+ double var14 = var13.getDistanceSq(par1, par3, par5);
+
+ if ((par7 < 0.0D || var14 < par7 * par7) && (var9 == -1.0D || var14 < var9)) {
+ var9 = var14;
+ var11 = var13;
+ }
+ }
+
+ return var11;
+ }
+
+ public EntityPlayer getClosestPlayerForSpawning(double par1, double par3, double par5) {
+ double var9 = -1.0D;
+ EntityPlayer var11 = null;
+
+ for (int var12 = 0; var12 < this.playerEntities.size(); ++var12) {
+ EntityPlayerMP var13 = (EntityPlayerMP) this.playerEntities.get(var12);
+ double var14 = var13.getDistanceSq(par1, par3, par5);
+ double par7 = (var13.renderDistance < 6) ? 16.0D : 24.0D;
+
+ if ((par7 < 0.0D || var14 < par7 * par7) && (var9 == -1.0D || var14 < var9)) {
+ var9 = var14;
+ var11 = var13;
+ }
+ }
+
+ return var11;
+ }
+
+ /**
+ * Returns the closest vulnerable player to this entity within the given radius,
+ * or null if none is found
+ */
+ public EntityPlayer getClosestVulnerablePlayerToEntity(Entity par1Entity, double par2) {
+ return this.getClosestVulnerablePlayer(par1Entity.posX, par1Entity.posY, par1Entity.posZ, par2);
+ }
+
+ /**
+ * Returns the closest vulnerable player within the given radius, or null if
+ * none is found.
+ */
+ public EntityPlayer getClosestVulnerablePlayer(double par1, double par3, double par5, double par7) {
+ double var9 = -1.0D;
+ EntityPlayer var11 = null;
+
+ for (int var12 = 0; var12 < this.playerEntities.size(); ++var12) {
+ EntityPlayer var13 = (EntityPlayer) this.playerEntities.get(var12);
+
+ if (!var13.capabilities.disableDamage && var13.isEntityAlive()) {
+ double var14 = var13.getDistanceSq(par1, par3, par5);
+ double var16 = par7;
+
+ if (var13.isSneaking()) {
+ var16 = par7 * 0.800000011920929D;
+ }
+
+ if (var13.isInvisible()) {
+ float var18 = var13.func_82243_bO();
+
+ if (var18 < 0.1F) {
+ var18 = 0.1F;
+ }
+
+ var16 *= (double) (0.7F * var18);
+ }
+
+ if ((par7 < 0.0D || var14 < var16 * var16) && (var9 == -1.0D || var14 < var9)) {
+ var9 = var14;
+ var11 = var13;
+ }
+ }
+ }
+
+ return var11;
+ }
+
+ /**
+ * Find a player by name in this world.
+ */
+ public EntityPlayer getPlayerEntityByName(String par1Str) {
+ for (int var2 = 0; var2 < this.playerEntities.size(); ++var2) {
+ if (par1Str.equals(((EntityPlayer) this.playerEntities.get(var2)).username)) {
+ return (EntityPlayer) this.playerEntities.get(var2);
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Checks whether the session lock file was modified by another process
+ */
+ public void checkSessionLock() throws MinecraftException {
+ this.saveHandler.checkSessionLock();
+ }
+
+ /**
+ * gets the random world seed
+ */
+ public long getSeed() {
+ return this.worldInfo.getSeed();
+ }
+
+ public long getTotalWorldTime() {
+ return this.worldInfo.getWorldTotalTime();
+ }
+
+ public long getWorldTime() {
+ return this.worldInfo.getWorldTime();
+ }
+
+ /**
+ * Sets the world time.
+ */
+ public void setWorldTime(long par1) {
+ this.worldInfo.setWorldTime(par1);
+ }
+
+ /**
+ * Returns the coordinates of the spawn point
+ */
+ public ChunkCoordinates getSpawnPoint() {
+ return new ChunkCoordinates(this.worldInfo.getSpawnX(), this.worldInfo.getSpawnY(), this.worldInfo.getSpawnZ());
+ }
+
+ /**
+ * Called when checking if a certain block can be mined or not. The 'spawn safe
+ * zone' check is located here.
+ */
+ public boolean canMineBlock(EntityPlayer par1EntityPlayer, int par2, int par3, int par4) {
+ return true;
+ }
+
+ /**
+ * sends a Packet 38 (Entity Status) to all tracked players of that entity
+ */
+ public void setEntityState(Entity par1Entity, byte par2) {
+ }
+
+ /**
+ * gets the world's chunk provider
+ */
+ public IChunkProvider getChunkProvider() {
+ return this.chunkProvider;
+ }
+
+ /**
+ * Adds a block event with the given Args to the blockEventCache. During the
+ * next tick(), the block specified will have its onBlockEvent handler called
+ * with the given parameters. Args: X,Y,Z, BlockID, EventID, EventParameter
+ */
+ public void addBlockEvent(int par1, int par2, int par3, int par4, int par5, int par6) {
+ if (par4 > 0) {
+ Block.blocksList[par4].onBlockEventReceived(this, par1, par2, par3, par5, par6);
+ }
+ }
+
+ /**
+ * Returns this world's current save handler
+ */
+ public ISaveHandler getSaveHandler() {
+ return this.saveHandler;
+ }
+
+ /**
+ * Returns the world's WorldInfo object
+ */
+ public WorldInfo getWorldInfo() {
+ return this.worldInfo;
+ }
+
+ /**
+ * Gets the GameRules instance.
+ */
+ public GameRules getGameRules() {
+ return this.worldInfo.getGameRulesInstance();
+ }
+
+ /**
+ * Updates the flag that indicates whether or not all players in the world are
+ * sleeping.
+ */
+ public void updateAllPlayersSleepingFlag() {
+ }
+
+ public float getWeightedThunderStrength(float par1) {
+ return (this.prevThunderingStrength + (this.thunderingStrength - this.prevThunderingStrength) * par1)
+ * this.getRainStrength(par1);
+ }
+
+ /**
+ * Not sure about this actually. Reverting this one myself.
+ */
+ public float getRainStrength(float par1) {
+ return this.prevRainingStrength + (this.rainingStrength - this.prevRainingStrength) * par1;
+ }
+
+ /**
+ * Returns true if the current thunder strength (weighted with the rain
+ * strength) is greater than 0.9
+ */
+ public boolean isThundering() {
+ return (double) this.getWeightedThunderStrength(1.0F) > 0.9D;
+ }
+
+ /**
+ * Returns true if the current rain strength is greater than 0.2
+ */
+ public boolean isRaining() {
+ return (double) this.getRainStrength(1.0F) > 0.2D;
+ }
+
+ public boolean canLightningStrikeAt(int par1, int par2, int par3) {
+ if (!this.isRaining()) {
+ return false;
+ } else if (!this.canBlockSeeTheSky(par1, par2, par3)) {
+ return false;
+ } else if (this.getPrecipitationHeight(par1, par3) > par2) {
+ return false;
+ } else {
+ BiomeGenBase var4 = this.getBiomeGenForCoords(par1, par3);
+ return var4.getEnableSnow() ? false : var4.canSpawnLightningBolt();
+ }
+ }
+
+ /**
+ * Checks to see if the biome rainfall values for a given x,y,z coordinate set
+ * are extremely high
+ */
+ public boolean isBlockHighHumidity(int par1, int par2, int par3) {
+ BiomeGenBase var4 = this.getBiomeGenForCoords(par1, par3);
+ return var4.isHighHumidity();
+ }
+
+ /**
+ * Assigns the given String id to the given MapDataBase using the MapStorage,
+ * removing any existing ones of the same id.
+ */
+ public void setItemData(String par1Str, WorldSavedData par2WorldSavedData) {
+ this.mapStorage.setData(par1Str, par2WorldSavedData);
+ }
+
+ /**
+ * Loads an existing MapDataBase corresponding to the given String id from disk
+ * using the MapStorage, instantiating the given Class, or returns null if none
+ * such file exists. args: Class to instantiate, String dataid
+ */
+ public WorldSavedData loadItemData(Function par1Class, String par2Str) {
+ return this.mapStorage.loadData(par1Class, par2Str);
+ }
+
+ /**
+ * Returns an unique new data id from the MapStorage for the given prefix and
+ * saves the idCounts map to the 'idcounts' file.
+ */
+ public int getUniqueDataId(String par1Str) {
+ return this.mapStorage.getUniqueDataId(par1Str);
+ }
+
+ public void func_82739_e(int par1, int par2, int par3, int par4, int par5) {
+ for (int var6 = 0; var6 < this.worldAccesses.size(); ++var6) {
+ ((IWorldAccess) this.worldAccesses.get(var6)).broadcastSound(par1, par2, par3, par4, par5);
+ }
+ }
+
+ /**
+ * Plays a sound or particle effect. Parameters: Effect ID, X, Y, Z, Data. For a
+ * list of ids and data, see http://wiki.vg/Protocol#Effects
+ */
+ public void playAuxSFX(int par1, int par2, int par3, int par4, int par5) {
+ this.playAuxSFXAtEntity((EntityPlayer) null, par1, par2, par3, par4, par5);
+ }
+
+ /**
+ * See description for playAuxSFX.
+ */
+ public void playAuxSFXAtEntity(EntityPlayer par1EntityPlayer, int par2, int par3, int par4, int par5, int par6) {
+ for (int var7 = 0; var7 < this.worldAccesses.size(); ++var7) {
+ ((IWorldAccess) this.worldAccesses.get(var7)).playAuxSFX(par1EntityPlayer, par2, par3, par4, par5,
+ par6);
+ }
+ }
+
+ /**
+ * Returns maximum world height.
+ */
+ public int getHeight() {
+ return 256;
+ }
+
+ /**
+ * Returns current world height.
+ */
+ public int getActualHeight() {
+ return this.provider.hasNoSky ? 128 : 256;
+ }
+
+ public IUpdatePlayerListBox func_82735_a(EntityMinecart par1EntityMinecart) {
+ return null;
+ }
+
+ /**
+ * puts the World Random seed to a specific state dependant on the inputs
+ */
+ public EaglercraftRandom setRandomSeed(int par1, int par2, int par3) {
+ long var4 = (long) par1 * 341873128712L + (long) par2 * 132897987541L + this.getWorldInfo().getSeed()
+ + (long) par3;
+ this.rand.setSeed(var4);
+ return this.rand;
+ }
+
+ /**
+ * Returns the location of the closest structure of the specified type. If not
+ * found returns null.
+ */
+ public ChunkPosition findClosestStructure(String par1Str, int par2, int par3, int par4) {
+ return this.getChunkProvider().findClosestStructure(this, par1Str, par2, par3, par4);
+ }
+
+ /**
+ * Starts (or continues) destroying a block with given ID at the given
+ * coordinates for the given partially destroyed value
+ */
+ public void destroyBlockInWorldPartially(int par1, int par2, int par3, int par4, int par5) {
+ for (int var6 = 0; var6 < this.worldAccesses.size(); ++var6) {
+ IWorldAccess var7 = (IWorldAccess) this.worldAccesses.get(var6);
+ var7.destroyBlockPartially(par1, par2, par3, par4, par5);
+ }
+ }
+
+ /**
+ * Return the Vec3Pool object for this world.
+ */
+ public Vec3Pool getWorldVec3Pool() {
+ return this.vecPool;
+ }
+
+ /**
+ * returns a calendar object containing the current date
+ */
+ public Calendar getCurrentDate() {
+ if (this.getTotalWorldTime() % 600L == 0L) {
+ this.theCalendar.setTimeInMillis(System.currentTimeMillis());
+ }
+
+ return this.theCalendar;
+ }
+
+ public Scoreboard getScoreboard() {
+ return this.worldScoreboard;
+ }
+
+ public void func_96440_m(int par1, int par2, int par3, int par4) {
+ for (int var5 = 0; var5 < 4; ++var5) {
+ int var6 = par1 + Direction.offsetX[var5];
+ int var7 = par3 + Direction.offsetZ[var5];
+ int var8 = this.getBlockId(var6, par2, var7);
+
+ if (var8 != 0) {
+ Block var9 = Block.blocksList[var8];
+
+ if (Block.redstoneComparatorIdle.func_94487_f(var8)) {
+ var9.onNeighborBlockChange(this, var6, par2, var7, par4);
+ } else if (Block.isNormalCube(var8)) {
+ var6 += Direction.offsetX[var5];
+ var7 += Direction.offsetZ[var5];
+ var8 = this.getBlockId(var6, par2, var7);
+ var9 = Block.blocksList[var8];
+
+ if (Block.redstoneComparatorIdle.func_94487_f(var8)) {
+ var9.onNeighborBlockChange(this, var6, par2, var7, par4);
+ }
+ }
+ }
+ }
+ }
+
+ public ILogAgent getWorldLogAgent() {
+ return this.worldLogAgent;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldChunkManager.java b/sp-server/src/main/java/net/minecraft/src/WorldChunkManager.java
new file mode 100644
index 0000000..4d6d62c
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldChunkManager.java
@@ -0,0 +1,226 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class WorldChunkManager {
+ private GenLayer genBiomes;
+
+ /** A GenLayer containing the indices into BiomeGenBase.biomeList[] */
+ private GenLayer biomeIndexLayer;
+
+ /** The biome list. */
+ private BiomeCache biomeCache;
+
+ /** A list of biomes that the player can spawn in. */
+ private List biomesToSpawnIn;
+
+ protected WorldChunkManager() {
+ this.biomeCache = new BiomeCache(this);
+ this.biomesToSpawnIn = new ArrayList();
+ this.biomesToSpawnIn.add(BiomeGenBase.forest);
+ this.biomesToSpawnIn.add(BiomeGenBase.plains);
+ this.biomesToSpawnIn.add(BiomeGenBase.taiga);
+ this.biomesToSpawnIn.add(BiomeGenBase.taigaHills);
+ this.biomesToSpawnIn.add(BiomeGenBase.forestHills);
+ this.biomesToSpawnIn.add(BiomeGenBase.jungle);
+ this.biomesToSpawnIn.add(BiomeGenBase.jungleHills);
+ }
+
+ public WorldChunkManager(long par1, WorldType par3WorldType) {
+ this();
+ GenLayer[] var4 = GenLayer.initializeAllBiomeGenerators(par1, par3WorldType);
+ this.genBiomes = var4[0];
+ this.biomeIndexLayer = var4[1];
+ }
+
+ public WorldChunkManager(World par1World) {
+ this(par1World.getSeed(), par1World.getWorldInfo().getTerrainType());
+ }
+
+ /**
+ * Gets the list of valid biomes for the player to spawn in.
+ */
+ public List getBiomesToSpawnIn() {
+ return this.biomesToSpawnIn;
+ }
+
+ /**
+ * Returns the BiomeGenBase related to the x, z position on the world.
+ */
+ public BiomeGenBase getBiomeGenAt(int par1, int par2) {
+ return this.biomeCache.getBiomeGenAt(par1, par2);
+ }
+
+ /**
+ * Returns a list of rainfall values for the specified blocks. Args:
+ * listToReuse, x, z, width, length.
+ */
+ public float[] getRainfall(float[] par1ArrayOfFloat, int par2, int par3, int par4, int par5) {
+ IntCache.resetIntCache();
+
+ if (par1ArrayOfFloat == null || par1ArrayOfFloat.length < par4 * par5) {
+ par1ArrayOfFloat = new float[par4 * par5];
+ }
+
+ int[] var6 = this.biomeIndexLayer.getInts(par2, par3, par4, par5);
+
+ for (int var7 = 0; var7 < par4 * par5; ++var7) {
+ float var8 = (float) BiomeGenBase.biomeList[var6[var7]].getIntRainfall() / 65536.0F;
+
+ if (var8 > 1.0F) {
+ var8 = 1.0F;
+ }
+
+ par1ArrayOfFloat[var7] = var8;
+ }
+
+ return par1ArrayOfFloat;
+ }
+
+ /**
+ * Returns a list of temperatures to use for the specified blocks. Args:
+ * listToReuse, x, y, width, length
+ */
+ public float[] getTemperatures(float[] par1ArrayOfFloat, int par2, int par3, int par4, int par5) {
+ IntCache.resetIntCache();
+
+ if (par1ArrayOfFloat == null || par1ArrayOfFloat.length < par4 * par5) {
+ par1ArrayOfFloat = new float[par4 * par5];
+ }
+
+ int[] var6 = this.biomeIndexLayer.getInts(par2, par3, par4, par5);
+
+ for (int var7 = 0; var7 < par4 * par5; ++var7) {
+ float var8 = (float) BiomeGenBase.biomeList[var6[var7]].getIntTemperature() / 65536.0F;
+
+ if (var8 > 1.0F) {
+ var8 = 1.0F;
+ }
+
+ par1ArrayOfFloat[var7] = var8;
+ }
+
+ return par1ArrayOfFloat;
+ }
+
+ /**
+ * Returns an array of biomes for the location input.
+ */
+ public BiomeGenBase[] getBiomesForGeneration(BiomeGenBase[] par1ArrayOfBiomeGenBase, int par2, int par3, int par4,
+ int par5) {
+ IntCache.resetIntCache();
+
+ if (par1ArrayOfBiomeGenBase == null || par1ArrayOfBiomeGenBase.length < par4 * par5) {
+ par1ArrayOfBiomeGenBase = new BiomeGenBase[par4 * par5];
+ }
+
+ int[] var6 = this.genBiomes.getInts(par2, par3, par4, par5);
+
+ for (int var7 = 0; var7 < par4 * par5; ++var7) {
+ par1ArrayOfBiomeGenBase[var7] = BiomeGenBase.biomeList[var6[var7]];
+ }
+
+ return par1ArrayOfBiomeGenBase;
+ }
+
+ /**
+ * Returns biomes to use for the blocks and loads the other data like
+ * temperature and humidity onto the WorldChunkManager Args: oldBiomeList, x, z,
+ * width, depth
+ */
+ public BiomeGenBase[] loadBlockGeneratorData(BiomeGenBase[] par1ArrayOfBiomeGenBase, int par2, int par3, int par4,
+ int par5) {
+ return this.getBiomeGenAt(par1ArrayOfBiomeGenBase, par2, par3, par4, par5, true);
+ }
+
+ /**
+ * Return a list of biomes for the specified blocks. Args: listToReuse, x, y,
+ * width, length, cacheFlag (if false, don't check biomeCache to avoid infinite
+ * loop in BiomeCacheBlock)
+ */
+ public BiomeGenBase[] getBiomeGenAt(BiomeGenBase[] par1ArrayOfBiomeGenBase, int par2, int par3, int par4, int par5,
+ boolean par6) {
+ IntCache.resetIntCache();
+
+ if (par1ArrayOfBiomeGenBase == null || par1ArrayOfBiomeGenBase.length < par4 * par5) {
+ par1ArrayOfBiomeGenBase = new BiomeGenBase[par4 * par5];
+ }
+
+ if (par6 && par4 == 16 && par5 == 16 && (par2 & 15) == 0 && (par3 & 15) == 0) {
+ BiomeGenBase[] var9 = this.biomeCache.getCachedBiomes(par2, par3);
+ System.arraycopy(var9, 0, par1ArrayOfBiomeGenBase, 0, par4 * par5);
+ return par1ArrayOfBiomeGenBase;
+ } else {
+ int[] var7 = this.biomeIndexLayer.getInts(par2, par3, par4, par5);
+
+ for (int var8 = 0; var8 < par4 * par5; ++var8) {
+ par1ArrayOfBiomeGenBase[var8] = BiomeGenBase.biomeList[var7[var8]];
+ }
+
+ return par1ArrayOfBiomeGenBase;
+ }
+ }
+
+ /**
+ * checks given Chunk's Biomes against List of allowed ones
+ */
+ public boolean areBiomesViable(int par1, int par2, int par3, List par4List) {
+ IntCache.resetIntCache();
+ int var5 = par1 - par3 >> 2;
+ int var6 = par2 - par3 >> 2;
+ int var7 = par1 + par3 >> 2;
+ int var8 = par2 + par3 >> 2;
+ int var9 = var7 - var5 + 1;
+ int var10 = var8 - var6 + 1;
+ int[] var11 = this.genBiomes.getInts(var5, var6, var9, var10);
+
+ for (int var12 = 0; var12 < var9 * var10; ++var12) {
+ BiomeGenBase var13 = BiomeGenBase.biomeList[var11[var12]];
+
+ if (!par4List.contains(var13)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Finds a valid position within a range, that is once of the listed biomes.
+ */
+ public ChunkPosition findBiomePosition(int par1, int par2, int par3, List par4List, EaglercraftRandom par5Random) {
+ IntCache.resetIntCache();
+ int var6 = par1 - par3 >> 2;
+ int var7 = par2 - par3 >> 2;
+ int var8 = par1 + par3 >> 2;
+ int var9 = par2 + par3 >> 2;
+ int var10 = var8 - var6 + 1;
+ int var11 = var9 - var7 + 1;
+ int[] var12 = this.genBiomes.getInts(var6, var7, var10, var11);
+ ChunkPosition var13 = null;
+ int var14 = 0;
+
+ for (int var15 = 0; var15 < var10 * var11; ++var15) {
+ int var16 = var6 + var15 % var10 << 2;
+ int var17 = var7 + var15 / var10 << 2;
+ BiomeGenBase var18 = BiomeGenBase.biomeList[var12[var15]];
+
+ if (par4List.contains(var18) && (var13 == null || par5Random.nextInt(var14 + 1) == 0)) {
+ var13 = new ChunkPosition(var16, 0, var17);
+ ++var14;
+ }
+ }
+
+ return var13;
+ }
+
+ /**
+ * Calls the WorldChunkManager's biomeCache.cleanupCache()
+ */
+ public void cleanupCache() {
+ this.biomeCache.cleanupCache();
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldChunkManagerHell.java b/sp-server/src/main/java/net/minecraft/src/WorldChunkManagerHell.java
new file mode 100644
index 0000000..d5070ec
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldChunkManagerHell.java
@@ -0,0 +1,109 @@
+package net.minecraft.src;
+
+import java.util.Arrays;
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class WorldChunkManagerHell extends WorldChunkManager {
+ /** The biome generator object. */
+ private BiomeGenBase biomeGenerator;
+ private float hellTemperature;
+
+ /** The rainfall in the world */
+ private float rainfall;
+
+ public WorldChunkManagerHell(BiomeGenBase par1BiomeGenBase, float par2, float par3) {
+ this.biomeGenerator = par1BiomeGenBase;
+ this.hellTemperature = par2;
+ this.rainfall = par3;
+ }
+
+ /**
+ * Returns the BiomeGenBase related to the x, z position on the world.
+ */
+ public BiomeGenBase getBiomeGenAt(int par1, int par2) {
+ return this.biomeGenerator;
+ }
+
+ /**
+ * Returns an array of biomes for the location input.
+ */
+ public BiomeGenBase[] getBiomesForGeneration(BiomeGenBase[] par1ArrayOfBiomeGenBase, int par2, int par3, int par4,
+ int par5) {
+ if (par1ArrayOfBiomeGenBase == null || par1ArrayOfBiomeGenBase.length < par4 * par5) {
+ par1ArrayOfBiomeGenBase = new BiomeGenBase[par4 * par5];
+ }
+
+ Arrays.fill(par1ArrayOfBiomeGenBase, 0, par4 * par5, this.biomeGenerator);
+ return par1ArrayOfBiomeGenBase;
+ }
+
+ /**
+ * Returns a list of temperatures to use for the specified blocks. Args:
+ * listToReuse, x, y, width, length
+ */
+ public float[] getTemperatures(float[] par1ArrayOfFloat, int par2, int par3, int par4, int par5) {
+ if (par1ArrayOfFloat == null || par1ArrayOfFloat.length < par4 * par5) {
+ par1ArrayOfFloat = new float[par4 * par5];
+ }
+
+ Arrays.fill(par1ArrayOfFloat, 0, par4 * par5, this.hellTemperature);
+ return par1ArrayOfFloat;
+ }
+
+ /**
+ * Returns a list of rainfall values for the specified blocks. Args:
+ * listToReuse, x, z, width, length.
+ */
+ public float[] getRainfall(float[] par1ArrayOfFloat, int par2, int par3, int par4, int par5) {
+ if (par1ArrayOfFloat == null || par1ArrayOfFloat.length < par4 * par5) {
+ par1ArrayOfFloat = new float[par4 * par5];
+ }
+
+ Arrays.fill(par1ArrayOfFloat, 0, par4 * par5, this.rainfall);
+ return par1ArrayOfFloat;
+ }
+
+ /**
+ * Returns biomes to use for the blocks and loads the other data like
+ * temperature and humidity onto the WorldChunkManager Args: oldBiomeList, x, z,
+ * width, depth
+ */
+ public BiomeGenBase[] loadBlockGeneratorData(BiomeGenBase[] par1ArrayOfBiomeGenBase, int par2, int par3, int par4,
+ int par5) {
+ if (par1ArrayOfBiomeGenBase == null || par1ArrayOfBiomeGenBase.length < par4 * par5) {
+ par1ArrayOfBiomeGenBase = new BiomeGenBase[par4 * par5];
+ }
+
+ Arrays.fill(par1ArrayOfBiomeGenBase, 0, par4 * par5, this.biomeGenerator);
+ return par1ArrayOfBiomeGenBase;
+ }
+
+ /**
+ * Return a list of biomes for the specified blocks. Args: listToReuse, x, y,
+ * width, length, cacheFlag (if false, don't check biomeCache to avoid infinite
+ * loop in BiomeCacheBlock)
+ */
+ public BiomeGenBase[] getBiomeGenAt(BiomeGenBase[] par1ArrayOfBiomeGenBase, int par2, int par3, int par4, int par5,
+ boolean par6) {
+ return this.loadBlockGeneratorData(par1ArrayOfBiomeGenBase, par2, par3, par4, par5);
+ }
+
+ /**
+ * Finds a valid position within a range, that is once of the listed biomes.
+ */
+ public ChunkPosition findBiomePosition(int par1, int par2, int par3, List par4List, EaglercraftRandom par5Random) {
+ return par4List.contains(this.biomeGenerator)
+ ? new ChunkPosition(par1 - par3 + par5Random.nextInt(par3 * 2 + 1), 0,
+ par2 - par3 + par5Random.nextInt(par3 * 2 + 1))
+ : null;
+ }
+
+ /**
+ * checks given Chunk's Biomes against List of allowed ones
+ */
+ public boolean areBiomesViable(int par1, int par2, int par3, List par4List) {
+ return par4List.contains(this.biomeGenerator);
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldGenBigMushroom.java b/sp-server/src/main/java/net/minecraft/src/WorldGenBigMushroom.java
new file mode 100644
index 0000000..c5645c6
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldGenBigMushroom.java
@@ -0,0 +1,169 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class WorldGenBigMushroom extends WorldGenerator {
+ /** The mushroom type. 0 for brown, 1 for red. */
+ private int mushroomType = -1;
+
+ public WorldGenBigMushroom(int par1) {
+ super(true);
+ this.mushroomType = par1;
+ }
+
+ public WorldGenBigMushroom() {
+ super(false);
+ }
+
+ public boolean generate(World par1World, EaglercraftRandom par2Random, int par3, int par4, int par5) {
+ int var6 = par2Random.nextInt(2);
+
+ if (this.mushroomType >= 0) {
+ var6 = this.mushroomType;
+ }
+
+ int var7 = par2Random.nextInt(3) + 4;
+ boolean var8 = true;
+
+ if (par4 >= 1 && par4 + var7 + 1 < 256) {
+ int var9;
+ int var11;
+ int var12;
+ int var13;
+
+ for (var9 = par4; var9 <= par4 + 1 + var7; ++var9) {
+ byte var10 = 3;
+
+ if (var9 <= par4 + 3) {
+ var10 = 0;
+ }
+
+ for (var11 = par3 - var10; var11 <= par3 + var10 && var8; ++var11) {
+ for (var12 = par5 - var10; var12 <= par5 + var10 && var8; ++var12) {
+ if (var9 >= 0 && var9 < 256) {
+ var13 = par1World.getBlockId(var11, var9, var12);
+
+ if (var13 != 0 && var13 != Block.leaves.blockID) {
+ var8 = false;
+ }
+ } else {
+ var8 = false;
+ }
+ }
+ }
+ }
+
+ if (!var8) {
+ return false;
+ } else {
+ var9 = par1World.getBlockId(par3, par4 - 1, par5);
+
+ if (var9 != Block.dirt.blockID && var9 != Block.grass.blockID && var9 != Block.mycelium.blockID) {
+ return false;
+ } else {
+ int var16 = par4 + var7;
+
+ if (var6 == 1) {
+ var16 = par4 + var7 - 3;
+ }
+
+ for (var11 = var16; var11 <= par4 + var7; ++var11) {
+ var12 = 1;
+
+ if (var11 < par4 + var7) {
+ ++var12;
+ }
+
+ if (var6 == 0) {
+ var12 = 3;
+ }
+
+ for (var13 = par3 - var12; var13 <= par3 + var12; ++var13) {
+ for (int var14 = par5 - var12; var14 <= par5 + var12; ++var14) {
+ int var15 = 5;
+
+ if (var13 == par3 - var12) {
+ --var15;
+ }
+
+ if (var13 == par3 + var12) {
+ ++var15;
+ }
+
+ if (var14 == par5 - var12) {
+ var15 -= 3;
+ }
+
+ if (var14 == par5 + var12) {
+ var15 += 3;
+ }
+
+ if (var6 == 0 || var11 < par4 + var7) {
+ if ((var13 == par3 - var12 || var13 == par3 + var12)
+ && (var14 == par5 - var12 || var14 == par5 + var12)) {
+ continue;
+ }
+
+ if (var13 == par3 - (var12 - 1) && var14 == par5 - var12) {
+ var15 = 1;
+ }
+
+ if (var13 == par3 - var12 && var14 == par5 - (var12 - 1)) {
+ var15 = 1;
+ }
+
+ if (var13 == par3 + (var12 - 1) && var14 == par5 - var12) {
+ var15 = 3;
+ }
+
+ if (var13 == par3 + var12 && var14 == par5 - (var12 - 1)) {
+ var15 = 3;
+ }
+
+ if (var13 == par3 - (var12 - 1) && var14 == par5 + var12) {
+ var15 = 7;
+ }
+
+ if (var13 == par3 - var12 && var14 == par5 + (var12 - 1)) {
+ var15 = 7;
+ }
+
+ if (var13 == par3 + (var12 - 1) && var14 == par5 + var12) {
+ var15 = 9;
+ }
+
+ if (var13 == par3 + var12 && var14 == par5 + (var12 - 1)) {
+ var15 = 9;
+ }
+ }
+
+ if (var15 == 5 && var11 < par4 + var7) {
+ var15 = 0;
+ }
+
+ if ((var15 != 0 || par4 >= par4 + var7 - 1)
+ && !Block.opaqueCubeLookup[par1World.getBlockId(var13, var11, var14)]) {
+ this.setBlockAndMetadata(par1World, var13, var11, var14,
+ Block.mushroomCapBrown.blockID + var6, var15);
+ }
+ }
+ }
+ }
+
+ for (var11 = 0; var11 < var7; ++var11) {
+ var12 = par1World.getBlockId(par3, par4 + var11, par5);
+
+ if (!Block.opaqueCubeLookup[var12]) {
+ this.setBlockAndMetadata(par1World, par3, par4 + var11, par5,
+ Block.mushroomCapBrown.blockID + var6, 10);
+ }
+ }
+
+ return true;
+ }
+ }
+ } else {
+ return false;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldGenBigTree.java b/sp-server/src/main/java/net/minecraft/src/WorldGenBigTree.java
new file mode 100644
index 0000000..0a9d4e3
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldGenBigTree.java
@@ -0,0 +1,440 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class WorldGenBigTree extends WorldGenerator {
+ /**
+ * Contains three sets of two values that provide complimentary indices for a
+ * given 'major' index - 1 and 2 for 0, 0 and 2 for 1, and 0 and 1 for 2.
+ */
+ static final byte[] otherCoordPairs = new byte[] { (byte) 2, (byte) 0, (byte) 0, (byte) 1, (byte) 2, (byte) 1 };
+
+ /** random seed for GenBigTree */
+ EaglercraftRandom rand = new EaglercraftRandom();
+
+ /** Reference to the World object. */
+ World worldObj;
+ int[] basePos = new int[] { 0, 0, 0 };
+ int heightLimit = 0;
+ int height;
+ double heightAttenuation = 0.618D;
+ double branchDensity = 1.0D;
+ double branchSlope = 0.381D;
+ double scaleWidth = 1.0D;
+ double leafDensity = 1.0D;
+
+ /**
+ * Currently always 1, can be set to 2 in the class constructor to generate a
+ * double-sized tree trunk for big trees.
+ */
+ int trunkSize = 1;
+
+ /**
+ * Sets the limit of the random value used to initialize the height limit.
+ */
+ int heightLimitLimit = 12;
+
+ /**
+ * Sets the distance limit for how far away the generator will populate leaves
+ * from the base leaf node.
+ */
+ int leafDistanceLimit = 4;
+
+ /** Contains a list of a points at which to generate groups of leaves. */
+ int[][] leafNodes;
+
+ public WorldGenBigTree(boolean par1) {
+ super(par1);
+ }
+
+ /**
+ * Generates a list of leaf nodes for the tree, to be populated by
+ * generateLeaves.
+ */
+ void generateLeafNodeList() {
+ this.height = (int) ((double) this.heightLimit * this.heightAttenuation);
+
+ if (this.height >= this.heightLimit) {
+ this.height = this.heightLimit - 1;
+ }
+
+ int var1 = (int) (1.382D + Math.pow(this.leafDensity * (double) this.heightLimit / 13.0D, 2.0D));
+
+ if (var1 < 1) {
+ var1 = 1;
+ }
+
+ int[][] var2 = new int[var1 * this.heightLimit][4];
+ int var3 = this.basePos[1] + this.heightLimit - this.leafDistanceLimit;
+ int var4 = 1;
+ int var5 = this.basePos[1] + this.height;
+ int var6 = var3 - this.basePos[1];
+ var2[0][0] = this.basePos[0];
+ var2[0][1] = var3;
+ var2[0][2] = this.basePos[2];
+ var2[0][3] = var5;
+ --var3;
+
+ while (var6 >= 0) {
+ int var7 = 0;
+ float var8 = this.layerSize(var6);
+
+ if (var8 < 0.0F) {
+ --var3;
+ --var6;
+ } else {
+ for (double var9 = 0.5D; var7 < var1; ++var7) {
+ double var11 = this.scaleWidth * (double) var8 * ((double) this.rand.nextFloat() + 0.328D);
+ double var13 = (double) this.rand.nextFloat() * 2.0D * Math.PI;
+ int var15 = MathHelper.floor_double(var11 * Math.sin(var13) + (double) this.basePos[0] + var9);
+ int var16 = MathHelper.floor_double(var11 * Math.cos(var13) + (double) this.basePos[2] + var9);
+ int[] var17 = new int[] { var15, var3, var16 };
+ int[] var18 = new int[] { var15, var3 + this.leafDistanceLimit, var16 };
+
+ if (this.checkBlockLine(var17, var18) == -1) {
+ int[] var19 = new int[] { this.basePos[0], this.basePos[1], this.basePos[2] };
+ double var20 = Math.sqrt(Math.pow((double) Math.abs(this.basePos[0] - var17[0]), 2.0D)
+ + Math.pow((double) Math.abs(this.basePos[2] - var17[2]), 2.0D));
+ double var22 = var20 * this.branchSlope;
+
+ if ((double) var17[1] - var22 > (double) var5) {
+ var19[1] = var5;
+ } else {
+ var19[1] = (int) ((double) var17[1] - var22);
+ }
+
+ if (this.checkBlockLine(var19, var17) == -1) {
+ var2[var4][0] = var15;
+ var2[var4][1] = var3;
+ var2[var4][2] = var16;
+ var2[var4][3] = var19[1];
+ ++var4;
+ }
+ }
+ }
+
+ --var3;
+ --var6;
+ }
+ }
+
+ this.leafNodes = new int[var4][4];
+ System.arraycopy(var2, 0, this.leafNodes, 0, var4);
+ }
+
+ void genTreeLayer(int par1, int par2, int par3, float par4, byte par5, int par6) {
+ int var7 = (int) ((double) par4 + 0.618D);
+ byte var8 = otherCoordPairs[par5];
+ byte var9 = otherCoordPairs[par5 + 3];
+ int[] var10 = new int[] { par1, par2, par3 };
+ int[] var11 = new int[] { 0, 0, 0 };
+ int var12 = -var7;
+ int var13 = -var7;
+
+ for (var11[par5] = var10[par5]; var12 <= var7; ++var12) {
+ var11[var8] = var10[var8] + var12;
+ var13 = -var7;
+
+ while (var13 <= var7) {
+ double var15 = Math.pow((double) Math.abs(var12) + 0.5D, 2.0D)
+ + Math.pow((double) Math.abs(var13) + 0.5D, 2.0D);
+
+ if (var15 > (double) (par4 * par4)) {
+ ++var13;
+ } else {
+ var11[var9] = var10[var9] + var13;
+ int var14 = this.worldObj.getBlockId(var11[0], var11[1], var11[2]);
+
+ if (var14 != 0 && var14 != Block.leaves.blockID) {
+ ++var13;
+ } else {
+ this.setBlockAndMetadata(this.worldObj, var11[0], var11[1], var11[2], par6, 0);
+ ++var13;
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Gets the rough size of a layer of the tree.
+ */
+ float layerSize(int par1) {
+ if ((double) par1 < (double) ((float) this.heightLimit) * 0.3D) {
+ return -1.618F;
+ } else {
+ float var2 = (float) this.heightLimit / 2.0F;
+ float var3 = (float) this.heightLimit / 2.0F - (float) par1;
+ float var4;
+
+ if (var3 == 0.0F) {
+ var4 = var2;
+ } else if (Math.abs(var3) >= var2) {
+ var4 = 0.0F;
+ } else {
+ var4 = (float) Math
+ .sqrt(Math.pow((double) Math.abs(var2), 2.0D) - Math.pow((double) Math.abs(var3), 2.0D));
+ }
+
+ var4 *= 0.5F;
+ return var4;
+ }
+ }
+
+ float leafSize(int par1) {
+ return par1 >= 0 && par1 < this.leafDistanceLimit
+ ? (par1 != 0 && par1 != this.leafDistanceLimit - 1 ? 3.0F : 2.0F)
+ : -1.0F;
+ }
+
+ /**
+ * Generates the leaves surrounding an individual entry in the leafNodes list.
+ */
+ void generateLeafNode(int par1, int par2, int par3) {
+ int var4 = par2;
+
+ for (int var5 = par2 + this.leafDistanceLimit; var4 < var5; ++var4) {
+ float var6 = this.leafSize(var4 - par2);
+ this.genTreeLayer(par1, var4, par3, var6, (byte) 1, Block.leaves.blockID);
+ }
+ }
+
+ /**
+ * Places a line of the specified block ID into the world from the first
+ * coordinate triplet to the second.
+ */
+ void placeBlockLine(int[] par1ArrayOfInteger, int[] par2ArrayOfInteger, int par3) {
+ int[] var4 = new int[] { 0, 0, 0 };
+ byte var5 = 0;
+ byte var6;
+
+ for (var6 = 0; var5 < 3; ++var5) {
+ var4[var5] = par2ArrayOfInteger[var5] - par1ArrayOfInteger[var5];
+
+ if (Math.abs(var4[var5]) > Math.abs(var4[var6])) {
+ var6 = var5;
+ }
+ }
+
+ if (var4[var6] != 0) {
+ byte var7 = otherCoordPairs[var6];
+ byte var8 = otherCoordPairs[var6 + 3];
+ byte var9;
+
+ if (var4[var6] > 0) {
+ var9 = 1;
+ } else {
+ var9 = -1;
+ }
+
+ double var10 = (double) var4[var7] / (double) var4[var6];
+ double var12 = (double) var4[var8] / (double) var4[var6];
+ int[] var14 = new int[] { 0, 0, 0 };
+ int var15 = 0;
+
+ for (int var16 = var4[var6] + var9; var15 != var16; var15 += var9) {
+ var14[var6] = MathHelper.floor_double((double) (par1ArrayOfInteger[var6] + var15) + 0.5D);
+ var14[var7] = MathHelper
+ .floor_double((double) par1ArrayOfInteger[var7] + (double) var15 * var10 + 0.5D);
+ var14[var8] = MathHelper
+ .floor_double((double) par1ArrayOfInteger[var8] + (double) var15 * var12 + 0.5D);
+ byte var17 = 0;
+ int var18 = Math.abs(var14[0] - par1ArrayOfInteger[0]);
+ int var19 = Math.abs(var14[2] - par1ArrayOfInteger[2]);
+ int var20 = Math.max(var18, var19);
+
+ if (var20 > 0) {
+ if (var18 == var20) {
+ var17 = 4;
+ } else if (var19 == var20) {
+ var17 = 8;
+ }
+ }
+
+ this.setBlockAndMetadata(this.worldObj, var14[0], var14[1], var14[2], par3, var17);
+ }
+ }
+ }
+
+ /**
+ * Generates the leaf portion of the tree as specified by the leafNodes list.
+ */
+ void generateLeaves() {
+ int var1 = 0;
+
+ for (int var2 = this.leafNodes.length; var1 < var2; ++var1) {
+ int var3 = this.leafNodes[var1][0];
+ int var4 = this.leafNodes[var1][1];
+ int var5 = this.leafNodes[var1][2];
+ this.generateLeafNode(var3, var4, var5);
+ }
+ }
+
+ /**
+ * Indicates whether or not a leaf node requires additional wood to be added to
+ * preserve integrity.
+ */
+ boolean leafNodeNeedsBase(int par1) {
+ return (double) par1 >= (double) this.heightLimit * 0.2D;
+ }
+
+ /**
+ * Places the trunk for the big tree that is being generated. Able to generate
+ * double-sized trunks by changing a field that is always 1 to 2.
+ */
+ void generateTrunk() {
+ int var1 = this.basePos[0];
+ int var2 = this.basePos[1];
+ int var3 = this.basePos[1] + this.height;
+ int var4 = this.basePos[2];
+ int[] var5 = new int[] { var1, var2, var4 };
+ int[] var6 = new int[] { var1, var3, var4 };
+ this.placeBlockLine(var5, var6, Block.wood.blockID);
+
+ if (this.trunkSize == 2) {
+ ++var5[0];
+ ++var6[0];
+ this.placeBlockLine(var5, var6, Block.wood.blockID);
+ ++var5[2];
+ ++var6[2];
+ this.placeBlockLine(var5, var6, Block.wood.blockID);
+ var5[0] += -1;
+ var6[0] += -1;
+ this.placeBlockLine(var5, var6, Block.wood.blockID);
+ }
+ }
+
+ /**
+ * Generates additional wood blocks to fill out the bases of different leaf
+ * nodes that would otherwise degrade.
+ */
+ void generateLeafNodeBases() {
+ int var1 = 0;
+ int var2 = this.leafNodes.length;
+
+ for (int[] var3 = new int[] { this.basePos[0], this.basePos[1], this.basePos[2] }; var1 < var2; ++var1) {
+ int[] var4 = this.leafNodes[var1];
+ int[] var5 = new int[] { var4[0], var4[1], var4[2] };
+ var3[1] = var4[3];
+ int var6 = var3[1] - this.basePos[1];
+
+ if (this.leafNodeNeedsBase(var6)) {
+ this.placeBlockLine(var3, var5, (byte) Block.wood.blockID);
+ }
+ }
+ }
+
+ /**
+ * Checks a line of blocks in the world from the first coordinate to triplet to
+ * the second, returning the distance (in blocks) before a non-air, non-leaf
+ * block is encountered and/or the end is encountered.
+ */
+ int checkBlockLine(int[] par1ArrayOfInteger, int[] par2ArrayOfInteger) {
+ int[] var3 = new int[] { 0, 0, 0 };
+ byte var4 = 0;
+ byte var5;
+
+ for (var5 = 0; var4 < 3; ++var4) {
+ var3[var4] = par2ArrayOfInteger[var4] - par1ArrayOfInteger[var4];
+
+ if (Math.abs(var3[var4]) > Math.abs(var3[var5])) {
+ var5 = var4;
+ }
+ }
+
+ if (var3[var5] == 0) {
+ return -1;
+ } else {
+ byte var6 = otherCoordPairs[var5];
+ byte var7 = otherCoordPairs[var5 + 3];
+ byte var8;
+
+ if (var3[var5] > 0) {
+ var8 = 1;
+ } else {
+ var8 = -1;
+ }
+
+ double var9 = (double) var3[var6] / (double) var3[var5];
+ double var11 = (double) var3[var7] / (double) var3[var5];
+ int[] var13 = new int[] { 0, 0, 0 };
+ int var14 = 0;
+ int var15;
+
+ for (var15 = var3[var5] + var8; var14 != var15; var14 += var8) {
+ var13[var5] = par1ArrayOfInteger[var5] + var14;
+ var13[var6] = MathHelper.floor_double((double) par1ArrayOfInteger[var6] + (double) var14 * var9);
+ var13[var7] = MathHelper.floor_double((double) par1ArrayOfInteger[var7] + (double) var14 * var11);
+ int var16 = this.worldObj.getBlockId(var13[0], var13[1], var13[2]);
+
+ if (var16 != 0 && var16 != Block.leaves.blockID) {
+ break;
+ }
+ }
+
+ return var14 == var15 ? -1 : Math.abs(var14);
+ }
+ }
+
+ /**
+ * Returns a boolean indicating whether or not the current location for the
+ * tree, spanning basePos to to the height limit, is valid.
+ */
+ boolean validTreeLocation() {
+ int[] var1 = new int[] { this.basePos[0], this.basePos[1], this.basePos[2] };
+ int[] var2 = new int[] { this.basePos[0], this.basePos[1] + this.heightLimit - 1, this.basePos[2] };
+ int var3 = this.worldObj.getBlockId(this.basePos[0], this.basePos[1] - 1, this.basePos[2]);
+
+ if (var3 != 2 && var3 != 3) {
+ return false;
+ } else {
+ int var4 = this.checkBlockLine(var1, var2);
+
+ if (var4 == -1) {
+ return true;
+ } else if (var4 < 6) {
+ return false;
+ } else {
+ this.heightLimit = var4;
+ return true;
+ }
+ }
+ }
+
+ /**
+ * Rescales the generator settings, only used in WorldGenBigTree
+ */
+ public void setScale(double par1, double par3, double par5) {
+ this.heightLimitLimit = (int) (par1 * 12.0D);
+
+ if (par1 > 0.5D) {
+ this.leafDistanceLimit = 5;
+ }
+
+ this.scaleWidth = par3;
+ this.leafDensity = par5;
+ }
+
+ public boolean generate(World par1World, EaglercraftRandom par2Random, int par3, int par4, int par5) {
+ this.worldObj = par1World;
+ long var6 = par2Random.nextLong();
+ this.rand.setSeed(var6);
+ this.basePos[0] = par3;
+ this.basePos[1] = par4;
+ this.basePos[2] = par5;
+
+ if (this.heightLimit == 0) {
+ this.heightLimit = 5 + this.rand.nextInt(this.heightLimitLimit);
+ }
+
+ if (!this.validTreeLocation()) {
+ return false;
+ } else {
+ this.generateLeafNodeList();
+ this.generateLeaves();
+ this.generateTrunk();
+ this.generateLeafNodeBases();
+ return true;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldGenCactus.java b/sp-server/src/main/java/net/minecraft/src/WorldGenCactus.java
new file mode 100644
index 0000000..4b647a8
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldGenCactus.java
@@ -0,0 +1,25 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class WorldGenCactus extends WorldGenerator {
+ public boolean generate(World par1World, EaglercraftRandom par2Random, int par3, int par4, int par5) {
+ for (int var6 = 0; var6 < 10; ++var6) {
+ int var7 = par3 + par2Random.nextInt(8) - par2Random.nextInt(8);
+ int var8 = par4 + par2Random.nextInt(4) - par2Random.nextInt(4);
+ int var9 = par5 + par2Random.nextInt(8) - par2Random.nextInt(8);
+
+ if (par1World.isAirBlock(var7, var8, var9)) {
+ int var10 = 1 + par2Random.nextInt(par2Random.nextInt(3) + 1);
+
+ for (int var11 = 0; var11 < var10; ++var11) {
+ if (Block.cactus.canBlockStay(par1World, var7, var8 + var11, var9)) {
+ par1World.setBlock(var7, var8 + var11, var9, Block.cactus.blockID, 0, 2);
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldGenClay.java b/sp-server/src/main/java/net/minecraft/src/WorldGenClay.java
new file mode 100644
index 0000000..fe4fa25
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldGenClay.java
@@ -0,0 +1,44 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class WorldGenClay extends WorldGenerator {
+ /** The block ID for clay. */
+ private int clayBlockId;
+
+ /** The number of blocks to generate. */
+ private int numberOfBlocks;
+
+ public WorldGenClay(int par1) {
+ this.clayBlockId = Block.blockClay.blockID;
+ this.numberOfBlocks = par1;
+ }
+
+ public boolean generate(World par1World, EaglercraftRandom par2Random, int par3, int par4, int par5) {
+ if (par1World.getBlockMaterial(par3, par4, par5) != Material.water) {
+ return false;
+ } else {
+ int var6 = par2Random.nextInt(this.numberOfBlocks - 2) + 2;
+ byte var7 = 1;
+
+ for (int var8 = par3 - var6; var8 <= par3 + var6; ++var8) {
+ for (int var9 = par5 - var6; var9 <= par5 + var6; ++var9) {
+ int var10 = var8 - par3;
+ int var11 = var9 - par5;
+
+ if (var10 * var10 + var11 * var11 <= var6 * var6) {
+ for (int var12 = par4 - var7; var12 <= par4 + var7; ++var12) {
+ int var13 = par1World.getBlockId(var8, var12, var9);
+
+ if (var13 == Block.dirt.blockID || var13 == Block.blockClay.blockID) {
+ par1World.setBlock(var8, var12, var9, this.clayBlockId, 0, 2);
+ }
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldGenDeadBush.java b/sp-server/src/main/java/net/minecraft/src/WorldGenDeadBush.java
new file mode 100644
index 0000000..7f45537
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldGenDeadBush.java
@@ -0,0 +1,34 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class WorldGenDeadBush extends WorldGenerator {
+ /** stores the ID for WorldGenDeadBush */
+ private int deadBushID;
+
+ public WorldGenDeadBush(int par1) {
+ this.deadBushID = par1;
+ }
+
+ public boolean generate(World par1World, EaglercraftRandom par2Random, int par3, int par4, int par5) {
+ int var11;
+
+ for (boolean var6 = false; ((var11 = par1World.getBlockId(par3, par4, par5)) == 0
+ || var11 == Block.leaves.blockID) && par4 > 0; --par4) {
+ ;
+ }
+
+ for (int var7 = 0; var7 < 4; ++var7) {
+ int var8 = par3 + par2Random.nextInt(8) - par2Random.nextInt(8);
+ int var9 = par4 + par2Random.nextInt(4) - par2Random.nextInt(4);
+ int var10 = par5 + par2Random.nextInt(8) - par2Random.nextInt(8);
+
+ if (par1World.isAirBlock(var8, var9, var10)
+ && Block.blocksList[this.deadBushID].canBlockStay(par1World, var8, var9, var10)) {
+ par1World.setBlock(var8, var9, var10, this.deadBushID, 0, 2);
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldGenDesertWells.java b/sp-server/src/main/java/net/minecraft/src/WorldGenDesertWells.java
new file mode 100644
index 0000000..c93319d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldGenDesertWells.java
@@ -0,0 +1,75 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class WorldGenDesertWells extends WorldGenerator {
+ public boolean generate(World par1World, EaglercraftRandom par2Random, int par3, int par4, int par5) {
+ while (par1World.isAirBlock(par3, par4, par5) && par4 > 2) {
+ --par4;
+ }
+
+ int var6 = par1World.getBlockId(par3, par4, par5);
+
+ if (var6 != Block.sand.blockID) {
+ return false;
+ } else {
+ int var7;
+ int var8;
+
+ for (var7 = -2; var7 <= 2; ++var7) {
+ for (var8 = -2; var8 <= 2; ++var8) {
+ if (par1World.isAirBlock(par3 + var7, par4 - 1, par5 + var8)
+ && par1World.isAirBlock(par3 + var7, par4 - 2, par5 + var8)) {
+ return false;
+ }
+ }
+ }
+
+ for (var7 = -1; var7 <= 0; ++var7) {
+ for (var8 = -2; var8 <= 2; ++var8) {
+ for (int var9 = -2; var9 <= 2; ++var9) {
+ par1World.setBlock(par3 + var8, par4 + var7, par5 + var9, Block.sandStone.blockID, 0, 2);
+ }
+ }
+ }
+
+ par1World.setBlock(par3, par4, par5, Block.waterMoving.blockID, 0, 2);
+ par1World.setBlock(par3 - 1, par4, par5, Block.waterMoving.blockID, 0, 2);
+ par1World.setBlock(par3 + 1, par4, par5, Block.waterMoving.blockID, 0, 2);
+ par1World.setBlock(par3, par4, par5 - 1, Block.waterMoving.blockID, 0, 2);
+ par1World.setBlock(par3, par4, par5 + 1, Block.waterMoving.blockID, 0, 2);
+
+ for (var7 = -2; var7 <= 2; ++var7) {
+ for (var8 = -2; var8 <= 2; ++var8) {
+ if (var7 == -2 || var7 == 2 || var8 == -2 || var8 == 2) {
+ par1World.setBlock(par3 + var7, par4 + 1, par5 + var8, Block.sandStone.blockID, 0, 2);
+ }
+ }
+ }
+
+ par1World.setBlock(par3 + 2, par4 + 1, par5, Block.stoneSingleSlab.blockID, 1, 2);
+ par1World.setBlock(par3 - 2, par4 + 1, par5, Block.stoneSingleSlab.blockID, 1, 2);
+ par1World.setBlock(par3, par4 + 1, par5 + 2, Block.stoneSingleSlab.blockID, 1, 2);
+ par1World.setBlock(par3, par4 + 1, par5 - 2, Block.stoneSingleSlab.blockID, 1, 2);
+
+ for (var7 = -1; var7 <= 1; ++var7) {
+ for (var8 = -1; var8 <= 1; ++var8) {
+ if (var7 == 0 && var8 == 0) {
+ par1World.setBlock(par3 + var7, par4 + 4, par5 + var8, Block.sandStone.blockID, 0, 2);
+ } else {
+ par1World.setBlock(par3 + var7, par4 + 4, par5 + var8, Block.stoneSingleSlab.blockID, 1, 2);
+ }
+ }
+ }
+
+ for (var7 = 1; var7 <= 3; ++var7) {
+ par1World.setBlock(par3 - 1, par4 + var7, par5 - 1, Block.sandStone.blockID, 0, 2);
+ par1World.setBlock(par3 - 1, par4 + var7, par5 + 1, Block.sandStone.blockID, 0, 2);
+ par1World.setBlock(par3 + 1, par4 + var7, par5 - 1, Block.sandStone.blockID, 0, 2);
+ par1World.setBlock(par3 + 1, par4 + var7, par5 + 1, Block.sandStone.blockID, 0, 2);
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldGenDungeons.java b/sp-server/src/main/java/net/minecraft/src/WorldGenDungeons.java
new file mode 100644
index 0000000..46f859b
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldGenDungeons.java
@@ -0,0 +1,173 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class WorldGenDungeons extends WorldGenerator {
+ public boolean generate(World par1World, EaglercraftRandom par2Random, int par3, int par4, int par5) {
+ byte var6 = 3;
+ int var7 = par2Random.nextInt(2) + 2;
+ int var8 = par2Random.nextInt(2) + 2;
+ int var9 = 0;
+ int var10;
+ int var11;
+ int var12;
+
+ for (var10 = par3 - var7 - 1; var10 <= par3 + var7 + 1; ++var10) {
+ for (var11 = par4 - 1; var11 <= par4 + var6 + 1; ++var11) {
+ for (var12 = par5 - var8 - 1; var12 <= par5 + var8 + 1; ++var12) {
+ Material var13 = par1World.getBlockMaterial(var10, var11, var12);
+
+ if (var11 == par4 - 1 && !var13.isSolid()) {
+ return false;
+ }
+
+ if (var11 == par4 + var6 + 1 && !var13.isSolid()) {
+ return false;
+ }
+
+ if ((var10 == par3 - var7 - 1 || var10 == par3 + var7 + 1 || var12 == par5 - var8 - 1
+ || var12 == par5 + var8 + 1) && var11 == par4 && par1World.isAirBlock(var10, var11, var12)
+ && par1World.isAirBlock(var10, var11 + 1, var12)) {
+ ++var9;
+ }
+ }
+ }
+ }
+
+ if (var9 >= 1 && var9 <= 5) {
+ for (var10 = par3 - var7 - 1; var10 <= par3 + var7 + 1; ++var10) {
+ for (var11 = par4 + var6; var11 >= par4 - 1; --var11) {
+ for (var12 = par5 - var8 - 1; var12 <= par5 + var8 + 1; ++var12) {
+ if (var10 != par3 - var7 - 1 && var11 != par4 - 1 && var12 != par5 - var8 - 1
+ && var10 != par3 + var7 + 1 && var11 != par4 + var6 + 1 && var12 != par5 + var8 + 1) {
+ par1World.setBlockToAir(var10, var11, var12);
+ } else if (var11 >= 0 && !par1World.getBlockMaterial(var10, var11 - 1, var12).isSolid()) {
+ par1World.setBlockToAir(var10, var11, var12);
+ } else if (par1World.getBlockMaterial(var10, var11, var12).isSolid()) {
+ if (var11 == par4 - 1 && par2Random.nextInt(4) != 0) {
+ par1World.setBlock(var10, var11, var12, Block.cobblestoneMossy.blockID, 0, 2);
+ } else {
+ par1World.setBlock(var10, var11, var12, Block.cobblestone.blockID, 0, 2);
+ }
+ }
+ }
+ }
+ }
+
+ var10 = 0;
+
+ while (var10 < 2) {
+ var11 = 0;
+
+ while (true) {
+ if (var11 < 3) {
+ label113: {
+ var12 = par3 + par2Random.nextInt(var7 * 2 + 1) - var7;
+ int var14 = par5 + par2Random.nextInt(var8 * 2 + 1) - var8;
+
+ if (par1World.isAirBlock(var12, par4, var14)) {
+ int var15 = 0;
+
+ if (par1World.getBlockMaterial(var12 - 1, par4, var14).isSolid()) {
+ ++var15;
+ }
+
+ if (par1World.getBlockMaterial(var12 + 1, par4, var14).isSolid()) {
+ ++var15;
+ }
+
+ if (par1World.getBlockMaterial(var12, par4, var14 - 1).isSolid()) {
+ ++var15;
+ }
+
+ if (par1World.getBlockMaterial(var12, par4, var14 + 1).isSolid()) {
+ ++var15;
+ }
+
+ if (var15 == 1) {
+ par1World.setBlock(var12, par4, var14, Block.chest.blockID, 0, 2);
+ TileEntityChest var16 = (TileEntityChest) par1World.getBlockTileEntity(var12, par4,
+ var14);
+
+ if (var16 != null) {
+ for (int var17 = 0; var17 < 8; ++var17) {
+ ItemStack var18 = this.pickCheckLootItem(par2Random);
+
+ if (var18 != null) {
+ var16.setInventorySlotContents(
+ par2Random.nextInt(var16.getSizeInventory()), var18);
+ }
+ }
+ }
+
+ break label113;
+ }
+ }
+
+ ++var11;
+ continue;
+ }
+ }
+
+ ++var10;
+ break;
+ }
+ }
+
+ par1World.setBlock(par3, par4, par5, Block.mobSpawner.blockID, 0, 2);
+ TileEntityMobSpawner var19 = (TileEntityMobSpawner) par1World.getBlockTileEntity(par3, par4, par5);
+
+ if (var19 != null) {
+ var19.func_98049_a().setMobID(this.pickMobSpawner(par2Random));
+ } else {
+ System.err.println("Failed to fetch mob spawner entity at (" + par3 + ", " + par4 + ", " + par5 + ")");
+ }
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Picks potentially a random item to add to a dungeon chest.
+ */
+ private ItemStack pickCheckLootItem(EaglercraftRandom par1Random) {
+ int var2 = par1Random.nextInt(12);
+ return var2 == 0 ? new ItemStack(Item.saddle)
+ : (var2 == 1 ? new ItemStack(Item.ingotIron, par1Random.nextInt(4) + 1)
+ : (var2 == 2 ? new ItemStack(Item.bread)
+ : (var2 == 3 ? new ItemStack(Item.wheat, par1Random.nextInt(4) + 1)
+ : (var2 == 4 ? new ItemStack(Item.gunpowder, par1Random.nextInt(4) + 1)
+ : (var2 == 5 ? new ItemStack(Item.silk, par1Random.nextInt(4) + 1)
+ : (var2 == 6 ? new ItemStack(Item.bucketEmpty)
+ : (var2 == 7 && par1Random.nextInt(100) == 0
+ ? new ItemStack(Item.appleGold)
+ : (var2 == 8 && par1Random.nextInt(2) == 0
+ ? new ItemStack(Item.redstone,
+ par1Random.nextInt(4) + 1)
+ : (var2 == 9 && par1Random.nextInt(
+ 10) == 0 ? new ItemStack(
+ Item.itemsList[Item.record13.itemID
+ + par1Random
+ .nextInt(
+ 2)])
+ : (var2 == 10
+ ? new ItemStack(
+ Item.dyePowder,
+ 1, 3)
+ : (var2 == 11
+ ? Item.enchantedBook
+ .func_92109_a(
+ par1Random)
+ : null)))))))))));
+ }
+
+ /**
+ * Randomly decides which spawner to use in a dungeon
+ */
+ private String pickMobSpawner(EaglercraftRandom par1Random) {
+ int var2 = par1Random.nextInt(4);
+ return var2 == 0 ? "Skeleton" : (var2 == 1 ? "Zombie" : (var2 == 2 ? "Zombie" : (var2 == 3 ? "Spider" : "")));
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldGenFire.java b/sp-server/src/main/java/net/minecraft/src/WorldGenFire.java
new file mode 100644
index 0000000..317a8f4
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldGenFire.java
@@ -0,0 +1,20 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class WorldGenFire extends WorldGenerator {
+ public boolean generate(World par1World, EaglercraftRandom par2Random, int par3, int par4, int par5) {
+ for (int var6 = 0; var6 < 64; ++var6) {
+ int var7 = par3 + par2Random.nextInt(8) - par2Random.nextInt(8);
+ int var8 = par4 + par2Random.nextInt(4) - par2Random.nextInt(4);
+ int var9 = par5 + par2Random.nextInt(8) - par2Random.nextInt(8);
+
+ if (par1World.isAirBlock(var7, var8, var9)
+ && par1World.getBlockId(var7, var8 - 1, var9) == Block.netherrack.blockID) {
+ par1World.setBlock(var7, var8, var9, Block.fire.blockID, 0, 2);
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldGenFlowers.java b/sp-server/src/main/java/net/minecraft/src/WorldGenFlowers.java
new file mode 100644
index 0000000..fa02ef6
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldGenFlowers.java
@@ -0,0 +1,27 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class WorldGenFlowers extends WorldGenerator {
+ /** The ID of the plant block used in this plant generator. */
+ private int plantBlockId;
+
+ public WorldGenFlowers(int par1) {
+ this.plantBlockId = par1;
+ }
+
+ public boolean generate(World par1World, EaglercraftRandom par2Random, int par3, int par4, int par5) {
+ for (int var6 = 0; var6 < 64; ++var6) {
+ int var7 = par3 + par2Random.nextInt(8) - par2Random.nextInt(8);
+ int var8 = par4 + par2Random.nextInt(4) - par2Random.nextInt(4);
+ int var9 = par5 + par2Random.nextInt(8) - par2Random.nextInt(8);
+
+ if (par1World.isAirBlock(var7, var8, var9) && (!par1World.provider.hasNoSky || var8 < 127)
+ && Block.blocksList[this.plantBlockId].canBlockStay(par1World, var7, var8, var9)) {
+ par1World.setBlock(var7, var8, var9, this.plantBlockId, 0, 2);
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldGenForest.java b/sp-server/src/main/java/net/minecraft/src/WorldGenForest.java
new file mode 100644
index 0000000..3ecd820
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldGenForest.java
@@ -0,0 +1,95 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class WorldGenForest extends WorldGenerator {
+ public WorldGenForest(boolean par1) {
+ super(par1);
+ }
+
+ public boolean generate(World par1World, EaglercraftRandom par2Random, int par3, int par4, int par5) {
+ int var6 = par2Random.nextInt(3) + 5;
+ boolean var7 = true;
+
+ if (par4 >= 1 && par4 + var6 + 1 <= 256) {
+ int var8;
+ int var10;
+ int var11;
+ int var12;
+
+ for (var8 = par4; var8 <= par4 + 1 + var6; ++var8) {
+ byte var9 = 1;
+
+ if (var8 == par4) {
+ var9 = 0;
+ }
+
+ if (var8 >= par4 + 1 + var6 - 2) {
+ var9 = 2;
+ }
+
+ for (var10 = par3 - var9; var10 <= par3 + var9 && var7; ++var10) {
+ for (var11 = par5 - var9; var11 <= par5 + var9 && var7; ++var11) {
+ if (var8 >= 0 && var8 < 256) {
+ var12 = par1World.getBlockId(var10, var8, var11);
+
+ if (var12 != 0 && var12 != Block.leaves.blockID) {
+ var7 = false;
+ }
+ } else {
+ var7 = false;
+ }
+ }
+ }
+ }
+
+ if (!var7) {
+ return false;
+ } else {
+ var8 = par1World.getBlockId(par3, par4 - 1, par5);
+
+ if ((var8 == Block.grass.blockID || var8 == Block.dirt.blockID) && par4 < 256 - var6 - 1) {
+ this.setBlock(par1World, par3, par4 - 1, par5, Block.dirt.blockID);
+ int var17;
+
+ for (var17 = par4 - 3 + var6; var17 <= par4 + var6; ++var17) {
+ var10 = var17 - (par4 + var6);
+ var11 = 1 - var10 / 2;
+
+ for (var12 = par3 - var11; var12 <= par3 + var11; ++var12) {
+ int var13 = var12 - par3;
+
+ for (int var14 = par5 - var11; var14 <= par5 + var11; ++var14) {
+ int var15 = var14 - par5;
+
+ if (Math.abs(var13) != var11 || Math.abs(var15) != var11
+ || par2Random.nextInt(2) != 0 && var10 != 0) {
+ int var16 = par1World.getBlockId(var12, var17, var14);
+
+ if (var16 == 0 || var16 == Block.leaves.blockID) {
+ this.setBlockAndMetadata(par1World, var12, var17, var14, Block.leaves.blockID,
+ 2);
+ }
+ }
+ }
+ }
+ }
+
+ for (var17 = 0; var17 < var6; ++var17) {
+ var10 = par1World.getBlockId(par3, par4 + var17, par5);
+
+ if (var10 == 0 || var10 == Block.leaves.blockID) {
+ this.setBlockAndMetadata(par1World, par3, par4 + var17, par5, Block.wood.blockID, 2);
+ }
+ }
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+ } else {
+ return false;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldGenGlowStone1.java b/sp-server/src/main/java/net/minecraft/src/WorldGenGlowStone1.java
new file mode 100644
index 0000000..f0db6a2
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldGenGlowStone1.java
@@ -0,0 +1,63 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class WorldGenGlowStone1 extends WorldGenerator {
+ public boolean generate(World par1World, EaglercraftRandom par2Random, int par3, int par4, int par5) {
+ if (!par1World.isAirBlock(par3, par4, par5)) {
+ return false;
+ } else if (par1World.getBlockId(par3, par4 + 1, par5) != Block.netherrack.blockID) {
+ return false;
+ } else {
+ par1World.setBlock(par3, par4, par5, Block.glowStone.blockID, 0, 2);
+
+ for (int var6 = 0; var6 < 1500; ++var6) {
+ int var7 = par3 + par2Random.nextInt(8) - par2Random.nextInt(8);
+ int var8 = par4 - par2Random.nextInt(12);
+ int var9 = par5 + par2Random.nextInt(8) - par2Random.nextInt(8);
+
+ if (par1World.getBlockId(var7, var8, var9) == 0) {
+ int var10 = 0;
+
+ for (int var11 = 0; var11 < 6; ++var11) {
+ int var12 = 0;
+
+ if (var11 == 0) {
+ var12 = par1World.getBlockId(var7 - 1, var8, var9);
+ }
+
+ if (var11 == 1) {
+ var12 = par1World.getBlockId(var7 + 1, var8, var9);
+ }
+
+ if (var11 == 2) {
+ var12 = par1World.getBlockId(var7, var8 - 1, var9);
+ }
+
+ if (var11 == 3) {
+ var12 = par1World.getBlockId(var7, var8 + 1, var9);
+ }
+
+ if (var11 == 4) {
+ var12 = par1World.getBlockId(var7, var8, var9 - 1);
+ }
+
+ if (var11 == 5) {
+ var12 = par1World.getBlockId(var7, var8, var9 + 1);
+ }
+
+ if (var12 == Block.glowStone.blockID) {
+ ++var10;
+ }
+ }
+
+ if (var10 == 1) {
+ par1World.setBlock(var7, var8, var9, Block.glowStone.blockID, 0, 2);
+ }
+ }
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldGenGlowStone2.java b/sp-server/src/main/java/net/minecraft/src/WorldGenGlowStone2.java
new file mode 100644
index 0000000..5ace90a
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldGenGlowStone2.java
@@ -0,0 +1,63 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class WorldGenGlowStone2 extends WorldGenerator {
+ public boolean generate(World par1World, EaglercraftRandom par2Random, int par3, int par4, int par5) {
+ if (!par1World.isAirBlock(par3, par4, par5)) {
+ return false;
+ } else if (par1World.getBlockId(par3, par4 + 1, par5) != Block.netherrack.blockID) {
+ return false;
+ } else {
+ par1World.setBlock(par3, par4, par5, Block.glowStone.blockID, 0, 2);
+
+ for (int var6 = 0; var6 < 1500; ++var6) {
+ int var7 = par3 + par2Random.nextInt(8) - par2Random.nextInt(8);
+ int var8 = par4 - par2Random.nextInt(12);
+ int var9 = par5 + par2Random.nextInt(8) - par2Random.nextInt(8);
+
+ if (par1World.getBlockId(var7, var8, var9) == 0) {
+ int var10 = 0;
+
+ for (int var11 = 0; var11 < 6; ++var11) {
+ int var12 = 0;
+
+ if (var11 == 0) {
+ var12 = par1World.getBlockId(var7 - 1, var8, var9);
+ }
+
+ if (var11 == 1) {
+ var12 = par1World.getBlockId(var7 + 1, var8, var9);
+ }
+
+ if (var11 == 2) {
+ var12 = par1World.getBlockId(var7, var8 - 1, var9);
+ }
+
+ if (var11 == 3) {
+ var12 = par1World.getBlockId(var7, var8 + 1, var9);
+ }
+
+ if (var11 == 4) {
+ var12 = par1World.getBlockId(var7, var8, var9 - 1);
+ }
+
+ if (var11 == 5) {
+ var12 = par1World.getBlockId(var7, var8, var9 + 1);
+ }
+
+ if (var12 == Block.glowStone.blockID) {
+ ++var10;
+ }
+ }
+
+ if (var10 == 1) {
+ par1World.setBlock(var7, var8, var9, Block.glowStone.blockID, 0, 2);
+ }
+ }
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldGenHellLava.java b/sp-server/src/main/java/net/minecraft/src/WorldGenHellLava.java
new file mode 100644
index 0000000..71271b4
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldGenHellLava.java
@@ -0,0 +1,76 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class WorldGenHellLava extends WorldGenerator {
+ /** Stores the ID for WorldGenHellLava */
+ private int hellLavaID;
+ private boolean field_94524_b = false;
+
+ public WorldGenHellLava(int par1, boolean par2) {
+ this.hellLavaID = par1;
+ this.field_94524_b = par2;
+ }
+
+ public boolean generate(World par1World, EaglercraftRandom par2Random, int par3, int par4, int par5) {
+ if (par1World.getBlockId(par3, par4 + 1, par5) != Block.netherrack.blockID) {
+ return false;
+ } else if (par1World.getBlockId(par3, par4, par5) != 0
+ && par1World.getBlockId(par3, par4, par5) != Block.netherrack.blockID) {
+ return false;
+ } else {
+ int var6 = 0;
+
+ if (par1World.getBlockId(par3 - 1, par4, par5) == Block.netherrack.blockID) {
+ ++var6;
+ }
+
+ if (par1World.getBlockId(par3 + 1, par4, par5) == Block.netherrack.blockID) {
+ ++var6;
+ }
+
+ if (par1World.getBlockId(par3, par4, par5 - 1) == Block.netherrack.blockID) {
+ ++var6;
+ }
+
+ if (par1World.getBlockId(par3, par4, par5 + 1) == Block.netherrack.blockID) {
+ ++var6;
+ }
+
+ if (par1World.getBlockId(par3, par4 - 1, par5) == Block.netherrack.blockID) {
+ ++var6;
+ }
+
+ int var7 = 0;
+
+ if (par1World.isAirBlock(par3 - 1, par4, par5)) {
+ ++var7;
+ }
+
+ if (par1World.isAirBlock(par3 + 1, par4, par5)) {
+ ++var7;
+ }
+
+ if (par1World.isAirBlock(par3, par4, par5 - 1)) {
+ ++var7;
+ }
+
+ if (par1World.isAirBlock(par3, par4, par5 + 1)) {
+ ++var7;
+ }
+
+ if (par1World.isAirBlock(par3, par4 - 1, par5)) {
+ ++var7;
+ }
+
+ if (!this.field_94524_b && var6 == 4 && var7 == 1 || var6 == 5) {
+ par1World.setBlock(par3, par4, par5, this.hellLavaID, 0, 2);
+ par1World.scheduledUpdatesAreImmediate = true;
+ Block.blocksList[this.hellLavaID].updateTick(par1World, par3, par4, par5, par2Random);
+ par1World.scheduledUpdatesAreImmediate = false;
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldGenHugeTrees.java b/sp-server/src/main/java/net/minecraft/src/WorldGenHugeTrees.java
new file mode 100644
index 0000000..b3d6f4e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldGenHugeTrees.java
@@ -0,0 +1,211 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class WorldGenHugeTrees extends WorldGenerator {
+ /** The base height of the tree */
+ private final int baseHeight;
+
+ /** Sets the metadata for the wood blocks used */
+ private final int woodMetadata;
+
+ /** Sets the metadata for the leaves used in huge trees */
+ private final int leavesMetadata;
+
+ public WorldGenHugeTrees(boolean par1, int par2, int par3, int par4) {
+ super(par1);
+ this.baseHeight = par2;
+ this.woodMetadata = par3;
+ this.leavesMetadata = par4;
+ }
+
+ public boolean generate(World par1World, EaglercraftRandom par2Random, int par3, int par4, int par5) {
+ int var6 = par2Random.nextInt(3) + this.baseHeight;
+ boolean var7 = true;
+
+ if (par4 >= 1 && par4 + var6 + 1 <= 256) {
+ int var8;
+ int var10;
+ int var11;
+ int var12;
+
+ for (var8 = par4; var8 <= par4 + 1 + var6; ++var8) {
+ byte var9 = 2;
+
+ if (var8 == par4) {
+ var9 = 1;
+ }
+
+ if (var8 >= par4 + 1 + var6 - 2) {
+ var9 = 2;
+ }
+
+ for (var10 = par3 - var9; var10 <= par3 + var9 && var7; ++var10) {
+ for (var11 = par5 - var9; var11 <= par5 + var9 && var7; ++var11) {
+ if (var8 >= 0 && var8 < 256) {
+ var12 = par1World.getBlockId(var10, var8, var11);
+
+ if (var12 != 0 && var12 != Block.leaves.blockID && var12 != Block.grass.blockID
+ && var12 != Block.dirt.blockID && var12 != Block.wood.blockID
+ && var12 != Block.sapling.blockID) {
+ var7 = false;
+ }
+ } else {
+ var7 = false;
+ }
+ }
+ }
+ }
+
+ if (!var7) {
+ return false;
+ } else {
+ var8 = par1World.getBlockId(par3, par4 - 1, par5);
+
+ if ((var8 == Block.grass.blockID || var8 == Block.dirt.blockID) && par4 < 256 - var6 - 1) {
+ par1World.setBlock(par3, par4 - 1, par5, Block.dirt.blockID, 0, 2);
+ par1World.setBlock(par3 + 1, par4 - 1, par5, Block.dirt.blockID, 0, 2);
+ par1World.setBlock(par3, par4 - 1, par5 + 1, Block.dirt.blockID, 0, 2);
+ par1World.setBlock(par3 + 1, par4 - 1, par5 + 1, Block.dirt.blockID, 0, 2);
+ this.growLeaves(par1World, par3, par5, par4 + var6, 2, par2Random);
+
+ for (int var14 = par4 + var6 - 2 - par2Random.nextInt(4); var14 > par4 + var6 / 2; var14 -= 2
+ + par2Random.nextInt(4)) {
+ float var15 = par2Random.nextFloat() * (float) Math.PI * 2.0F;
+ var11 = par3 + (int) (0.5F + MathHelper.cos(var15) * 4.0F);
+ var12 = par5 + (int) (0.5F + MathHelper.sin(var15) * 4.0F);
+ this.growLeaves(par1World, var11, var12, var14, 0, par2Random);
+
+ for (int var13 = 0; var13 < 5; ++var13) {
+ var11 = par3 + (int) (1.5F + MathHelper.cos(var15) * (float) var13);
+ var12 = par5 + (int) (1.5F + MathHelper.sin(var15) * (float) var13);
+ this.setBlockAndMetadata(par1World, var11, var14 - 3 + var13 / 2, var12, Block.wood.blockID,
+ this.woodMetadata);
+ }
+ }
+
+ for (var10 = 0; var10 < var6; ++var10) {
+ var11 = par1World.getBlockId(par3, par4 + var10, par5);
+
+ if (var11 == 0 || var11 == Block.leaves.blockID) {
+ this.setBlockAndMetadata(par1World, par3, par4 + var10, par5, Block.wood.blockID,
+ this.woodMetadata);
+
+ if (var10 > 0) {
+ if (par2Random.nextInt(3) > 0 && par1World.isAirBlock(par3 - 1, par4 + var10, par5)) {
+ this.setBlockAndMetadata(par1World, par3 - 1, par4 + var10, par5,
+ Block.vine.blockID, 8);
+ }
+
+ if (par2Random.nextInt(3) > 0 && par1World.isAirBlock(par3, par4 + var10, par5 - 1)) {
+ this.setBlockAndMetadata(par1World, par3, par4 + var10, par5 - 1,
+ Block.vine.blockID, 1);
+ }
+ }
+ }
+
+ if (var10 < var6 - 1) {
+ var11 = par1World.getBlockId(par3 + 1, par4 + var10, par5);
+
+ if (var11 == 0 || var11 == Block.leaves.blockID) {
+ this.setBlockAndMetadata(par1World, par3 + 1, par4 + var10, par5, Block.wood.blockID,
+ this.woodMetadata);
+
+ if (var10 > 0) {
+ if (par2Random.nextInt(3) > 0
+ && par1World.isAirBlock(par3 + 2, par4 + var10, par5)) {
+ this.setBlockAndMetadata(par1World, par3 + 2, par4 + var10, par5,
+ Block.vine.blockID, 2);
+ }
+
+ if (par2Random.nextInt(3) > 0
+ && par1World.isAirBlock(par3 + 1, par4 + var10, par5 - 1)) {
+ this.setBlockAndMetadata(par1World, par3 + 1, par4 + var10, par5 - 1,
+ Block.vine.blockID, 1);
+ }
+ }
+ }
+
+ var11 = par1World.getBlockId(par3 + 1, par4 + var10, par5 + 1);
+
+ if (var11 == 0 || var11 == Block.leaves.blockID) {
+ this.setBlockAndMetadata(par1World, par3 + 1, par4 + var10, par5 + 1,
+ Block.wood.blockID, this.woodMetadata);
+
+ if (var10 > 0) {
+ if (par2Random.nextInt(3) > 0
+ && par1World.isAirBlock(par3 + 2, par4 + var10, par5 + 1)) {
+ this.setBlockAndMetadata(par1World, par3 + 2, par4 + var10, par5 + 1,
+ Block.vine.blockID, 2);
+ }
+
+ if (par2Random.nextInt(3) > 0
+ && par1World.isAirBlock(par3 + 1, par4 + var10, par5 + 2)) {
+ this.setBlockAndMetadata(par1World, par3 + 1, par4 + var10, par5 + 2,
+ Block.vine.blockID, 4);
+ }
+ }
+ }
+
+ var11 = par1World.getBlockId(par3, par4 + var10, par5 + 1);
+
+ if (var11 == 0 || var11 == Block.leaves.blockID) {
+ this.setBlockAndMetadata(par1World, par3, par4 + var10, par5 + 1, Block.wood.blockID,
+ this.woodMetadata);
+
+ if (var10 > 0) {
+ if (par2Random.nextInt(3) > 0
+ && par1World.isAirBlock(par3 - 1, par4 + var10, par5 + 1)) {
+ this.setBlockAndMetadata(par1World, par3 - 1, par4 + var10, par5 + 1,
+ Block.vine.blockID, 8);
+ }
+
+ if (par2Random.nextInt(3) > 0
+ && par1World.isAirBlock(par3, par4 + var10, par5 + 2)) {
+ this.setBlockAndMetadata(par1World, par3, par4 + var10, par5 + 2,
+ Block.vine.blockID, 4);
+ }
+ }
+ }
+ }
+ }
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+ } else {
+ return false;
+ }
+ }
+
+ private void growLeaves(World par1World, int par2, int par3, int par4, int par5, EaglercraftRandom par6Random) {
+ byte var7 = 2;
+
+ for (int var8 = par4 - var7; var8 <= par4; ++var8) {
+ int var9 = var8 - par4;
+ int var10 = par5 + 1 - var9;
+
+ for (int var11 = par2 - var10; var11 <= par2 + var10 + 1; ++var11) {
+ int var12 = var11 - par2;
+
+ for (int var13 = par3 - var10; var13 <= par3 + var10 + 1; ++var13) {
+ int var14 = var13 - par3;
+
+ if ((var12 >= 0 || var14 >= 0 || var12 * var12 + var14 * var14 <= var10 * var10)
+ && (var12 <= 0 && var14 <= 0 || var12 * var12 + var14 * var14 <= (var10 + 1) * (var10 + 1))
+ && (par6Random.nextInt(4) != 0
+ || var12 * var12 + var14 * var14 <= (var10 - 1) * (var10 - 1))) {
+ int var15 = par1World.getBlockId(var11, var8, var13);
+
+ if (var15 == 0 || var15 == Block.leaves.blockID) {
+ this.setBlockAndMetadata(par1World, var11, var8, var13, Block.leaves.blockID,
+ this.leavesMetadata);
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldGenLakes.java b/sp-server/src/main/java/net/minecraft/src/WorldGenLakes.java
new file mode 100644
index 0000000..d61c258
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldGenLakes.java
@@ -0,0 +1,151 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class WorldGenLakes extends WorldGenerator {
+ private int blockIndex;
+
+ public WorldGenLakes(int par1) {
+ this.blockIndex = par1;
+ }
+
+ public boolean generate(World par1World, EaglercraftRandom par2Random, int par3, int par4, int par5) {
+ par3 -= 8;
+
+ for (par5 -= 8; par4 > 5 && par1World.isAirBlock(par3, par4, par5); --par4) {
+ ;
+ }
+
+ if (par4 <= 4) {
+ return false;
+ } else {
+ par4 -= 4;
+ boolean[] var6 = new boolean[2048];
+ int var7 = par2Random.nextInt(4) + 4;
+ int var8;
+
+ for (var8 = 0; var8 < var7; ++var8) {
+ double var9 = par2Random.nextDouble() * 6.0D + 3.0D;
+ double var11 = par2Random.nextDouble() * 4.0D + 2.0D;
+ double var13 = par2Random.nextDouble() * 6.0D + 3.0D;
+ double var15 = par2Random.nextDouble() * (16.0D - var9 - 2.0D) + 1.0D + var9 / 2.0D;
+ double var17 = par2Random.nextDouble() * (8.0D - var11 - 4.0D) + 2.0D + var11 / 2.0D;
+ double var19 = par2Random.nextDouble() * (16.0D - var13 - 2.0D) + 1.0D + var13 / 2.0D;
+
+ for (int var21 = 1; var21 < 15; ++var21) {
+ for (int var22 = 1; var22 < 15; ++var22) {
+ for (int var23 = 1; var23 < 7; ++var23) {
+ double var24 = ((double) var21 - var15) / (var9 / 2.0D);
+ double var26 = ((double) var23 - var17) / (var11 / 2.0D);
+ double var28 = ((double) var22 - var19) / (var13 / 2.0D);
+ double var30 = var24 * var24 + var26 * var26 + var28 * var28;
+
+ if (var30 < 1.0D) {
+ var6[(var21 * 16 + var22) * 8 + var23] = true;
+ }
+ }
+ }
+ }
+ }
+
+ int var10;
+ int var32;
+ boolean var33;
+
+ for (var8 = 0; var8 < 16; ++var8) {
+ for (var32 = 0; var32 < 16; ++var32) {
+ for (var10 = 0; var10 < 8; ++var10) {
+ var33 = !var6[(var8 * 16 + var32) * 8 + var10]
+ && (var8 < 15 && var6[((var8 + 1) * 16 + var32) * 8 + var10]
+ || var8 > 0 && var6[((var8 - 1) * 16 + var32) * 8 + var10]
+ || var32 < 15 && var6[(var8 * 16 + var32 + 1) * 8 + var10]
+ || var32 > 0 && var6[(var8 * 16 + (var32 - 1)) * 8 + var10]
+ || var10 < 7 && var6[(var8 * 16 + var32) * 8 + var10 + 1]
+ || var10 > 0 && var6[(var8 * 16 + var32) * 8 + (var10 - 1)]);
+
+ if (var33) {
+ Material var12 = par1World.getBlockMaterial(par3 + var8, par4 + var10, par5 + var32);
+
+ if (var10 >= 4 && var12.isLiquid()) {
+ return false;
+ }
+
+ if (var10 < 4 && !var12.isSolid() && par1World.getBlockId(par3 + var8, par4 + var10,
+ par5 + var32) != this.blockIndex) {
+ return false;
+ }
+ }
+ }
+ }
+ }
+
+ for (var8 = 0; var8 < 16; ++var8) {
+ for (var32 = 0; var32 < 16; ++var32) {
+ for (var10 = 0; var10 < 8; ++var10) {
+ if (var6[(var8 * 16 + var32) * 8 + var10]) {
+ par1World.setBlock(par3 + var8, par4 + var10, par5 + var32,
+ var10 >= 4 ? 0 : this.blockIndex, 0, 2);
+ }
+ }
+ }
+ }
+
+ for (var8 = 0; var8 < 16; ++var8) {
+ for (var32 = 0; var32 < 16; ++var32) {
+ for (var10 = 4; var10 < 8; ++var10) {
+ if (var6[(var8 * 16 + var32) * 8 + var10]
+ && par1World.getBlockId(par3 + var8, par4 + var10 - 1,
+ par5 + var32) == Block.dirt.blockID
+ && par1World.getSavedLightValue(EnumSkyBlock.Sky, par3 + var8, par4 + var10,
+ par5 + var32) > 0) {
+ BiomeGenBase var34 = par1World.getBiomeGenForCoords(par3 + var8, par5 + var32);
+
+ if (var34.topBlock == Block.mycelium.blockID) {
+ par1World.setBlock(par3 + var8, par4 + var10 - 1, par5 + var32, Block.mycelium.blockID,
+ 0, 2);
+ } else {
+ par1World.setBlock(par3 + var8, par4 + var10 - 1, par5 + var32, Block.grass.blockID, 0,
+ 2);
+ }
+ }
+ }
+ }
+ }
+
+ if (Block.blocksList[this.blockIndex].blockMaterial == Material.lava) {
+ for (var8 = 0; var8 < 16; ++var8) {
+ for (var32 = 0; var32 < 16; ++var32) {
+ for (var10 = 0; var10 < 8; ++var10) {
+ var33 = !var6[(var8 * 16 + var32) * 8 + var10]
+ && (var8 < 15 && var6[((var8 + 1) * 16 + var32) * 8 + var10]
+ || var8 > 0 && var6[((var8 - 1) * 16 + var32) * 8 + var10]
+ || var32 < 15 && var6[(var8 * 16 + var32 + 1) * 8 + var10]
+ || var32 > 0 && var6[(var8 * 16 + (var32 - 1)) * 8 + var10]
+ || var10 < 7 && var6[(var8 * 16 + var32) * 8 + var10 + 1]
+ || var10 > 0 && var6[(var8 * 16 + var32) * 8 + (var10 - 1)]);
+
+ if (var33 && (var10 < 4 || par2Random.nextInt(2) != 0)
+ && par1World.getBlockMaterial(par3 + var8, par4 + var10, par5 + var32).isSolid()) {
+ par1World.setBlock(par3 + var8, par4 + var10, par5 + var32, Block.stone.blockID, 0, 2);
+ }
+ }
+ }
+ }
+ }
+
+ if (Block.blocksList[this.blockIndex].blockMaterial == Material.water) {
+ for (var8 = 0; var8 < 16; ++var8) {
+ for (var32 = 0; var32 < 16; ++var32) {
+ byte var35 = 4;
+
+ if (par1World.isBlockFreezable(par3 + var8, par4 + var35, par5 + var32)) {
+ par1World.setBlock(par3 + var8, par4 + var35, par5 + var32, Block.ice.blockID, 0, 2);
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldGenLiquids.java b/sp-server/src/main/java/net/minecraft/src/WorldGenLiquids.java
new file mode 100644
index 0000000..81a0275
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldGenLiquids.java
@@ -0,0 +1,68 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class WorldGenLiquids extends WorldGenerator {
+ /** The ID of the liquid block used in this liquid generator. */
+ private int liquidBlockId;
+
+ public WorldGenLiquids(int par1) {
+ this.liquidBlockId = par1;
+ }
+
+ public boolean generate(World par1World, EaglercraftRandom par2Random, int par3, int par4, int par5) {
+ if (par1World.getBlockId(par3, par4 + 1, par5) != Block.stone.blockID) {
+ return false;
+ } else if (par1World.getBlockId(par3, par4 - 1, par5) != Block.stone.blockID) {
+ return false;
+ } else if (par1World.getBlockId(par3, par4, par5) != 0
+ && par1World.getBlockId(par3, par4, par5) != Block.stone.blockID) {
+ return false;
+ } else {
+ int var6 = 0;
+
+ if (par1World.getBlockId(par3 - 1, par4, par5) == Block.stone.blockID) {
+ ++var6;
+ }
+
+ if (par1World.getBlockId(par3 + 1, par4, par5) == Block.stone.blockID) {
+ ++var6;
+ }
+
+ if (par1World.getBlockId(par3, par4, par5 - 1) == Block.stone.blockID) {
+ ++var6;
+ }
+
+ if (par1World.getBlockId(par3, par4, par5 + 1) == Block.stone.blockID) {
+ ++var6;
+ }
+
+ int var7 = 0;
+
+ if (par1World.isAirBlock(par3 - 1, par4, par5)) {
+ ++var7;
+ }
+
+ if (par1World.isAirBlock(par3 + 1, par4, par5)) {
+ ++var7;
+ }
+
+ if (par1World.isAirBlock(par3, par4, par5 - 1)) {
+ ++var7;
+ }
+
+ if (par1World.isAirBlock(par3, par4, par5 + 1)) {
+ ++var7;
+ }
+
+ if (var6 == 3 && var7 == 1) {
+ par1World.setBlock(par3, par4, par5, this.liquidBlockId, 0, 2);
+ par1World.scheduledUpdatesAreImmediate = true;
+ Block.blocksList[this.liquidBlockId].updateTick(par1World, par3, par4, par5, par2Random);
+ par1World.scheduledUpdatesAreImmediate = false;
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldGenMinable.java b/sp-server/src/main/java/net/minecraft/src/WorldGenMinable.java
new file mode 100644
index 0000000..0ac9d36
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldGenMinable.java
@@ -0,0 +1,72 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class WorldGenMinable extends WorldGenerator {
+ /** The block ID of the ore to be placed using this generator. */
+ private int minableBlockId;
+
+ /** The number of blocks to generate. */
+ private int numberOfBlocks;
+ private int field_94523_c;
+
+ public WorldGenMinable(int par1, int par2) {
+ this(par1, par2, Block.stone.blockID);
+ }
+
+ public WorldGenMinable(int par1, int par2, int par3) {
+ this.minableBlockId = par1;
+ this.numberOfBlocks = par2;
+ this.field_94523_c = par3;
+ }
+
+ public boolean generate(World par1World, EaglercraftRandom par2Random, int par3, int par4, int par5) {
+ float var6 = par2Random.nextFloat() * (float) Math.PI;
+ double var7 = (double) ((float) (par3 + 8) + MathHelper.sin(var6) * (float) this.numberOfBlocks / 8.0F);
+ double var9 = (double) ((float) (par3 + 8) - MathHelper.sin(var6) * (float) this.numberOfBlocks / 8.0F);
+ double var11 = (double) ((float) (par5 + 8) + MathHelper.cos(var6) * (float) this.numberOfBlocks / 8.0F);
+ double var13 = (double) ((float) (par5 + 8) - MathHelper.cos(var6) * (float) this.numberOfBlocks / 8.0F);
+ double var15 = (double) (par4 + par2Random.nextInt(3) - 2);
+ double var17 = (double) (par4 + par2Random.nextInt(3) - 2);
+
+ for (int var19 = 0; var19 <= this.numberOfBlocks; ++var19) {
+ double var20 = var7 + (var9 - var7) * (double) var19 / (double) this.numberOfBlocks;
+ double var22 = var15 + (var17 - var15) * (double) var19 / (double) this.numberOfBlocks;
+ double var24 = var11 + (var13 - var11) * (double) var19 / (double) this.numberOfBlocks;
+ double var26 = par2Random.nextDouble() * (double) this.numberOfBlocks / 16.0D;
+ double var28 = (double) (MathHelper.sin((float) var19 * (float) Math.PI / (float) this.numberOfBlocks)
+ + 1.0F) * var26 + 1.0D;
+ double var30 = (double) (MathHelper.sin((float) var19 * (float) Math.PI / (float) this.numberOfBlocks)
+ + 1.0F) * var26 + 1.0D;
+ int var32 = MathHelper.floor_double(var20 - var28 / 2.0D);
+ int var33 = MathHelper.floor_double(var22 - var30 / 2.0D);
+ int var34 = MathHelper.floor_double(var24 - var28 / 2.0D);
+ int var35 = MathHelper.floor_double(var20 + var28 / 2.0D);
+ int var36 = MathHelper.floor_double(var22 + var30 / 2.0D);
+ int var37 = MathHelper.floor_double(var24 + var28 / 2.0D);
+
+ for (int var38 = var32; var38 <= var35; ++var38) {
+ double var39 = ((double) var38 + 0.5D - var20) / (var28 / 2.0D);
+
+ if (var39 * var39 < 1.0D) {
+ for (int var41 = var33; var41 <= var36; ++var41) {
+ double var42 = ((double) var41 + 0.5D - var22) / (var30 / 2.0D);
+
+ if (var39 * var39 + var42 * var42 < 1.0D) {
+ for (int var44 = var34; var44 <= var37; ++var44) {
+ double var45 = ((double) var44 + 0.5D - var24) / (var28 / 2.0D);
+
+ if (var39 * var39 + var42 * var42 + var45 * var45 < 1.0D
+ && par1World.getBlockId(var38, var41, var44) == this.field_94523_c) {
+ par1World.setBlock(var38, var41, var44, this.minableBlockId, 0, 2);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldGenPumpkin.java b/sp-server/src/main/java/net/minecraft/src/WorldGenPumpkin.java
new file mode 100644
index 0000000..8795201
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldGenPumpkin.java
@@ -0,0 +1,21 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class WorldGenPumpkin extends WorldGenerator {
+ public boolean generate(World par1World, EaglercraftRandom par2Random, int par3, int par4, int par5) {
+ for (int var6 = 0; var6 < 64; ++var6) {
+ int var7 = par3 + par2Random.nextInt(8) - par2Random.nextInt(8);
+ int var8 = par4 + par2Random.nextInt(4) - par2Random.nextInt(4);
+ int var9 = par5 + par2Random.nextInt(8) - par2Random.nextInt(8);
+
+ if (par1World.isAirBlock(var7, var8, var9)
+ && par1World.getBlockId(var7, var8 - 1, var9) == Block.grass.blockID
+ && Block.pumpkin.canPlaceBlockAt(par1World, var7, var8, var9)) {
+ par1World.setBlock(var7, var8, var9, Block.pumpkin.blockID, par2Random.nextInt(4), 2);
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldGenReed.java b/sp-server/src/main/java/net/minecraft/src/WorldGenReed.java
new file mode 100644
index 0000000..64b68f8
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldGenReed.java
@@ -0,0 +1,29 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class WorldGenReed extends WorldGenerator {
+ public boolean generate(World par1World, EaglercraftRandom par2Random, int par3, int par4, int par5) {
+ for (int var6 = 0; var6 < 20; ++var6) {
+ int var7 = par3 + par2Random.nextInt(4) - par2Random.nextInt(4);
+ int var8 = par4;
+ int var9 = par5 + par2Random.nextInt(4) - par2Random.nextInt(4);
+
+ if (par1World.isAirBlock(var7, par4, var9)
+ && (par1World.getBlockMaterial(var7 - 1, par4 - 1, var9) == Material.water
+ || par1World.getBlockMaterial(var7 + 1, par4 - 1, var9) == Material.water
+ || par1World.getBlockMaterial(var7, par4 - 1, var9 - 1) == Material.water
+ || par1World.getBlockMaterial(var7, par4 - 1, var9 + 1) == Material.water)) {
+ int var10 = 2 + par2Random.nextInt(par2Random.nextInt(3) + 1);
+
+ for (int var11 = 0; var11 < var10; ++var11) {
+ if (Block.reed.canBlockStay(par1World, var7, var8 + var11, var9)) {
+ par1World.setBlock(var7, var8 + var11, var9, Block.reed.blockID, 0, 2);
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldGenSand.java b/sp-server/src/main/java/net/minecraft/src/WorldGenSand.java
new file mode 100644
index 0000000..daf5119
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldGenSand.java
@@ -0,0 +1,44 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class WorldGenSand extends WorldGenerator {
+ /** Stores ID for WorldGenSand */
+ private int sandID;
+
+ /** The maximum radius used when generating a patch of blocks. */
+ private int radius;
+
+ public WorldGenSand(int par1, int par2) {
+ this.sandID = par2;
+ this.radius = par1;
+ }
+
+ public boolean generate(World par1World, EaglercraftRandom par2Random, int par3, int par4, int par5) {
+ if (par1World.getBlockMaterial(par3, par4, par5) != Material.water) {
+ return false;
+ } else {
+ int var6 = par2Random.nextInt(this.radius - 2) + 2;
+ byte var7 = 2;
+
+ for (int var8 = par3 - var6; var8 <= par3 + var6; ++var8) {
+ for (int var9 = par5 - var6; var9 <= par5 + var6; ++var9) {
+ int var10 = var8 - par3;
+ int var11 = var9 - par5;
+
+ if (var10 * var10 + var11 * var11 <= var6 * var6) {
+ for (int var12 = par4 - var7; var12 <= par4 + var7; ++var12) {
+ int var13 = par1World.getBlockId(var8, var12, var9);
+
+ if (var13 == Block.dirt.blockID || var13 == Block.grass.blockID) {
+ par1World.setBlock(var8, var12, var9, this.sandID, 0, 2);
+ }
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldGenShrub.java b/sp-server/src/main/java/net/minecraft/src/WorldGenShrub.java
new file mode 100644
index 0000000..4418c82
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldGenShrub.java
@@ -0,0 +1,50 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class WorldGenShrub extends WorldGenerator {
+ private int field_76527_a;
+ private int field_76526_b;
+
+ public WorldGenShrub(int par1, int par2) {
+ this.field_76526_b = par1;
+ this.field_76527_a = par2;
+ }
+
+ public boolean generate(World par1World, EaglercraftRandom par2Random, int par3, int par4, int par5) {
+ int var15;
+
+ for (boolean var6 = false; ((var15 = par1World.getBlockId(par3, par4, par5)) == 0
+ || var15 == Block.leaves.blockID) && par4 > 0; --par4) {
+ ;
+ }
+
+ int var7 = par1World.getBlockId(par3, par4, par5);
+
+ if (var7 == Block.dirt.blockID || var7 == Block.grass.blockID) {
+ ++par4;
+ this.setBlockAndMetadata(par1World, par3, par4, par5, Block.wood.blockID, this.field_76526_b);
+
+ for (int var8 = par4; var8 <= par4 + 2; ++var8) {
+ int var9 = var8 - par4;
+ int var10 = 2 - var9;
+
+ for (int var11 = par3 - var10; var11 <= par3 + var10; ++var11) {
+ int var12 = var11 - par3;
+
+ for (int var13 = par5 - var10; var13 <= par5 + var10; ++var13) {
+ int var14 = var13 - par5;
+
+ if ((Math.abs(var12) != var10 || Math.abs(var14) != var10 || par2Random.nextInt(2) != 0)
+ && !Block.opaqueCubeLookup[par1World.getBlockId(var11, var8, var13)]) {
+ this.setBlockAndMetadata(par1World, var11, var8, var13, Block.leaves.blockID,
+ this.field_76527_a);
+ }
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldGenSpikes.java b/sp-server/src/main/java/net/minecraft/src/WorldGenSpikes.java
new file mode 100644
index 0000000..551626f
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldGenSpikes.java
@@ -0,0 +1,60 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class WorldGenSpikes extends WorldGenerator {
+ /**
+ * The Block ID that the generator is allowed to replace while generating the
+ * terrain.
+ */
+ private int replaceID;
+
+ public WorldGenSpikes(int par1) {
+ this.replaceID = par1;
+ }
+
+ public boolean generate(World par1World, EaglercraftRandom par2Random, int par3, int par4, int par5) {
+ if (par1World.isAirBlock(par3, par4, par5) && par1World.getBlockId(par3, par4 - 1, par5) == this.replaceID) {
+ int var6 = par2Random.nextInt(32) + 6;
+ int var7 = par2Random.nextInt(4) + 1;
+ int var8;
+ int var9;
+ int var10;
+ int var11;
+
+ for (var8 = par3 - var7; var8 <= par3 + var7; ++var8) {
+ for (var9 = par5 - var7; var9 <= par5 + var7; ++var9) {
+ var10 = var8 - par3;
+ var11 = var9 - par5;
+
+ if (var10 * var10 + var11 * var11 <= var7 * var7 + 1
+ && par1World.getBlockId(var8, par4 - 1, var9) != this.replaceID) {
+ return false;
+ }
+ }
+ }
+
+ for (var8 = par4; var8 < par4 + var6 && var8 < 128; ++var8) {
+ for (var9 = par3 - var7; var9 <= par3 + var7; ++var9) {
+ for (var10 = par5 - var7; var10 <= par5 + var7; ++var10) {
+ var11 = var9 - par3;
+ int var12 = var10 - par5;
+
+ if (var11 * var11 + var12 * var12 <= var7 * var7 + 1) {
+ par1World.setBlock(var9, var8, var10, Block.obsidian.blockID, 0, 2);
+ }
+ }
+ }
+ }
+
+ EntityEnderCrystal var13 = new EntityEnderCrystal(par1World);
+ var13.setLocationAndAngles((double) ((float) par3 + 0.5F), (double) (par4 + var6),
+ (double) ((float) par5 + 0.5F), par2Random.nextFloat() * 360.0F, 0.0F);
+ par1World.spawnEntityInWorld(var13);
+ par1World.setBlock(par3, par4 + var6, par5, Block.bedrock.blockID, 0, 2);
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldGenSwamp.java b/sp-server/src/main/java/net/minecraft/src/WorldGenSwamp.java
new file mode 100644
index 0000000..e7279c7
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldGenSwamp.java
@@ -0,0 +1,149 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class WorldGenSwamp extends WorldGenerator {
+ public boolean generate(World par1World, EaglercraftRandom par2Random, int par3, int par4, int par5) {
+ int var6;
+
+ for (var6 = par2Random.nextInt(4) + 5; par1World.getBlockMaterial(par3, par4 - 1,
+ par5) == Material.water; --par4) {
+ ;
+ }
+
+ boolean var7 = true;
+
+ if (par4 >= 1 && par4 + var6 + 1 <= 128) {
+ int var8;
+ int var10;
+ int var11;
+ int var12;
+
+ for (var8 = par4; var8 <= par4 + 1 + var6; ++var8) {
+ byte var9 = 1;
+
+ if (var8 == par4) {
+ var9 = 0;
+ }
+
+ if (var8 >= par4 + 1 + var6 - 2) {
+ var9 = 3;
+ }
+
+ for (var10 = par3 - var9; var10 <= par3 + var9 && var7; ++var10) {
+ for (var11 = par5 - var9; var11 <= par5 + var9 && var7; ++var11) {
+ if (var8 >= 0 && var8 < 128) {
+ var12 = par1World.getBlockId(var10, var8, var11);
+
+ if (var12 != 0 && var12 != Block.leaves.blockID) {
+ if (var12 != Block.waterStill.blockID && var12 != Block.waterMoving.blockID) {
+ var7 = false;
+ } else if (var8 > par4) {
+ var7 = false;
+ }
+ }
+ } else {
+ var7 = false;
+ }
+ }
+ }
+ }
+
+ if (!var7) {
+ return false;
+ } else {
+ var8 = par1World.getBlockId(par3, par4 - 1, par5);
+
+ if ((var8 == Block.grass.blockID || var8 == Block.dirt.blockID) && par4 < 128 - var6 - 1) {
+ this.setBlock(par1World, par3, par4 - 1, par5, Block.dirt.blockID);
+ int var13;
+ int var16;
+
+ for (var16 = par4 - 3 + var6; var16 <= par4 + var6; ++var16) {
+ var10 = var16 - (par4 + var6);
+ var11 = 2 - var10 / 2;
+
+ for (var12 = par3 - var11; var12 <= par3 + var11; ++var12) {
+ var13 = var12 - par3;
+
+ for (int var14 = par5 - var11; var14 <= par5 + var11; ++var14) {
+ int var15 = var14 - par5;
+
+ if ((Math.abs(var13) != var11 || Math.abs(var15) != var11
+ || par2Random.nextInt(2) != 0 && var10 != 0)
+ && !Block.opaqueCubeLookup[par1World.getBlockId(var12, var16, var14)]) {
+ this.setBlock(par1World, var12, var16, var14, Block.leaves.blockID);
+ }
+ }
+ }
+ }
+
+ for (var16 = 0; var16 < var6; ++var16) {
+ var10 = par1World.getBlockId(par3, par4 + var16, par5);
+
+ if (var10 == 0 || var10 == Block.leaves.blockID || var10 == Block.waterMoving.blockID
+ || var10 == Block.waterStill.blockID) {
+ this.setBlock(par1World, par3, par4 + var16, par5, Block.wood.blockID);
+ }
+ }
+
+ for (var16 = par4 - 3 + var6; var16 <= par4 + var6; ++var16) {
+ var10 = var16 - (par4 + var6);
+ var11 = 2 - var10 / 2;
+
+ for (var12 = par3 - var11; var12 <= par3 + var11; ++var12) {
+ for (var13 = par5 - var11; var13 <= par5 + var11; ++var13) {
+ if (par1World.getBlockId(var12, var16, var13) == Block.leaves.blockID) {
+ if (par2Random.nextInt(4) == 0
+ && par1World.getBlockId(var12 - 1, var16, var13) == 0) {
+ this.generateVines(par1World, var12 - 1, var16, var13, 8);
+ }
+
+ if (par2Random.nextInt(4) == 0
+ && par1World.getBlockId(var12 + 1, var16, var13) == 0) {
+ this.generateVines(par1World, var12 + 1, var16, var13, 2);
+ }
+
+ if (par2Random.nextInt(4) == 0
+ && par1World.getBlockId(var12, var16, var13 - 1) == 0) {
+ this.generateVines(par1World, var12, var16, var13 - 1, 1);
+ }
+
+ if (par2Random.nextInt(4) == 0
+ && par1World.getBlockId(var12, var16, var13 + 1) == 0) {
+ this.generateVines(par1World, var12, var16, var13 + 1, 4);
+ }
+ }
+ }
+ }
+ }
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Generates vines at the given position until it hits a block.
+ */
+ private void generateVines(World par1World, int par2, int par3, int par4, int par5) {
+ this.setBlockAndMetadata(par1World, par2, par3, par4, Block.vine.blockID, par5);
+ int var6 = 4;
+
+ while (true) {
+ --par3;
+
+ if (par1World.getBlockId(par2, par3, par4) != 0 || var6 <= 0) {
+ return;
+ }
+
+ this.setBlockAndMetadata(par1World, par2, par3, par4, Block.vine.blockID, par5);
+ --var6;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldGenTaiga1.java b/sp-server/src/main/java/net/minecraft/src/WorldGenTaiga1.java
new file mode 100644
index 0000000..890ed50
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldGenTaiga1.java
@@ -0,0 +1,91 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class WorldGenTaiga1 extends WorldGenerator {
+ public boolean generate(World par1World, EaglercraftRandom par2Random, int par3, int par4, int par5) {
+ int var6 = par2Random.nextInt(5) + 7;
+ int var7 = var6 - par2Random.nextInt(2) - 3;
+ int var8 = var6 - var7;
+ int var9 = 1 + par2Random.nextInt(var8 + 1);
+ boolean var10 = true;
+
+ if (par4 >= 1 && par4 + var6 + 1 <= 128) {
+ int var11;
+ int var13;
+ int var14;
+ int var15;
+ int var18;
+
+ for (var11 = par4; var11 <= par4 + 1 + var6 && var10; ++var11) {
+ boolean var12 = true;
+
+ if (var11 - par4 < var7) {
+ var18 = 0;
+ } else {
+ var18 = var9;
+ }
+
+ for (var13 = par3 - var18; var13 <= par3 + var18 && var10; ++var13) {
+ for (var14 = par5 - var18; var14 <= par5 + var18 && var10; ++var14) {
+ if (var11 >= 0 && var11 < 128) {
+ var15 = par1World.getBlockId(var13, var11, var14);
+
+ if (var15 != 0 && var15 != Block.leaves.blockID) {
+ var10 = false;
+ }
+ } else {
+ var10 = false;
+ }
+ }
+ }
+ }
+
+ if (!var10) {
+ return false;
+ } else {
+ var11 = par1World.getBlockId(par3, par4 - 1, par5);
+
+ if ((var11 == Block.grass.blockID || var11 == Block.dirt.blockID) && par4 < 128 - var6 - 1) {
+ this.setBlock(par1World, par3, par4 - 1, par5, Block.dirt.blockID);
+ var18 = 0;
+
+ for (var13 = par4 + var6; var13 >= par4 + var7; --var13) {
+ for (var14 = par3 - var18; var14 <= par3 + var18; ++var14) {
+ var15 = var14 - par3;
+
+ for (int var16 = par5 - var18; var16 <= par5 + var18; ++var16) {
+ int var17 = var16 - par5;
+
+ if ((Math.abs(var15) != var18 || Math.abs(var17) != var18 || var18 <= 0)
+ && !Block.opaqueCubeLookup[par1World.getBlockId(var14, var13, var16)]) {
+ this.setBlockAndMetadata(par1World, var14, var13, var16, Block.leaves.blockID, 1);
+ }
+ }
+ }
+
+ if (var18 >= 1 && var13 == par4 + var7 + 1) {
+ --var18;
+ } else if (var18 < var9) {
+ ++var18;
+ }
+ }
+
+ for (var13 = 0; var13 < var6 - 1; ++var13) {
+ var14 = par1World.getBlockId(par3, par4 + var13, par5);
+
+ if (var14 == 0 || var14 == Block.leaves.blockID) {
+ this.setBlockAndMetadata(par1World, par3, par4 + var13, par5, Block.wood.blockID, 1);
+ }
+ }
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+ } else {
+ return false;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldGenTaiga2.java b/sp-server/src/main/java/net/minecraft/src/WorldGenTaiga2.java
new file mode 100644
index 0000000..7e85625
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldGenTaiga2.java
@@ -0,0 +1,108 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class WorldGenTaiga2 extends WorldGenerator {
+ public WorldGenTaiga2(boolean par1) {
+ super(par1);
+ }
+
+ public boolean generate(World par1World, EaglercraftRandom par2Random, int par3, int par4, int par5) {
+ int var6 = par2Random.nextInt(4) + 6;
+ int var7 = 1 + par2Random.nextInt(2);
+ int var8 = var6 - var7;
+ int var9 = 2 + par2Random.nextInt(2);
+ boolean var10 = true;
+
+ if (par4 >= 1 && par4 + var6 + 1 <= 256) {
+ int var11;
+ int var13;
+ int var15;
+ int var21;
+
+ for (var11 = par4; var11 <= par4 + 1 + var6 && var10; ++var11) {
+ boolean var12 = true;
+
+ if (var11 - par4 < var7) {
+ var21 = 0;
+ } else {
+ var21 = var9;
+ }
+
+ for (var13 = par3 - var21; var13 <= par3 + var21 && var10; ++var13) {
+ for (int var14 = par5 - var21; var14 <= par5 + var21 && var10; ++var14) {
+ if (var11 >= 0 && var11 < 256) {
+ var15 = par1World.getBlockId(var13, var11, var14);
+
+ if (var15 != 0 && var15 != Block.leaves.blockID) {
+ var10 = false;
+ }
+ } else {
+ var10 = false;
+ }
+ }
+ }
+ }
+
+ if (!var10) {
+ return false;
+ } else {
+ var11 = par1World.getBlockId(par3, par4 - 1, par5);
+
+ if ((var11 == Block.grass.blockID || var11 == Block.dirt.blockID) && par4 < 256 - var6 - 1) {
+ this.setBlock(par1World, par3, par4 - 1, par5, Block.dirt.blockID);
+ var21 = par2Random.nextInt(2);
+ var13 = 1;
+ byte var22 = 0;
+ int var16;
+ int var17;
+
+ for (var15 = 0; var15 <= var8; ++var15) {
+ var16 = par4 + var6 - var15;
+
+ for (var17 = par3 - var21; var17 <= par3 + var21; ++var17) {
+ int var18 = var17 - par3;
+
+ for (int var19 = par5 - var21; var19 <= par5 + var21; ++var19) {
+ int var20 = var19 - par5;
+
+ if ((Math.abs(var18) != var21 || Math.abs(var20) != var21 || var21 <= 0)
+ && !Block.opaqueCubeLookup[par1World.getBlockId(var17, var16, var19)]) {
+ this.setBlockAndMetadata(par1World, var17, var16, var19, Block.leaves.blockID, 1);
+ }
+ }
+ }
+
+ if (var21 >= var13) {
+ var21 = var22;
+ var22 = 1;
+ ++var13;
+
+ if (var13 > var9) {
+ var13 = var9;
+ }
+ } else {
+ ++var21;
+ }
+ }
+
+ var15 = par2Random.nextInt(3);
+
+ for (var16 = 0; var16 < var6 - var15; ++var16) {
+ var17 = par1World.getBlockId(par3, par4 + var16, par5);
+
+ if (var17 == 0 || var17 == Block.leaves.blockID) {
+ this.setBlockAndMetadata(par1World, par3, par4 + var16, par5, Block.wood.blockID, 1);
+ }
+ }
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+ } else {
+ return false;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldGenTallGrass.java b/sp-server/src/main/java/net/minecraft/src/WorldGenTallGrass.java
new file mode 100644
index 0000000..be93833
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldGenTallGrass.java
@@ -0,0 +1,36 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class WorldGenTallGrass extends WorldGenerator {
+ /** Stores ID for WorldGenTallGrass */
+ private int tallGrassID;
+ private int tallGrassMetadata;
+
+ public WorldGenTallGrass(int par1, int par2) {
+ this.tallGrassID = par1;
+ this.tallGrassMetadata = par2;
+ }
+
+ public boolean generate(World par1World, EaglercraftRandom par2Random, int par3, int par4, int par5) {
+ int var11;
+
+ for (boolean var6 = false; ((var11 = par1World.getBlockId(par3, par4, par5)) == 0
+ || var11 == Block.leaves.blockID) && par4 > 0; --par4) {
+ ;
+ }
+
+ for (int var7 = 0; var7 < 128; ++var7) {
+ int var8 = par3 + par2Random.nextInt(8) - par2Random.nextInt(8);
+ int var9 = par4 + par2Random.nextInt(4) - par2Random.nextInt(4);
+ int var10 = par5 + par2Random.nextInt(8) - par2Random.nextInt(8);
+
+ if (par1World.isAirBlock(var8, var9, var10)
+ && Block.blocksList[this.tallGrassID].canBlockStay(par1World, var8, var9, var10)) {
+ par1World.setBlock(var8, var9, var10, this.tallGrassID, this.tallGrassMetadata, 2);
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldGenTrees.java b/sp-server/src/main/java/net/minecraft/src/WorldGenTrees.java
new file mode 100644
index 0000000..df8e693
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldGenTrees.java
@@ -0,0 +1,211 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class WorldGenTrees extends WorldGenerator {
+ /** The minimum height of a generated tree. */
+ private final int minTreeHeight;
+
+ /** True if this tree should grow Vines. */
+ private final boolean vinesGrow;
+
+ /** The metadata value of the wood to use in tree generation. */
+ private final int metaWood;
+
+ /** The metadata value of the leaves to use in tree generation. */
+ private final int metaLeaves;
+
+ public WorldGenTrees(boolean par1) {
+ this(par1, 4, 0, 0, false);
+ }
+
+ public WorldGenTrees(boolean par1, int par2, int par3, int par4, boolean par5) {
+ super(par1);
+ this.minTreeHeight = par2;
+ this.metaWood = par3;
+ this.metaLeaves = par4;
+ this.vinesGrow = par5;
+ }
+
+ public boolean generate(World par1World, EaglercraftRandom par2Random, int par3, int par4, int par5) {
+ int var6 = par2Random.nextInt(3) + this.minTreeHeight;
+ boolean var7 = true;
+
+ if (par4 >= 1 && par4 + var6 + 1 <= 256) {
+ int var8;
+ byte var9;
+ int var11;
+ int var12;
+
+ for (var8 = par4; var8 <= par4 + 1 + var6; ++var8) {
+ var9 = 1;
+
+ if (var8 == par4) {
+ var9 = 0;
+ }
+
+ if (var8 >= par4 + 1 + var6 - 2) {
+ var9 = 2;
+ }
+
+ for (int var10 = par3 - var9; var10 <= par3 + var9 && var7; ++var10) {
+ for (var11 = par5 - var9; var11 <= par5 + var9 && var7; ++var11) {
+ if (var8 >= 0 && var8 < 256) {
+ var12 = par1World.getBlockId(var10, var8, var11);
+
+ if (var12 != 0 && var12 != Block.leaves.blockID && var12 != Block.grass.blockID
+ && var12 != Block.dirt.blockID && var12 != Block.wood.blockID) {
+ var7 = false;
+ }
+ } else {
+ var7 = false;
+ }
+ }
+ }
+ }
+
+ if (!var7) {
+ return false;
+ } else {
+ var8 = par1World.getBlockId(par3, par4 - 1, par5);
+
+ if ((var8 == Block.grass.blockID || var8 == Block.dirt.blockID) && par4 < 256 - var6 - 1) {
+ this.setBlock(par1World, par3, par4 - 1, par5, Block.dirt.blockID);
+ var9 = 3;
+ byte var19 = 0;
+ int var13;
+ int var14;
+ int var15;
+
+ for (var11 = par4 - var9 + var6; var11 <= par4 + var6; ++var11) {
+ var12 = var11 - (par4 + var6);
+ var13 = var19 + 1 - var12 / 2;
+
+ for (var14 = par3 - var13; var14 <= par3 + var13; ++var14) {
+ var15 = var14 - par3;
+
+ for (int var16 = par5 - var13; var16 <= par5 + var13; ++var16) {
+ int var17 = var16 - par5;
+
+ if (Math.abs(var15) != var13 || Math.abs(var17) != var13
+ || par2Random.nextInt(2) != 0 && var12 != 0) {
+ int var18 = par1World.getBlockId(var14, var11, var16);
+
+ if (var18 == 0 || var18 == Block.leaves.blockID) {
+ this.setBlockAndMetadata(par1World, var14, var11, var16, Block.leaves.blockID,
+ this.metaLeaves);
+ }
+ }
+ }
+ }
+ }
+
+ for (var11 = 0; var11 < var6; ++var11) {
+ var12 = par1World.getBlockId(par3, par4 + var11, par5);
+
+ if (var12 == 0 || var12 == Block.leaves.blockID) {
+ this.setBlockAndMetadata(par1World, par3, par4 + var11, par5, Block.wood.blockID,
+ this.metaWood);
+
+ if (this.vinesGrow && var11 > 0) {
+ if (par2Random.nextInt(3) > 0 && par1World.isAirBlock(par3 - 1, par4 + var11, par5)) {
+ this.setBlockAndMetadata(par1World, par3 - 1, par4 + var11, par5,
+ Block.vine.blockID, 8);
+ }
+
+ if (par2Random.nextInt(3) > 0 && par1World.isAirBlock(par3 + 1, par4 + var11, par5)) {
+ this.setBlockAndMetadata(par1World, par3 + 1, par4 + var11, par5,
+ Block.vine.blockID, 2);
+ }
+
+ if (par2Random.nextInt(3) > 0 && par1World.isAirBlock(par3, par4 + var11, par5 - 1)) {
+ this.setBlockAndMetadata(par1World, par3, par4 + var11, par5 - 1,
+ Block.vine.blockID, 1);
+ }
+
+ if (par2Random.nextInt(3) > 0 && par1World.isAirBlock(par3, par4 + var11, par5 + 1)) {
+ this.setBlockAndMetadata(par1World, par3, par4 + var11, par5 + 1,
+ Block.vine.blockID, 4);
+ }
+ }
+ }
+ }
+
+ if (this.vinesGrow) {
+ for (var11 = par4 - 3 + var6; var11 <= par4 + var6; ++var11) {
+ var12 = var11 - (par4 + var6);
+ var13 = 2 - var12 / 2;
+
+ for (var14 = par3 - var13; var14 <= par3 + var13; ++var14) {
+ for (var15 = par5 - var13; var15 <= par5 + var13; ++var15) {
+ if (par1World.getBlockId(var14, var11, var15) == Block.leaves.blockID) {
+ if (par2Random.nextInt(4) == 0
+ && par1World.getBlockId(var14 - 1, var11, var15) == 0) {
+ this.growVines(par1World, var14 - 1, var11, var15, 8);
+ }
+
+ if (par2Random.nextInt(4) == 0
+ && par1World.getBlockId(var14 + 1, var11, var15) == 0) {
+ this.growVines(par1World, var14 + 1, var11, var15, 2);
+ }
+
+ if (par2Random.nextInt(4) == 0
+ && par1World.getBlockId(var14, var11, var15 - 1) == 0) {
+ this.growVines(par1World, var14, var11, var15 - 1, 1);
+ }
+
+ if (par2Random.nextInt(4) == 0
+ && par1World.getBlockId(var14, var11, var15 + 1) == 0) {
+ this.growVines(par1World, var14, var11, var15 + 1, 4);
+ }
+ }
+ }
+ }
+ }
+
+ if (par2Random.nextInt(5) == 0 && var6 > 5) {
+ for (var11 = 0; var11 < 2; ++var11) {
+ for (var12 = 0; var12 < 4; ++var12) {
+ if (par2Random.nextInt(4 - var11) == 0) {
+ var13 = par2Random.nextInt(3);
+ this.setBlockAndMetadata(par1World,
+ par3 + Direction.offsetX[Direction.footInvisibleFaceRemap[var12]],
+ par4 + var6 - 5 + var11,
+ par5 + Direction.offsetZ[Direction.footInvisibleFaceRemap[var12]],
+ Block.cocoaPlant.blockID, var13 << 2 | var12);
+ }
+ }
+ }
+ }
+ }
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Grows vines downward from the given block for a given length. Args: World, x,
+ * starty, z, vine-length
+ */
+ private void growVines(World par1World, int par2, int par3, int par4, int par5) {
+ this.setBlockAndMetadata(par1World, par2, par3, par4, Block.vine.blockID, par5);
+ int var6 = 4;
+
+ while (true) {
+ --par3;
+
+ if (par1World.getBlockId(par2, par3, par4) != 0 || var6 <= 0) {
+ return;
+ }
+
+ this.setBlockAndMetadata(par1World, par2, par3, par4, Block.vine.blockID, par5);
+ --var6;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldGenVines.java b/sp-server/src/main/java/net/minecraft/src/WorldGenVines.java
new file mode 100644
index 0000000..10b5149
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldGenVines.java
@@ -0,0 +1,26 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class WorldGenVines extends WorldGenerator {
+ public boolean generate(World par1World, EaglercraftRandom par2Random, int par3, int par4, int par5) {
+ int var6 = par3;
+
+ for (int var7 = par5; par4 < 128; ++par4) {
+ if (par1World.isAirBlock(par3, par4, par5)) {
+ for (int var8 = 2; var8 <= 5; ++var8) {
+ if (Block.vine.canPlaceBlockOnSide(par1World, par3, par4, par5, var8)) {
+ par1World.setBlock(par3, par4, par5, Block.vine.blockID,
+ 1 << Direction.facingToDirection[Facing.oppositeSide[var8]], 2);
+ break;
+ }
+ }
+ } else {
+ par3 = var6 + par2Random.nextInt(4) - par2Random.nextInt(4);
+ par5 = var7 + par2Random.nextInt(4) - par2Random.nextInt(4);
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldGenWaterlily.java b/sp-server/src/main/java/net/minecraft/src/WorldGenWaterlily.java
new file mode 100644
index 0000000..a6e1c49
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldGenWaterlily.java
@@ -0,0 +1,20 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class WorldGenWaterlily extends WorldGenerator {
+ public boolean generate(World par1World, EaglercraftRandom par2Random, int par3, int par4, int par5) {
+ for (int var6 = 0; var6 < 10; ++var6) {
+ int var7 = par3 + par2Random.nextInt(8) - par2Random.nextInt(8);
+ int var8 = par4 + par2Random.nextInt(4) - par2Random.nextInt(4);
+ int var9 = par5 + par2Random.nextInt(8) - par2Random.nextInt(8);
+
+ if (par1World.isAirBlock(var7, var8, var9)
+ && Block.waterlily.canPlaceBlockAt(par1World, var7, var8, var9)) {
+ par1World.setBlock(var7, var8, var9, Block.waterlily.blockID, 0, 2);
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldGenerator.java b/sp-server/src/main/java/net/minecraft/src/WorldGenerator.java
new file mode 100644
index 0000000..eddb80e
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldGenerator.java
@@ -0,0 +1,46 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public abstract class WorldGenerator {
+ /**
+ * Sets wither or not the generator should notify blocks of blocks it changes.
+ * When the world is first generated, this is false, when saplings grow, this is
+ * true.
+ */
+ private final boolean doBlockNotify;
+
+ public WorldGenerator() {
+ this.doBlockNotify = false;
+ }
+
+ public WorldGenerator(boolean par1) {
+ this.doBlockNotify = par1;
+ }
+
+ public abstract boolean generate(World var1, EaglercraftRandom var2, int var3, int var4, int var5);
+
+ /**
+ * Rescales the generator settings, only used in WorldGenBigTree
+ */
+ public void setScale(double par1, double par3, double par5) {
+ }
+
+ /**
+ * Sets the block without metadata in the world, notifying neighbors if enabled.
+ */
+ protected void setBlock(World par1World, int par2, int par3, int par4, int par5) {
+ this.setBlockAndMetadata(par1World, par2, par3, par4, par5, 0);
+ }
+
+ /**
+ * Sets the block in the world, notifying neighbors if enabled.
+ */
+ protected void setBlockAndMetadata(World par1World, int par2, int par3, int par4, int par5, int par6) {
+ if (this.doBlockNotify) {
+ par1World.setBlock(par2, par3, par4, par5, par6, 3);
+ } else {
+ par1World.setBlock(par2, par3, par4, par5, par6, 2);
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldGeneratorBonusChest.java b/sp-server/src/main/java/net/minecraft/src/WorldGeneratorBonusChest.java
new file mode 100644
index 0000000..034c990
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldGeneratorBonusChest.java
@@ -0,0 +1,78 @@
+package net.minecraft.src;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+
+public class WorldGeneratorBonusChest extends WorldGenerator {
+ /**
+ * Instance of WeightedRandomChestContent what will randomly generate items into
+ * the Bonus Chest.
+ */
+ private final WeightedRandomChestContent[] theBonusChestGenerator;
+
+ /**
+ * Value of this int will determine how much items gonna generate in Bonus
+ * Chest.
+ */
+ private final int itemsToGenerateInBonusChest;
+
+ public WorldGeneratorBonusChest(WeightedRandomChestContent[] par1ArrayOfWeightedRandomChestContent, int par2) {
+ this.theBonusChestGenerator = par1ArrayOfWeightedRandomChestContent;
+ this.itemsToGenerateInBonusChest = par2;
+ }
+
+ public boolean generate(World par1World, EaglercraftRandom par2Random, int par3, int par4, int par5) {
+ int var12;
+
+ for (boolean var6 = false; ((var12 = par1World.getBlockId(par3, par4, par5)) == 0
+ || var12 == Block.leaves.blockID) && par4 > 1; --par4) {
+ ;
+ }
+
+ if (par4 < 1) {
+ return false;
+ } else {
+ ++par4;
+
+ for (int var7 = 0; var7 < 4; ++var7) {
+ int var8 = par3 + par2Random.nextInt(4) - par2Random.nextInt(4);
+ int var9 = par4 + par2Random.nextInt(3) - par2Random.nextInt(3);
+ int var10 = par5 + par2Random.nextInt(4) - par2Random.nextInt(4);
+
+ if (par1World.isAirBlock(var8, var9, var10)
+ && par1World.doesBlockHaveSolidTopSurface(var8, var9 - 1, var10)) {
+ par1World.setBlock(var8, var9, var10, Block.chest.blockID, 0, 2);
+ TileEntityChest var11 = (TileEntityChest) par1World.getBlockTileEntity(var8, var9, var10);
+
+ if (var11 != null && var11 != null) {
+ WeightedRandomChestContent.generateChestContents(par2Random, this.theBonusChestGenerator, var11,
+ this.itemsToGenerateInBonusChest);
+ }
+
+ if (par1World.isAirBlock(var8 - 1, var9, var10)
+ && par1World.doesBlockHaveSolidTopSurface(var8 - 1, var9 - 1, var10)) {
+ par1World.setBlock(var8 - 1, var9, var10, Block.torchWood.blockID, 0, 2);
+ }
+
+ if (par1World.isAirBlock(var8 + 1, var9, var10)
+ && par1World.doesBlockHaveSolidTopSurface(var8 - 1, var9 - 1, var10)) {
+ par1World.setBlock(var8 + 1, var9, var10, Block.torchWood.blockID, 0, 2);
+ }
+
+ if (par1World.isAirBlock(var8, var9, var10 - 1)
+ && par1World.doesBlockHaveSolidTopSurface(var8 - 1, var9 - 1, var10)) {
+ par1World.setBlock(var8, var9, var10 - 1, Block.torchWood.blockID, 0, 2);
+ }
+
+ if (par1World.isAirBlock(var8, var9, var10 + 1)
+ && par1World.doesBlockHaveSolidTopSurface(var8 - 1, var9 - 1, var10)) {
+ par1World.setBlock(var8, var9, var10 + 1, Block.torchWood.blockID, 0, 2);
+ }
+
+ return true;
+ }
+ }
+
+ return false;
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldInfo.java b/sp-server/src/main/java/net/minecraft/src/WorldInfo.java
new file mode 100644
index 0000000..978d906
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldInfo.java
@@ -0,0 +1,542 @@
+package net.minecraft.src;
+
+public class WorldInfo {
+ /** Holds the seed of the currently world. */
+ private long randomSeed;
+ private WorldType terrainType;
+ private String generatorOptions;
+
+ /** The spawn zone position X coordinate. */
+ private int spawnX;
+
+ /** The spawn zone position Y coordinate. */
+ private int spawnY;
+
+ /** The spawn zone position Z coordinate. */
+ private int spawnZ;
+
+ /** Total time for this world. */
+ private long totalTime;
+
+ /** The current world time in ticks, ranging from 0 to 23999. */
+ private long worldTime;
+
+ /** The last time the player was in this world. */
+ private long lastTimePlayed;
+
+ /** The size of entire save of current world on the disk, isn't exactly. */
+ private long sizeOnDisk;
+ private NBTTagCompound playerTag;
+ private int dimension;
+
+ /** The name of the save defined at world creation. */
+ private String levelName;
+
+ /** Introduced in beta 1.3, is the save version for future control. */
+ private int saveVersion;
+
+ /** True if it's raining, false otherwise. */
+ private boolean raining;
+
+ /** Number of ticks until next rain. */
+ private int rainTime;
+
+ /** Is thunderbolts failing now? */
+ private boolean thundering;
+
+ /** Number of ticks untils next thunderbolt. */
+ private int thunderTime;
+
+ /** The Game Type. */
+ private EnumGameType theGameType;
+
+ /**
+ * Whether the map features (e.g. strongholds) generation is enabled or
+ * disabled.
+ */
+ private boolean mapFeaturesEnabled;
+
+ /** Hardcore mode flag */
+ private boolean hardcore;
+ private boolean allowCommands;
+ private boolean initialized;
+ private GameRules theGameRules;
+
+ protected WorldInfo() {
+ this.terrainType = WorldType.DEFAULT;
+ this.generatorOptions = "";
+ this.theGameRules = new GameRules();
+ }
+
+ public WorldInfo(NBTTagCompound par1NBTTagCompound) {
+ this.terrainType = WorldType.DEFAULT;
+ this.generatorOptions = "";
+ this.theGameRules = new GameRules();
+ this.randomSeed = par1NBTTagCompound.getLong("RandomSeed");
+
+ if (par1NBTTagCompound.hasKey("generatorName")) {
+ String var2 = par1NBTTagCompound.getString("generatorName");
+ this.terrainType = WorldType.parseWorldType(var2);
+
+ if (this.terrainType == null) {
+ this.terrainType = WorldType.DEFAULT;
+ } else if (this.terrainType.isVersioned()) {
+ int var3 = 0;
+
+ if (par1NBTTagCompound.hasKey("generatorVersion")) {
+ var3 = par1NBTTagCompound.getInteger("generatorVersion");
+ }
+
+ this.terrainType = this.terrainType.getWorldTypeForGeneratorVersion(var3);
+ }
+
+ if (par1NBTTagCompound.hasKey("generatorOptions")) {
+ this.generatorOptions = par1NBTTagCompound.getString("generatorOptions");
+ }
+ }
+
+ this.theGameType = EnumGameType.getByID(par1NBTTagCompound.getInteger("GameType"));
+
+ if (par1NBTTagCompound.hasKey("MapFeatures")) {
+ this.mapFeaturesEnabled = par1NBTTagCompound.getBoolean("MapFeatures");
+ } else {
+ this.mapFeaturesEnabled = true;
+ }
+
+ this.spawnX = par1NBTTagCompound.getInteger("SpawnX");
+ this.spawnY = par1NBTTagCompound.getInteger("SpawnY");
+ this.spawnZ = par1NBTTagCompound.getInteger("SpawnZ");
+ this.totalTime = par1NBTTagCompound.getLong("Time");
+
+ if (par1NBTTagCompound.hasKey("DayTime")) {
+ this.worldTime = par1NBTTagCompound.getLong("DayTime");
+ } else {
+ this.worldTime = this.totalTime;
+ }
+
+ this.lastTimePlayed = par1NBTTagCompound.getLong("LastPlayed");
+ this.sizeOnDisk = par1NBTTagCompound.getLong("SizeOnDisk");
+ this.levelName = par1NBTTagCompound.getString("LevelName");
+ this.saveVersion = par1NBTTagCompound.getInteger("version");
+ this.rainTime = par1NBTTagCompound.getInteger("rainTime");
+ this.raining = par1NBTTagCompound.getBoolean("raining");
+ this.thunderTime = par1NBTTagCompound.getInteger("thunderTime");
+ this.thundering = par1NBTTagCompound.getBoolean("thundering");
+ this.hardcore = par1NBTTagCompound.getBoolean("hardcore");
+
+ if (par1NBTTagCompound.hasKey("initialized")) {
+ this.initialized = par1NBTTagCompound.getBoolean("initialized");
+ } else {
+ this.initialized = true;
+ }
+
+ if (par1NBTTagCompound.hasKey("allowCommands")) {
+ this.allowCommands = par1NBTTagCompound.getBoolean("allowCommands");
+ } else {
+ this.allowCommands = this.theGameType == EnumGameType.CREATIVE;
+ }
+
+ if (par1NBTTagCompound.hasKey("Player")) {
+ this.playerTag = par1NBTTagCompound.getCompoundTag("Player");
+ this.dimension = this.playerTag.getInteger("Dimension");
+ }
+
+ if (par1NBTTagCompound.hasKey("GameRules")) {
+ this.theGameRules.readGameRulesFromNBT(par1NBTTagCompound.getCompoundTag("GameRules"));
+ }
+ }
+
+ public WorldInfo(WorldSettings par1WorldSettings, String par2Str) {
+ this.terrainType = WorldType.DEFAULT;
+ this.generatorOptions = "";
+ this.theGameRules = new GameRules();
+ this.randomSeed = par1WorldSettings.getSeed();
+ this.theGameType = par1WorldSettings.getGameType();
+ this.mapFeaturesEnabled = par1WorldSettings.isMapFeaturesEnabled();
+ this.levelName = par2Str;
+ this.hardcore = par1WorldSettings.getHardcoreEnabled();
+ this.terrainType = par1WorldSettings.getTerrainType();
+ this.generatorOptions = par1WorldSettings.func_82749_j();
+ this.allowCommands = par1WorldSettings.areCommandsAllowed();
+ this.initialized = false;
+ }
+
+ public WorldInfo(WorldInfo par1WorldInfo) {
+ this.terrainType = WorldType.DEFAULT;
+ this.generatorOptions = "";
+ this.theGameRules = new GameRules();
+ this.randomSeed = par1WorldInfo.randomSeed;
+ this.terrainType = par1WorldInfo.terrainType;
+ this.generatorOptions = par1WorldInfo.generatorOptions;
+ this.theGameType = par1WorldInfo.theGameType;
+ this.mapFeaturesEnabled = par1WorldInfo.mapFeaturesEnabled;
+ this.spawnX = par1WorldInfo.spawnX;
+ this.spawnY = par1WorldInfo.spawnY;
+ this.spawnZ = par1WorldInfo.spawnZ;
+ this.totalTime = par1WorldInfo.totalTime;
+ this.worldTime = par1WorldInfo.worldTime;
+ this.lastTimePlayed = par1WorldInfo.lastTimePlayed;
+ this.sizeOnDisk = par1WorldInfo.sizeOnDisk;
+ this.playerTag = par1WorldInfo.playerTag;
+ this.dimension = par1WorldInfo.dimension;
+ this.levelName = par1WorldInfo.levelName;
+ this.saveVersion = par1WorldInfo.saveVersion;
+ this.rainTime = par1WorldInfo.rainTime;
+ this.raining = par1WorldInfo.raining;
+ this.thunderTime = par1WorldInfo.thunderTime;
+ this.thundering = par1WorldInfo.thundering;
+ this.hardcore = par1WorldInfo.hardcore;
+ this.allowCommands = par1WorldInfo.allowCommands;
+ this.initialized = par1WorldInfo.initialized;
+ this.theGameRules = par1WorldInfo.theGameRules;
+ }
+
+ /**
+ * Gets the NBTTagCompound for the worldInfo
+ */
+ public NBTTagCompound getNBTTagCompound() {
+ NBTTagCompound var1 = new NBTTagCompound();
+ this.updateTagCompound(var1, this.playerTag);
+ return var1;
+ }
+
+ /**
+ * Creates a new NBTTagCompound for the world, with the given NBTTag as the
+ * "Player"
+ */
+ public NBTTagCompound cloneNBTCompound(NBTTagCompound par1NBTTagCompound) {
+ NBTTagCompound var2 = new NBTTagCompound();
+ this.updateTagCompound(var2, par1NBTTagCompound);
+ return var2;
+ }
+
+ private void updateTagCompound(NBTTagCompound par1NBTTagCompound, NBTTagCompound par2NBTTagCompound) {
+ par1NBTTagCompound.setLong("RandomSeed", this.randomSeed);
+ par1NBTTagCompound.setString("generatorName", this.terrainType.getWorldTypeName());
+ par1NBTTagCompound.setInteger("generatorVersion", this.terrainType.getGeneratorVersion());
+ par1NBTTagCompound.setString("generatorOptions", this.generatorOptions);
+ par1NBTTagCompound.setInteger("GameType", this.theGameType.getID());
+ par1NBTTagCompound.setBoolean("MapFeatures", this.mapFeaturesEnabled);
+ par1NBTTagCompound.setInteger("SpawnX", this.spawnX);
+ par1NBTTagCompound.setInteger("SpawnY", this.spawnY);
+ par1NBTTagCompound.setInteger("SpawnZ", this.spawnZ);
+ par1NBTTagCompound.setLong("Time", this.totalTime);
+ par1NBTTagCompound.setLong("DayTime", this.worldTime);
+ par1NBTTagCompound.setLong("SizeOnDisk", this.sizeOnDisk);
+ par1NBTTagCompound.setLong("LastPlayed", System.currentTimeMillis());
+ par1NBTTagCompound.setString("LevelName", this.levelName);
+ par1NBTTagCompound.setInteger("version", this.saveVersion);
+ par1NBTTagCompound.setInteger("rainTime", this.rainTime);
+ par1NBTTagCompound.setBoolean("raining", this.raining);
+ par1NBTTagCompound.setInteger("thunderTime", this.thunderTime);
+ par1NBTTagCompound.setBoolean("thundering", this.thundering);
+ par1NBTTagCompound.setBoolean("hardcore", this.hardcore);
+ par1NBTTagCompound.setBoolean("allowCommands", this.allowCommands);
+ par1NBTTagCompound.setBoolean("initialized", this.initialized);
+ par1NBTTagCompound.setCompoundTag("GameRules", this.theGameRules.writeGameRulesToNBT());
+
+ if (par2NBTTagCompound != null) {
+ par1NBTTagCompound.setCompoundTag("Player", par2NBTTagCompound);
+ }
+ }
+
+ /**
+ * Returns the seed of current world.
+ */
+ public long getSeed() {
+ return this.randomSeed;
+ }
+
+ /**
+ * Returns the x spawn position
+ */
+ public int getSpawnX() {
+ return this.spawnX;
+ }
+
+ /**
+ * Return the Y axis spawning point of the player.
+ */
+ public int getSpawnY() {
+ return this.spawnY;
+ }
+
+ /**
+ * Returns the z spawn position
+ */
+ public int getSpawnZ() {
+ return this.spawnZ;
+ }
+
+ public long getWorldTotalTime() {
+ return this.totalTime;
+ }
+
+ /**
+ * Get current world time
+ */
+ public long getWorldTime() {
+ return this.worldTime;
+ }
+
+ /**
+ * Returns the player's NBTTagCompound to be loaded
+ */
+ public NBTTagCompound getPlayerNBTTagCompound() {
+ return this.playerTag;
+ }
+
+ public int getDimension() {
+ return this.dimension;
+ }
+
+ public void incrementTotalWorldTime(long par1) {
+ this.totalTime = par1;
+ }
+
+ /**
+ * Set current world time
+ */
+ public void setWorldTime(long par1) {
+ this.worldTime = par1;
+ }
+
+ /**
+ * Sets the spawn zone position. Args: x, y, z
+ */
+ public void setSpawnPosition(int par1, int par2, int par3) {
+ this.spawnX = par1;
+ this.spawnY = par2;
+ this.spawnZ = par3;
+ }
+
+ /**
+ * Get current world name
+ */
+ public String getWorldName() {
+ return this.levelName;
+ }
+
+ public void setWorldName(String par1Str) {
+ this.levelName = par1Str;
+ }
+
+ /**
+ * Returns the save version of this world
+ */
+ public int getSaveVersion() {
+ return this.saveVersion;
+ }
+
+ /**
+ * Sets the save version of the world
+ */
+ public void setSaveVersion(int par1) {
+ this.saveVersion = par1;
+ }
+
+ /**
+ * Returns true if it is thundering, false otherwise.
+ */
+ public boolean isThundering() {
+ return this.thundering;
+ }
+
+ /**
+ * Sets whether it is thundering or not.
+ */
+ public void setThundering(boolean par1) {
+ this.thundering = par1;
+ }
+
+ /**
+ * Returns the number of ticks until next thunderbolt.
+ */
+ public int getThunderTime() {
+ return this.thunderTime;
+ }
+
+ /**
+ * Defines the number of ticks until next thunderbolt.
+ */
+ public void setThunderTime(int par1) {
+ this.thunderTime = par1;
+ }
+
+ /**
+ * Returns true if it is raining, false otherwise.
+ */
+ public boolean isRaining() {
+ return this.raining;
+ }
+
+ /**
+ * Sets whether it is raining or not.
+ */
+ public void setRaining(boolean par1) {
+ this.raining = par1;
+ }
+
+ /**
+ * Return the number of ticks until rain.
+ */
+ public int getRainTime() {
+ return this.rainTime;
+ }
+
+ /**
+ * Sets the number of ticks until rain.
+ */
+ public void setRainTime(int par1) {
+ this.rainTime = par1;
+ }
+
+ /**
+ * Gets the GameType.
+ */
+ public EnumGameType getGameType() {
+ return this.theGameType;
+ }
+
+ /**
+ * Get whether the map features (e.g. strongholds) generation is enabled or
+ * disabled.
+ */
+ public boolean isMapFeaturesEnabled() {
+ return this.mapFeaturesEnabled;
+ }
+
+ /**
+ * Sets the GameType.
+ */
+ public void setGameType(EnumGameType par1EnumGameType) {
+ this.theGameType = par1EnumGameType;
+ }
+
+ /**
+ * Returns true if hardcore mode is enabled, otherwise false
+ */
+ public boolean isHardcoreModeEnabled() {
+ return this.hardcore;
+ }
+
+ public WorldType getTerrainType() {
+ return this.terrainType;
+ }
+
+ public void setTerrainType(WorldType par1WorldType) {
+ this.terrainType = par1WorldType;
+ }
+
+ public String getGeneratorOptions() {
+ return this.generatorOptions;
+ }
+
+ /**
+ * Returns true if commands are allowed on this World.
+ */
+ public boolean areCommandsAllowed() {
+ return this.allowCommands;
+ }
+
+ /**
+ * Returns true if the World is initialized.
+ */
+ public boolean isInitialized() {
+ return this.initialized;
+ }
+
+ /**
+ * Sets the initialization status of the World.
+ */
+ public void setServerInitialized(boolean par1) {
+ this.initialized = par1;
+ }
+
+ /**
+ * Gets the GameRules class Instance.
+ */
+ public GameRules getGameRulesInstance() {
+ return this.theGameRules;
+ }
+
+ /**
+ * Return the terrain type of a world
+ */
+ static WorldType getTerrainTypeOfWorld(WorldInfo par0WorldInfo) {
+ return par0WorldInfo.terrainType;
+ }
+
+ /**
+ * Return the map feautures enabled of a world
+ */
+ static boolean getMapFeaturesEnabled(WorldInfo par0WorldInfo) {
+ return par0WorldInfo.mapFeaturesEnabled;
+ }
+
+ static String getWorldGeneratorOptions(WorldInfo par0WorldInfo) {
+ return par0WorldInfo.generatorOptions;
+ }
+
+ static int getSpawnXCoordinate(WorldInfo par0WorldInfo) {
+ return par0WorldInfo.spawnX;
+ }
+
+ static int getSpawnYCoordinate(WorldInfo par0WorldInfo) {
+ return par0WorldInfo.spawnY;
+ }
+
+ static int getSpawnZCoordinate(WorldInfo par0WorldInfo) {
+ return par0WorldInfo.spawnZ;
+ }
+
+ static long func_85126_g(WorldInfo par0WorldInfo) {
+ return par0WorldInfo.totalTime;
+ }
+
+ static long getWorldTime(WorldInfo par0WorldInfo) {
+ return par0WorldInfo.worldTime;
+ }
+
+ static int func_85122_i(WorldInfo par0WorldInfo) {
+ return par0WorldInfo.dimension;
+ }
+
+ static int getSaveVersion(WorldInfo par0WorldInfo) {
+ return par0WorldInfo.saveVersion;
+ }
+
+ static int getRainTime(WorldInfo par0WorldInfo) {
+ return par0WorldInfo.rainTime;
+ }
+
+ /**
+ * Returns wether it's raining or not.
+ */
+ static boolean getRaining(WorldInfo par0WorldInfo) {
+ return par0WorldInfo.raining;
+ }
+
+ static int getThunderTime(WorldInfo par0WorldInfo) {
+ return par0WorldInfo.thunderTime;
+ }
+
+ /**
+ * Returns wether it's thundering or not.
+ */
+ static boolean getThundering(WorldInfo par0WorldInfo) {
+ return par0WorldInfo.thundering;
+ }
+
+ static EnumGameType getGameType(WorldInfo par0WorldInfo) {
+ return par0WorldInfo.theGameType;
+ }
+
+ static boolean func_85117_p(WorldInfo par0WorldInfo) {
+ return par0WorldInfo.hardcore;
+ }
+
+ static boolean func_85131_q(WorldInfo par0WorldInfo) {
+ return par0WorldInfo.allowCommands;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldManager.java b/sp-server/src/main/java/net/minecraft/src/WorldManager.java
new file mode 100644
index 0000000..9c6014a
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldManager.java
@@ -0,0 +1,128 @@
+package net.minecraft.src;
+
+import java.util.Iterator;
+
+import net.minecraft.server.MinecraftServer;
+
+public class WorldManager implements IWorldAccess {
+ /** Reference to the MinecraftServer object. */
+ private MinecraftServer mcServer;
+
+ /** The WorldServer object. */
+ private WorldServer theWorldServer;
+
+ public WorldManager(MinecraftServer par1MinecraftServer, WorldServer par2WorldServer) {
+ this.mcServer = par1MinecraftServer;
+ this.theWorldServer = par2WorldServer;
+ }
+
+ /**
+ * Spawns a particle. Arg: particleType, x, y, z, velX, velY, velZ
+ */
+ public void spawnParticle(String par1Str, double par2, double par4, double par6, double par8, double par10,
+ double par12) {
+ }
+
+ /**
+ * Called on all IWorldAccesses when an entity is created or loaded. On client
+ * worlds, starts downloading any necessary textures. On server worlds, adds the
+ * entity to the entity tracker.
+ */
+ public void onEntityCreate(Entity par1Entity) {
+ this.theWorldServer.getEntityTracker().trackEntity(par1Entity);
+ }
+
+ /**
+ * Called on all IWorldAccesses when an entity is unloaded or destroyed. On
+ * client worlds, releases any downloaded textures. On server worlds, removes
+ * the entity from the entity tracker.
+ */
+ public void onEntityDestroy(Entity par1Entity) {
+ this.theWorldServer.getEntityTracker().untrackEntity(par1Entity);
+ }
+
+ /**
+ * Plays the specified sound. Arg: soundName, x, y, z, volume, pitch
+ */
+ public void playSound(String par1Str, double par2, double par4, double par6, float par8, float par9) {
+ this.mcServer.getConfigurationManager().sendPacketToPlayersAroundPoint(par2, par4, par6,
+ par8 > 1.0F ? (double) (16.0F * par8) : 16.0D, this.theWorldServer.provider.dimensionId,
+ new Packet62LevelSound(par1Str, par2, par4, par6, par8, par9));
+ }
+
+ /**
+ * Plays sound to all near players except the player reference given
+ */
+ public void playSoundToNearExcept(EntityPlayer par1EntityPlayer, String par2Str, double par3, double par5,
+ double par7, float par9, float par10) {
+ this.mcServer.getConfigurationManager().sendToAllNearExcept(par1EntityPlayer, par3, par5, par7,
+ par9 > 1.0F ? (double) (16.0F * par9) : 16.0D, this.theWorldServer.provider.dimensionId,
+ new Packet62LevelSound(par2Str, par3, par5, par7, par9, par10));
+ }
+
+ /**
+ * On the client, re-renders all blocks in this range, inclusive. On the server,
+ * does nothing. Args: min x, min y, min z, max x, max y, max z
+ */
+ public void markBlockRangeForRenderUpdate(int par1, int par2, int par3, int par4, int par5, int par6) {
+ }
+
+ /**
+ * On the client, re-renders the block. On the server, sends the block to the
+ * client (which will re-render it), including the tile entity description
+ * packet if applicable. Args: x, y, z
+ */
+ public void markBlockForUpdate(int par1, int par2, int par3) {
+ this.theWorldServer.getPlayerManager().markBlockNeedsUpdate(par1, par2, par3);
+ }
+
+ /**
+ * On the client, re-renders this block. On the server, does nothing. Used for
+ * lighting updates.
+ */
+ public void markBlockForRenderUpdate(int par1, int par2, int par3) {
+ }
+
+ /**
+ * Plays the specified record. Arg: recordName, x, y, z
+ */
+ public void playRecord(String par1Str, int par2, int par3, int par4) {
+ }
+
+ /**
+ * Plays a pre-canned sound effect along with potentially auxiliary data-driven
+ * one-shot behaviour (particles, etc).
+ */
+ public void playAuxSFX(EntityPlayer par1EntityPlayer, int par2, int par3, int par4, int par5, int par6) {
+ this.mcServer.getConfigurationManager().sendToAllNearExcept(par1EntityPlayer, (double) par3, (double) par4,
+ (double) par5, 64.0D, this.theWorldServer.provider.dimensionId,
+ new Packet61DoorChange(par2, par3, par4, par5, par6, false));
+ }
+
+ public void broadcastSound(int par1, int par2, int par3, int par4, int par5) {
+ this.mcServer.getConfigurationManager()
+ .sendPacketToAllPlayers(new Packet61DoorChange(par1, par2, par3, par4, par5, true));
+ }
+
+ /**
+ * Starts (or continues) destroying a block with given ID at the given
+ * coordinates for the given partially destroyed value
+ */
+ public void destroyBlockPartially(int par1, int par2, int par3, int par4, int par5) {
+ Iterator var6 = this.mcServer.getConfigurationManager().playerEntityList.iterator();
+
+ while (var6.hasNext()) {
+ EntityPlayerMP var7 = (EntityPlayerMP) var6.next();
+
+ if (var7 != null && var7.worldObj == this.theWorldServer && var7.entityId != par1) {
+ double var8 = (double) par2 - var7.posX;
+ double var10 = (double) par3 - var7.posY;
+ double var12 = (double) par4 - var7.posZ;
+
+ if (var8 * var8 + var10 * var10 + var12 * var12 < 1024.0D) {
+ var7.playerNetServerHandler.sendPacket(new Packet55BlockDestroy(par1, par2, par3, par4, par5));
+ }
+ }
+ }
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldProvider.java b/sp-server/src/main/java/net/minecraft/src/WorldProvider.java
new file mode 100644
index 0000000..36ffe29
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldProvider.java
@@ -0,0 +1,152 @@
+package net.minecraft.src;
+
+public abstract class WorldProvider {
+ /** world object being used */
+ public World worldObj;
+ public WorldType terrainType;
+ public String field_82913_c;
+
+ /** World chunk manager being used to generate chunks */
+ public WorldChunkManager worldChunkMgr;
+
+ /**
+ * States whether the Hell world provider is used(true) or if the normal world
+ * provider is used(false)
+ */
+ public boolean isHellWorld = false;
+
+ /**
+ * A boolean that tells if a world does not have a sky. Used in calculating
+ * weather and skylight
+ */
+ public boolean hasNoSky = false;
+
+ /** Light to brightness conversion table */
+ public float[] lightBrightnessTable = new float[16];
+
+ /** The id for the dimension (ex. -1: Nether, 0: Overworld, 1: The End) */
+ public int dimensionId = 0;
+
+ /** Array for sunrise/sunset colors (RGBA) */
+ private float[] colorsSunriseSunset = new float[4];
+
+ /**
+ * associate an existing world with a World provider, and setup its
+ * lightbrightness table
+ */
+ public final void registerWorld(World par1World) {
+ this.worldObj = par1World;
+ this.terrainType = par1World.getWorldInfo().getTerrainType();
+ this.field_82913_c = par1World.getWorldInfo().getGeneratorOptions();
+ this.registerWorldChunkManager();
+ this.generateLightBrightnessTable();
+ }
+
+ /**
+ * Creates the light to brightness table
+ */
+ protected void generateLightBrightnessTable() {
+ float var1 = 0.0F;
+
+ for (int var2 = 0; var2 <= 15; ++var2) {
+ float var3 = 1.0F - (float) var2 / 15.0F;
+ this.lightBrightnessTable[var2] = (1.0F - var3) / (var3 * 3.0F + 1.0F) * (1.0F - var1) + var1;
+ }
+ }
+
+ /**
+ * creates a new world chunk manager for WorldProvider
+ */
+ protected void registerWorldChunkManager() {
+ if (this.worldObj.getWorldInfo().getTerrainType() == WorldType.FLAT) {
+ FlatGeneratorInfo var1 = FlatGeneratorInfo
+ .createFlatGeneratorFromString(this.worldObj.getWorldInfo().getGeneratorOptions());
+ this.worldChunkMgr = new WorldChunkManagerHell(BiomeGenBase.biomeList[var1.getBiome()], 0.5F, 0.5F);
+ } else {
+ this.worldChunkMgr = new WorldChunkManager(this.worldObj);
+ }
+ }
+
+ /**
+ * Returns a new chunk provider which generates chunks for this world
+ */
+ public IChunkProvider createChunkGenerator() {
+ return (IChunkProvider) (this.terrainType == WorldType.FLAT
+ ? new ChunkProviderFlat(this.worldObj, this.worldObj.getSeed(),
+ this.worldObj.getWorldInfo().isMapFeaturesEnabled(), this.field_82913_c)
+ : new ChunkProviderGenerate(this.worldObj, this.worldObj.getSeed(),
+ this.worldObj.getWorldInfo().isMapFeaturesEnabled()));
+ }
+
+ /**
+ * Will check if the x, z position specified is alright to be set as the map
+ * spawn point
+ */
+ public boolean canCoordinateBeSpawn(int par1, int par2) {
+ int var3 = this.worldObj.getFirstUncoveredBlock(par1, par2);
+ return var3 == Block.grass.blockID;
+ }
+
+ /**
+ * Calculates the angle of sun and moon in the sky relative to a specified time
+ * (usually worldTime)
+ */
+ public float calculateCelestialAngle(long par1, float par3) {
+ int var4 = (int) (par1 % 24000L);
+ float var5 = ((float) var4 + par3) / 24000.0F - 0.25F;
+
+ if (var5 < 0.0F) {
+ ++var5;
+ }
+
+ if (var5 > 1.0F) {
+ --var5;
+ }
+
+ float var6 = var5;
+ var5 = 1.0F - (float) ((Math.cos((double) var5 * Math.PI) + 1.0D) / 2.0D);
+ var5 = var6 + (var5 - var6) / 3.0F;
+ return var5;
+ }
+
+ public int func_76559_b(long par1) {
+ return (int) (par1 / 24000L) % 8;
+ }
+
+ /**
+ * Returns 'true' if in the "main surface world", but 'false' if in the Nether
+ * or End dimensions.
+ */
+ public boolean isSurfaceWorld() {
+ return true;
+ }
+
+ /**
+ * True if the player can respawn in this dimension (true = overworld, false =
+ * nether).
+ */
+ public boolean canRespawnHere() {
+ return true;
+ }
+
+ public static WorldProvider getProviderForDimension(int par0) {
+ return (WorldProvider) (par0 == -1 ? new WorldProviderHell()
+ : (par0 == 0 ? new WorldProviderSurface() : (par0 == 1 ? new WorldProviderEnd() : null)));
+ }
+
+ /**
+ * Gets the hard-coded portal location to use when entering this dimension.
+ */
+ public ChunkCoordinates getEntrancePortalLocation() {
+ return null;
+ }
+
+ public int getAverageGroundLevel() {
+ return this.terrainType == WorldType.FLAT ? 4 : 64;
+ }
+
+ /**
+ * Returns the dimension's name, e.g. "The End", "Nether", or "Overworld".
+ */
+ public abstract String getDimensionName();
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldProviderEnd.java b/sp-server/src/main/java/net/minecraft/src/WorldProviderEnd.java
new file mode 100644
index 0000000..5d79a3b
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldProviderEnd.java
@@ -0,0 +1,70 @@
+package net.minecraft.src;
+
+public class WorldProviderEnd extends WorldProvider {
+ /**
+ * creates a new world chunk manager for WorldProvider
+ */
+ public void registerWorldChunkManager() {
+ this.worldChunkMgr = new WorldChunkManagerHell(BiomeGenBase.sky, 0.5F, 0.0F);
+ this.dimensionId = 1;
+ this.hasNoSky = true;
+ }
+
+ /**
+ * Returns a new chunk provider which generates chunks for this world
+ */
+ public IChunkProvider createChunkGenerator() {
+ return new ChunkProviderEnd(this.worldObj, this.worldObj.getSeed());
+ }
+
+ /**
+ * Calculates the angle of sun and moon in the sky relative to a specified time
+ * (usually worldTime)
+ */
+ public float calculateCelestialAngle(long par1, float par3) {
+ return 0.0F;
+ }
+
+ /**
+ * True if the player can respawn in this dimension (true = overworld, false =
+ * nether).
+ */
+ public boolean canRespawnHere() {
+ return false;
+ }
+
+ /**
+ * Returns 'true' if in the "main surface world", but 'false' if in the Nether
+ * or End dimensions.
+ */
+ public boolean isSurfaceWorld() {
+ return false;
+ }
+
+ /**
+ * Will check if the x, z position specified is alright to be set as the map
+ * spawn point
+ */
+ public boolean canCoordinateBeSpawn(int par1, int par2) {
+ int var3 = this.worldObj.getFirstUncoveredBlock(par1, par2);
+ return var3 == 0 ? false : Block.blocksList[var3].blockMaterial.blocksMovement();
+ }
+
+ /**
+ * Gets the hard-coded portal location to use when entering this dimension.
+ */
+ public ChunkCoordinates getEntrancePortalLocation() {
+ return new ChunkCoordinates(100, 50, 0);
+ }
+
+ public int getAverageGroundLevel() {
+ return 50;
+ }
+
+ /**
+ * Returns the dimension's name, e.g. "The End", "Nether", or "Overworld".
+ */
+ public String getDimensionName() {
+ return "The End";
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldProviderHell.java b/sp-server/src/main/java/net/minecraft/src/WorldProviderHell.java
new file mode 100644
index 0000000..f6a9d5c
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldProviderHell.java
@@ -0,0 +1,71 @@
+package net.minecraft.src;
+
+public class WorldProviderHell extends WorldProvider {
+ /**
+ * creates a new world chunk manager for WorldProvider
+ */
+ public void registerWorldChunkManager() {
+ this.worldChunkMgr = new WorldChunkManagerHell(BiomeGenBase.hell, 1.0F, 0.0F);
+ this.isHellWorld = true;
+ this.hasNoSky = true;
+ this.dimensionId = -1;
+ }
+
+ /**
+ * Creates the light to brightness table
+ */
+ protected void generateLightBrightnessTable() {
+ float var1 = 0.1F;
+
+ for (int var2 = 0; var2 <= 15; ++var2) {
+ float var3 = 1.0F - (float) var2 / 15.0F;
+ this.lightBrightnessTable[var2] = (1.0F - var3) / (var3 * 3.0F + 1.0F) * (1.0F - var1) + var1;
+ }
+ }
+
+ /**
+ * Returns a new chunk provider which generates chunks for this world
+ */
+ public IChunkProvider createChunkGenerator() {
+ return new ChunkProviderHell(this.worldObj, this.worldObj.getSeed());
+ }
+
+ /**
+ * Returns 'true' if in the "main surface world", but 'false' if in the Nether
+ * or End dimensions.
+ */
+ public boolean isSurfaceWorld() {
+ return false;
+ }
+
+ /**
+ * Will check if the x, z position specified is alright to be set as the map
+ * spawn point
+ */
+ public boolean canCoordinateBeSpawn(int par1, int par2) {
+ return false;
+ }
+
+ /**
+ * Calculates the angle of sun and moon in the sky relative to a specified time
+ * (usually worldTime)
+ */
+ public float calculateCelestialAngle(long par1, float par3) {
+ return 0.5F;
+ }
+
+ /**
+ * True if the player can respawn in this dimension (true = overworld, false =
+ * nether).
+ */
+ public boolean canRespawnHere() {
+ return false;
+ }
+
+ /**
+ * Returns the dimension's name, e.g. "The End", "Nether", or "Overworld".
+ */
+ public String getDimensionName() {
+ return "Nether";
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldProviderSurface.java b/sp-server/src/main/java/net/minecraft/src/WorldProviderSurface.java
new file mode 100644
index 0000000..cac7078
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldProviderSurface.java
@@ -0,0 +1,10 @@
+package net.minecraft.src;
+
+public class WorldProviderSurface extends WorldProvider {
+ /**
+ * Returns the dimension's name, e.g. "The End", "Nether", or "Overworld".
+ */
+ public String getDimensionName() {
+ return "Overworld";
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldSavedData.java b/sp-server/src/main/java/net/minecraft/src/WorldSavedData.java
new file mode 100644
index 0000000..fbe0a5d
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldSavedData.java
@@ -0,0 +1,45 @@
+package net.minecraft.src;
+
+public abstract class WorldSavedData {
+ /** The name of the map data nbt */
+ public final String mapName;
+
+ /** Whether this MapDataBase needs saving to disk. */
+ private boolean dirty;
+
+ public WorldSavedData(String par1Str) {
+ this.mapName = par1Str;
+ }
+
+ /**
+ * reads in data from the NBTTagCompound into this MapDataBase
+ */
+ public abstract void readFromNBT(NBTTagCompound var1);
+
+ /**
+ * write data to NBTTagCompound from this MapDataBase, similar to Entities and
+ * TileEntities
+ */
+ public abstract void writeToNBT(NBTTagCompound var1);
+
+ /**
+ * Marks this MapDataBase dirty, to be saved to disk when the level next saves.
+ */
+ public void markDirty() {
+ this.setDirty(true);
+ }
+
+ /**
+ * Sets the dirty state of this MapDataBase, whether it needs saving to disk.
+ */
+ public void setDirty(boolean par1) {
+ this.dirty = par1;
+ }
+
+ /**
+ * Whether this MapDataBase needs saving to disk.
+ */
+ public boolean isDirty() {
+ return this.dirty;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldServer.java b/sp-server/src/main/java/net/minecraft/src/WorldServer.java
new file mode 100644
index 0000000..c863910
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldServer.java
@@ -0,0 +1,909 @@
+package net.minecraft.src;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
+import net.lax1dude.eaglercraft.sp.SysUtil;
+import net.minecraft.server.MinecraftServer;
+
+public class WorldServer extends World {
+ private final MinecraftServer mcServer;
+ private final EntityTracker theEntityTracker;
+ private final PlayerManager thePlayerManager;
+ private Set field_73064_N;
+
+ /** All work to do in future ticks. */
+ private TreeSet pendingTickListEntries;
+ public ChunkProviderServer theChunkProviderServer;
+
+ /** Whether or not level saving is enabled */
+ public boolean levelSaving;
+
+ /** is false if there are no players */
+ private boolean allPlayersSleeping;
+ private int updateEntityTick = 0;
+ private final Teleporter field_85177_Q;
+
+ private int r = 0;
+ private int w = 0;
+ private int g = 0;
+ private int tu = 0;
+ private int lu = 0;
+
+ private int _r = 0;
+ private int _w = 0;
+ private int _g = 0;
+ private int _tu = 0;
+ private int _lu = 0;
+
+ private long rwgtuluTimer = 0l;
+
+ /**
+ * Double buffer of ServerBlockEventList[] for holding pending BlockEventData's
+ */
+ private ServerBlockEventList[] blockEventCache = new ServerBlockEventList[] {
+ new ServerBlockEventList((ServerBlockEvent) null), new ServerBlockEventList((ServerBlockEvent) null) };
+
+ /**
+ * The index into the blockEventCache; either 0, or 1, toggled in
+ * sendBlockEventPackets where all BlockEvent are applied locally and send to
+ * clients.
+ */
+ private int blockEventCacheIndex = 0;
+ private static final WeightedRandomChestContent[] bonusChestContent = new WeightedRandomChestContent[] {
+ new WeightedRandomChestContent(Item.stick.itemID, 0, 1, 3, 10),
+ new WeightedRandomChestContent(Block.planks.blockID, 0, 1, 3, 10),
+ new WeightedRandomChestContent(Block.wood.blockID, 0, 1, 3, 10),
+ new WeightedRandomChestContent(Item.axeStone.itemID, 0, 1, 1, 3),
+ new WeightedRandomChestContent(Item.axeWood.itemID, 0, 1, 1, 5),
+ new WeightedRandomChestContent(Item.pickaxeStone.itemID, 0, 1, 1, 3),
+ new WeightedRandomChestContent(Item.pickaxeWood.itemID, 0, 1, 1, 5),
+ new WeightedRandomChestContent(Item.appleRed.itemID, 0, 2, 3, 5),
+ new WeightedRandomChestContent(Item.bread.itemID, 0, 2, 3, 3) };
+ private ArrayList field_94579_S = new ArrayList();
+
+ /** An IntHashMap of entity IDs (integers) to their Entity objects. */
+ private IntHashMap entityIdMap;
+
+ public WorldServer(MinecraftServer par1MinecraftServer, ISaveHandler par2ISaveHandler, String par3Str, int par4,
+ WorldSettings par5WorldSettings, ILogAgent par7ILogAgent) {
+ super(par2ISaveHandler, par3Str, par5WorldSettings, WorldProvider.getProviderForDimension(par4), par7ILogAgent);
+ this.mcServer = par1MinecraftServer;
+ this.theEntityTracker = new EntityTracker(this);
+ this.thePlayerManager = new PlayerManager(this,
+ par1MinecraftServer.getConfigurationManager().getViewDistance());
+
+ if (this.entityIdMap == null) {
+ this.entityIdMap = new IntHashMap();
+ }
+
+ if (this.field_73064_N == null) {
+ this.field_73064_N = new HashSet();
+ }
+
+ if (this.pendingTickListEntries == null) {
+ this.pendingTickListEntries = new TreeSet();
+ }
+
+ this.field_85177_Q = new Teleporter(this);
+ this.worldScoreboard = new ServerScoreboard(par1MinecraftServer);
+ ScoreboardSaveData var8 = (ScoreboardSaveData) this.mapStorage.loadData((s) -> new ScoreboardSaveData(s), "scoreboard");
+
+ if (var8 == null) {
+ var8 = new ScoreboardSaveData();
+ this.mapStorage.setData("scoreboard", var8);
+ }
+
+ var8.func_96499_a(this.worldScoreboard);
+ ((ServerScoreboard) this.worldScoreboard).func_96547_a(var8);
+ }
+
+ /**
+ * Runs a single tick for the world
+ */
+ public void tick() {
+ super.tick();
+
+ if (this.getWorldInfo().isHardcoreModeEnabled() && this.difficultySetting < 3) {
+ this.difficultySetting = 3;
+ }
+
+ this.provider.worldChunkMgr.cleanupCache();
+
+ if (this.areAllPlayersAsleep()) {
+ boolean var1 = false;
+
+ if (this.spawnHostileMobs && this.difficultySetting >= 1) {
+ ;
+ }
+
+ if (!var1) {
+ long var2 = this.worldInfo.getWorldTime() + 24000L;
+ this.worldInfo.setWorldTime(var2 - var2 % 24000L);
+ this.wakeAllPlayers();
+ }
+ }
+
+ if (this.getGameRules().getGameRuleBooleanValue("doMobSpawning")) {
+ SpawnerAnimals.findChunksForSpawning(this, this.spawnHostileMobs, this.spawnPeacefulMobs,
+ this.worldInfo.getWorldTotalTime() % 400L == 0L);
+ }
+
+ this.chunkProvider.unloadQueuedChunks();
+ int var4 = this.calculateSkylightSubtracted(1.0F);
+
+ if (var4 != this.skylightSubtracted) {
+ this.skylightSubtracted = var4;
+ }
+
+ this.worldInfo.incrementTotalWorldTime(this.worldInfo.getWorldTotalTime() + 1L);
+ this.worldInfo.setWorldTime(this.worldInfo.getWorldTime() + 1L);
+ this.tickUpdates(false);
+ this.tickBlocksAndAmbiance();
+ this.thePlayerManager.updatePlayerInstances();
+ this.villageCollectionObj.tick();
+ this.villageSiegeObj.tick();
+ this.field_85177_Q.removeStalePortalLocations(this.getTotalWorldTime());
+ this.sendAndApplyBlockEvents();
+
+ _r += this.theChunkProviderServer.statR();
+ _w += this.theChunkProviderServer.statW();
+ _g += this.theChunkProviderServer.statG();
+ _lu += Chunk.totalBlockLightUpdates;
+ Chunk.totalBlockLightUpdates = 0;
+
+ long millis = SysUtil.steadyTimeMillis();
+ if(millis - rwgtuluTimer >= 1000l) {
+ rwgtuluTimer = millis;
+ r = _r; _r = 0;
+ w = _w; _w = 0;
+ g = _g; _g = 0;
+ tu = _tu; _tu = 0;
+ lu = _lu; _lu = 0;
+ }
+
+ }
+
+ public int getR() {
+ return r;
+ }
+
+ public int getW() {
+ return w;
+ }
+
+ public int getG() {
+ return g;
+ }
+
+ public int getTU() {
+ return tu;
+ }
+
+ public int getLU() {
+ return lu;
+ }
+
+ /**
+ * only spawns creatures allowed by the chunkProvider
+ */
+ public SpawnListEntry spawnRandomCreature(EnumCreatureType par1EnumCreatureType, int par2, int par3, int par4) {
+ List var5 = this.getChunkProvider().getPossibleCreatures(par1EnumCreatureType, par2, par3, par4);
+ return var5 != null && !var5.isEmpty() ? (SpawnListEntry) WeightedRandom.getRandomItem(this.rand, var5) : null;
+ }
+
+ /**
+ * Updates the flag that indicates whether or not all players in the world are
+ * sleeping.
+ */
+ public void updateAllPlayersSleepingFlag() {
+ this.allPlayersSleeping = !this.playerEntities.isEmpty();
+ Iterator var1 = this.playerEntities.iterator();
+
+ while (var1.hasNext()) {
+ EntityPlayer var2 = (EntityPlayer) var1.next();
+
+ if (!var2.isPlayerSleeping()) {
+ this.allPlayersSleeping = false;
+ break;
+ }
+ }
+ }
+
+ protected void wakeAllPlayers() {
+ this.allPlayersSleeping = false;
+ Iterator var1 = this.playerEntities.iterator();
+
+ while (var1.hasNext()) {
+ EntityPlayer var2 = (EntityPlayer) var1.next();
+
+ if (var2.isPlayerSleeping()) {
+ var2.wakeUpPlayer(false, false, true);
+ }
+ }
+
+ this.resetRainAndThunder();
+ }
+
+ private void resetRainAndThunder() {
+ this.worldInfo.setRainTime(0);
+ this.worldInfo.setRaining(false);
+ this.worldInfo.setThunderTime(0);
+ this.worldInfo.setThundering(false);
+ }
+
+ public boolean areAllPlayersAsleep() {
+ if (this.allPlayersSleeping && !this.isRemote) {
+ Iterator var1 = this.playerEntities.iterator();
+ EntityPlayer var2;
+
+ do {
+ if (!var1.hasNext()) {
+ return true;
+ }
+
+ var2 = (EntityPlayer) var1.next();
+ } while (var2.isPlayerFullyAsleep());
+
+ return false;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * plays random cave ambient sounds and runs updateTick on random blocks within
+ * each chunk in the vacinity of a player
+ */
+ protected void tickBlocksAndAmbiance() {
+ super.tickBlocksAndAmbiance();
+ int var1 = 0;
+ int var2 = 0;
+ Iterator var3 = this.activeChunkSet.iterator();
+
+ while (var3.hasNext()) {
+ ChunkCoordIntPair var4 = (ChunkCoordIntPair) var3.next();
+ int var5 = var4.chunkXPos * 16;
+ int var6 = var4.chunkZPos * 16;
+ Chunk var7 = this.getChunkFromChunkCoords(var4.chunkXPos, var4.chunkZPos);
+ this.moodSoundAndLightCheck(var5, var6, var7);
+ if(var7.updateSkylight()) {
+ ++_lu;
+ }
+ int var8;
+ int var9;
+ int var10;
+ int var11;
+
+ if (this.rand.nextInt(100000) == 0 && this.isRaining() && this.isThundering()) {
+ this.updateLCG = this.updateLCG * 3 + 1013904223;
+ var8 = this.updateLCG >> 2;
+ var9 = var5 + (var8 & 15);
+ var10 = var6 + (var8 >> 8 & 15);
+ var11 = this.getPrecipitationHeight(var9, var10);
+
+ if (this.canLightningStrikeAt(var9, var11, var10)) {
+ this.addWeatherEffect(new EntityLightningBolt(this, (double) var9, (double) var11, (double) var10));
+ }
+ }
+
+ int var13;
+
+ if (this.rand.nextInt(16) == 0) {
+ this.updateLCG = this.updateLCG * 3 + 1013904223;
+ var8 = this.updateLCG >> 2;
+ var9 = var8 & 15;
+ var10 = var8 >> 8 & 15;
+ var11 = this.getPrecipitationHeight(var9 + var5, var10 + var6);
+
+ if (this.isBlockFreezableNaturally(var9 + var5, var11 - 1, var10 + var6)) {
+ this.setBlock(var9 + var5, var11 - 1, var10 + var6, Block.ice.blockID);
+ }
+
+ if (this.isRaining() && this.canSnowAt(var9 + var5, var11, var10 + var6)) {
+ this.setBlock(var9 + var5, var11, var10 + var6, Block.snow.blockID);
+ }
+
+ if (this.isRaining()) {
+ BiomeGenBase var12 = this.getBiomeGenForCoords(var9 + var5, var10 + var6);
+
+ if (var12.canSpawnLightningBolt()) {
+ var13 = this.getBlockId(var9 + var5, var11 - 1, var10 + var6);
+
+ if (var13 != 0) {
+ Block.blocksList[var13].fillWithRain(this, var9 + var5, var11 - 1, var10 + var6);
+ }
+ }
+ }
+ }
+
+ ExtendedBlockStorage[] var19 = var7.getBlockStorageArray();
+ var9 = var19.length;
+
+ for (var10 = 0; var10 < var9; ++var10) {
+ ExtendedBlockStorage var20 = var19[var10];
+
+ if (var20 != null && var20.getNeedsRandomTick()) {
+ for (int var21 = 0; var21 < 3; ++var21) {
+ this.updateLCG = this.updateLCG * 3 + 1013904223;
+ var13 = this.updateLCG >> 2;
+ int var14 = var13 & 15;
+ int var15 = var13 >> 8 & 15;
+ int var16 = var13 >> 16 & 15;
+ int var17 = var20.getExtBlockID(var14, var16, var15);
+ ++var2;
+ Block var18 = Block.blocksList[var17];
+
+ if (var18 != null && var18.getTickRandomly()) {
+ ++var1;
+ var18.updateTick(this, var14 + var5, var16 + var20.getYLocation(), var15 + var6, this.rand);
+ ++_tu;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns true if the given block will receive a scheduled tick in the future.
+ * Args: X, Y, Z, blockID
+ */
+ public boolean isBlockTickScheduled(int par1, int par2, int par3, int par4) {
+ NextTickListEntry var5 = new NextTickListEntry(par1, par2, par3, par4);
+ return this.field_94579_S.contains(var5);
+ }
+
+ /**
+ * Used to schedule a call to the updateTick method on the specified block.
+ */
+ public void scheduleBlockUpdate(int par1, int par2, int par3, int par4, int par5) {
+ this.func_82740_a(par1, par2, par3, par4, par5, 0);
+ }
+
+ public void func_82740_a(int par1, int par2, int par3, int par4, int par5, int par6) {
+ NextTickListEntry var7 = new NextTickListEntry(par1, par2, par3, par4);
+ byte var8 = 0;
+
+ if (this.scheduledUpdatesAreImmediate && par4 > 0) {
+ if (Block.blocksList[par4].func_82506_l()) {
+ if (this.checkChunksExist(var7.xCoord - var8, var7.yCoord - var8, var7.zCoord - var8,
+ var7.xCoord + var8, var7.yCoord + var8, var7.zCoord + var8)) {
+ int var9 = this.getBlockId(var7.xCoord, var7.yCoord, var7.zCoord);
+
+ if (var9 == var7.blockID && var9 > 0) {
+ Block.blocksList[var9].updateTick(this, var7.xCoord, var7.yCoord, var7.zCoord, this.rand);
+ ++_tu;
+ }
+ }
+
+ return;
+ }
+
+ par5 = 1;
+ }
+
+ if (this.checkChunksExist(par1 - var8, par2 - var8, par3 - var8, par1 + var8, par2 + var8, par3 + var8)) {
+ if (par4 > 0) {
+ var7.setScheduledTime((long) par5 + this.worldInfo.getWorldTotalTime());
+ var7.func_82753_a(par6);
+ }
+
+ if (!this.field_73064_N.contains(var7)) {
+ this.field_73064_N.add(var7);
+ this.pendingTickListEntries.add(var7);
+ }
+ }
+ }
+
+ /**
+ * Schedules a block update from the saved information in a chunk. Called when
+ * the chunk is loaded.
+ */
+ public void scheduleBlockUpdateFromLoad(int par1, int par2, int par3, int par4, int par5, int par6) {
+ NextTickListEntry var7 = new NextTickListEntry(par1, par2, par3, par4);
+ var7.func_82753_a(par6);
+
+ if (par4 > 0) {
+ var7.setScheduledTime((long) par5 + this.worldInfo.getWorldTotalTime());
+ }
+
+ if (!this.field_73064_N.contains(var7)) {
+ this.field_73064_N.add(var7);
+ this.pendingTickListEntries.add(var7);
+ }
+ }
+
+ /**
+ * Updates (and cleans up) entities and tile entities
+ */
+ public void updateEntities() {
+ if (this.playerEntities.isEmpty()) {
+ if (this.updateEntityTick++ >= 1200) {
+ return;
+ }
+ } else {
+ this.resetUpdateEntityTick();
+ }
+
+ super.updateEntities();
+ }
+
+ /**
+ * Resets the updateEntityTick field to 0
+ */
+ public void resetUpdateEntityTick() {
+ this.updateEntityTick = 0;
+ }
+
+ /**
+ * Runs through the list of updates to run and ticks them
+ */
+ public boolean tickUpdates(boolean par1) {
+ int var2 = this.pendingTickListEntries.size();
+
+ if (var2 != this.field_73064_N.size()) {
+ throw new IllegalStateException("TickNextTick list out of synch");
+ } else {
+ if (var2 > 1000) {
+ var2 = 1000;
+ }
+
+ NextTickListEntry var4;
+
+ for (int var3 = 0; var3 < var2; ++var3) {
+ var4 = (NextTickListEntry) this.pendingTickListEntries.first();
+
+ if (!par1 && var4.scheduledTime > this.worldInfo.getWorldTotalTime()) {
+ break;
+ }
+
+ this.pendingTickListEntries.remove(var4);
+ this.field_73064_N.remove(var4);
+ this.field_94579_S.add(var4);
+ }
+
+ Iterator var14 = this.field_94579_S.iterator();
+
+ while (var14.hasNext()) {
+ var4 = (NextTickListEntry) var14.next();
+ var14.remove();
+ byte var5 = 0;
+
+ if (this.checkChunksExist(var4.xCoord - var5, var4.yCoord - var5, var4.zCoord - var5,
+ var4.xCoord + var5, var4.yCoord + var5, var4.zCoord + var5)) {
+ int var6 = this.getBlockId(var4.xCoord, var4.yCoord, var4.zCoord);
+
+ if (var6 > 0 && Block.isAssociatedBlockID(var6, var4.blockID)) {
+ Block.blocksList[var6].updateTick(this, var4.xCoord, var4.yCoord, var4.zCoord, this.rand);
+ ++_tu;
+ }
+ } else {
+ this.scheduleBlockUpdate(var4.xCoord, var4.yCoord, var4.zCoord, var4.blockID, 0);
+ }
+ }
+
+ this.field_94579_S.clear();
+ return !this.pendingTickListEntries.isEmpty();
+ }
+ }
+
+ public List getPendingBlockUpdates(Chunk par1Chunk, boolean par2) {
+ ArrayList var3 = null;
+ ChunkCoordIntPair var4 = par1Chunk.getChunkCoordIntPair();
+ int var5 = (var4.chunkXPos << 4) - 2;
+ int var6 = var5 + 16 + 2;
+ int var7 = (var4.chunkZPos << 4) - 2;
+ int var8 = var7 + 16 + 2;
+
+ for (int var9 = 0; var9 < 2; ++var9) {
+ Iterator var10;
+
+ if (var9 == 0) {
+ var10 = this.pendingTickListEntries.iterator();
+ } else {
+ var10 = this.field_94579_S.iterator();
+
+ if (!this.field_94579_S.isEmpty()) {
+ System.out.println(this.field_94579_S.size());
+ }
+ }
+
+ while (var10.hasNext()) {
+ NextTickListEntry var11 = (NextTickListEntry) var10.next();
+
+ if (var11.xCoord >= var5 && var11.xCoord < var6 && var11.zCoord >= var7 && var11.zCoord < var8) {
+ if (par2) {
+ this.field_73064_N.remove(var11);
+ var10.remove();
+ }
+
+ if (var3 == null) {
+ var3 = new ArrayList();
+ }
+
+ var3.add(var11);
+ }
+ }
+ }
+
+ return var3;
+ }
+
+ /**
+ * Will update the entity in the world if the chunk the entity is in is
+ * currently loaded or its forced to update. Args: entity, forceUpdate
+ */
+ public void updateEntityWithOptionalForce(Entity par1Entity, boolean par2) {
+ if (!this.mcServer.getCanSpawnAnimals()
+ && (par1Entity instanceof EntityAnimal || par1Entity instanceof EntityWaterMob)) {
+ par1Entity.setDead();
+ }
+
+ if (!this.mcServer.getCanSpawnNPCs() && par1Entity instanceof INpc) {
+ par1Entity.setDead();
+ }
+
+ if (!(par1Entity.riddenByEntity instanceof EntityPlayer)) {
+ super.updateEntityWithOptionalForce(par1Entity, par2);
+ }
+ }
+
+ /**
+ * direct call to super.updateEntityWithOptionalForce
+ */
+ public void uncheckedUpdateEntity(Entity par1Entity, boolean par2) {
+ super.updateEntityWithOptionalForce(par1Entity, par2);
+ }
+
+ /**
+ * Creates the chunk provider for this world. Called in the constructor.
+ * Retrieves provider from worldProvider?
+ */
+ protected IChunkProvider createChunkProvider() {
+ IChunkLoader var1 = this.saveHandler.getChunkLoader(this.provider);
+ this.theChunkProviderServer = new ChunkProviderServer(this, var1, this.provider.createChunkGenerator());
+ return this.theChunkProviderServer;
+ }
+
+ /**
+ * get a list of tileEntity's
+ */
+ public List getTileEntityList(int par1, int par2, int par3, int par4, int par5, int par6) {
+ ArrayList var7 = new ArrayList();
+
+ for (int var8 = 0; var8 < this.loadedTileEntityList.size(); ++var8) {
+ TileEntity var9 = (TileEntity) this.loadedTileEntityList.get(var8);
+
+ if (var9.xCoord >= par1 && var9.yCoord >= par2 && var9.zCoord >= par3 && var9.xCoord < par4
+ && var9.yCoord < par5 && var9.zCoord < par6) {
+ var7.add(var9);
+ }
+ }
+
+ return var7;
+ }
+
+ /**
+ * Called when checking if a certain block can be mined or not. The 'spawn safe
+ * zone' check is located here.
+ */
+ public boolean canMineBlock(EntityPlayer par1EntityPlayer, int par2, int par3, int par4) {
+ return !this.mcServer.func_96290_a(this, par2, par3, par4, par1EntityPlayer);
+ }
+
+ protected void initialize(WorldSettings par1WorldSettings) {
+ if (this.entityIdMap == null) {
+ this.entityIdMap = new IntHashMap();
+ }
+
+ if (this.field_73064_N == null) {
+ this.field_73064_N = new HashSet();
+ }
+
+ if (this.pendingTickListEntries == null) {
+ this.pendingTickListEntries = new TreeSet();
+ }
+
+ this.createSpawnPosition(par1WorldSettings);
+ super.initialize(par1WorldSettings);
+ }
+
+ /**
+ * creates a spawn position at random within 256 blocks of 0,0
+ */
+ protected void createSpawnPosition(WorldSettings par1WorldSettings) {
+ if (!this.provider.canRespawnHere()) {
+ this.worldInfo.setSpawnPosition(0, this.provider.getAverageGroundLevel(), 0);
+ } else {
+ this.findingSpawnPoint = true;
+ WorldChunkManager var2 = this.provider.worldChunkMgr;
+ List var3 = var2.getBiomesToSpawnIn();
+ EaglercraftRandom var4 = new EaglercraftRandom(this.getSeed());
+ ChunkPosition var5 = var2.findBiomePosition(0, 0, 256, var3, var4);
+ int var6 = 0;
+ int var7 = this.provider.getAverageGroundLevel();
+ int var8 = 0;
+
+ if (var5 != null) {
+ var6 = var5.x;
+ var8 = var5.z;
+ } else {
+ this.getWorldLogAgent().func_98236_b("Unable to find spawn biome");
+ }
+
+ int var9 = 0;
+
+ while (!this.provider.canCoordinateBeSpawn(var6, var8)) {
+ var6 += var4.nextInt(64) - var4.nextInt(64);
+ var8 += var4.nextInt(64) - var4.nextInt(64);
+ ++var9;
+
+ if (var9 == 1000) {
+ break;
+ }
+ }
+
+ this.worldInfo.setSpawnPosition(var6, var7, var8);
+ this.findingSpawnPoint = false;
+
+ if (par1WorldSettings.isBonusChestEnabled()) {
+ this.createBonusChest();
+ }
+ }
+ }
+
+ /**
+ * Creates the bonus chest in the world.
+ */
+ protected void createBonusChest() {
+ WorldGeneratorBonusChest var1 = new WorldGeneratorBonusChest(bonusChestContent, 10);
+
+ for (int var2 = 0; var2 < 10; ++var2) {
+ int var3 = this.worldInfo.getSpawnX() + this.rand.nextInt(6) - this.rand.nextInt(6);
+ int var4 = this.worldInfo.getSpawnZ() + this.rand.nextInt(6) - this.rand.nextInt(6);
+ int var5 = this.getTopSolidOrLiquidBlock(var3, var4) + 1;
+
+ if (var1.generate(this, this.rand, var3, var5, var4)) {
+ break;
+ }
+ }
+ }
+
+ /**
+ * Gets the hard-coded portal location to use when entering this dimension.
+ */
+ public ChunkCoordinates getEntrancePortalLocation() {
+ return this.provider.getEntrancePortalLocation();
+ }
+
+ /**
+ * Saves all chunks to disk while updating progress bar.
+ */
+ public void saveAllChunks(boolean par1, IProgressUpdate par2IProgressUpdate) throws MinecraftException {
+ if (this.chunkProvider.canSave()) {
+ if (par2IProgressUpdate != null) {
+ par2IProgressUpdate.displaySavingString("Saving level");
+ }
+
+ this.saveLevel();
+
+ if (par2IProgressUpdate != null) {
+ par2IProgressUpdate.displayLoadingString("Saving chunks");
+ }
+
+ this.chunkProvider.saveChunks(par1, par2IProgressUpdate);
+ }
+ }
+
+ public void func_104140_m() {
+ if (this.chunkProvider.canSave()) {
+ this.chunkProvider.func_104112_b();
+ }
+ }
+
+ /**
+ * Saves the chunks to disk.
+ */
+ protected void saveLevel() throws MinecraftException {
+ this.checkSessionLock();
+ this.saveHandler.saveWorldInfoWithPlayer(this.worldInfo,
+ this.mcServer.getConfigurationManager().getHostPlayerData());
+ this.mapStorage.saveAllData();
+ }
+
+ /**
+ * Start the skin for this entity downloading, if necessary, and increment its
+ * reference counter
+ */
+ protected void obtainEntitySkin(Entity par1Entity) {
+ super.obtainEntitySkin(par1Entity);
+ this.entityIdMap.addKey(par1Entity.entityId, par1Entity);
+ Entity[] var2 = par1Entity.getParts();
+
+ if (var2 != null) {
+ for (int var3 = 0; var3 < var2.length; ++var3) {
+ this.entityIdMap.addKey(var2[var3].entityId, var2[var3]);
+ }
+ }
+ }
+
+ /**
+ * Decrement the reference counter for this entity's skin image data
+ */
+ protected void releaseEntitySkin(Entity par1Entity) {
+ super.releaseEntitySkin(par1Entity);
+ this.entityIdMap.removeObject(par1Entity.entityId);
+ Entity[] var2 = par1Entity.getParts();
+
+ if (var2 != null) {
+ for (int var3 = 0; var3 < var2.length; ++var3) {
+ this.entityIdMap.removeObject(var2[var3].entityId);
+ }
+ }
+ }
+
+ /**
+ * Returns the Entity with the given ID, or null if it doesn't exist in this
+ * World.
+ */
+ public Entity getEntityByID(int par1) {
+ return (Entity) this.entityIdMap.lookup(par1);
+ }
+
+ /**
+ * adds a lightning bolt to the list of lightning bolts in this world.
+ */
+ public boolean addWeatherEffect(Entity par1Entity) {
+ if (super.addWeatherEffect(par1Entity)) {
+ this.mcServer.getConfigurationManager().sendPacketToPlayersAroundPoint(par1Entity.posX, par1Entity.posY,
+ par1Entity.posZ, 512.0D, this.provider.dimensionId, new Packet71Weather(par1Entity));
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * sends a Packet 38 (Entity Status) to all tracked players of that entity
+ */
+ public void setEntityState(Entity par1Entity, byte par2) {
+ Packet38EntityStatus var3 = new Packet38EntityStatus(par1Entity.entityId, par2);
+ this.getEntityTracker().sendPacketToTrackedPlayersAndTrackedEntity(par1Entity, var3);
+ }
+
+ /**
+ * returns a new explosion. Does initiation (at time of writing Explosion is not
+ * finished)
+ */
+ public Explosion newExplosion(Entity par1Entity, double par2, double par4, double par6, float par8, boolean par9,
+ boolean par10) {
+ Explosion var11 = new Explosion(this, par1Entity, par2, par4, par6, par8);
+ var11.isFlaming = par9;
+ var11.isSmoking = par10;
+ var11.doExplosionA();
+ var11.doExplosionB(false);
+
+ if (!par10) {
+ var11.affectedBlockPositions.clear();
+ }
+
+ Iterator var12 = this.playerEntities.iterator();
+
+ while (var12.hasNext()) {
+ EntityPlayer var13 = (EntityPlayer) var12.next();
+
+ if (var13.getDistanceSq(par2, par4, par6) < 4096.0D) {
+ ((EntityPlayerMP) var13).playerNetServerHandler.sendPacket(new Packet60Explosion(par2, par4, par6, par8,
+ var11.affectedBlockPositions, (Vec3) var11.func_77277_b().get(var13)));
+ }
+ }
+
+ return var11;
+ }
+
+ /**
+ * Adds a block event with the given Args to the blockEventCache. During the
+ * next tick(), the block specified will have its onBlockEvent handler called
+ * with the given parameters. Args: X,Y,Z, BlockID, EventID, EventParameter
+ */
+ public void addBlockEvent(int par1, int par2, int par3, int par4, int par5, int par6) {
+ BlockEventData var7 = new BlockEventData(par1, par2, par3, par4, par5, par6);
+ Iterator var8 = this.blockEventCache[this.blockEventCacheIndex].iterator();
+ BlockEventData var9;
+
+ do {
+ if (!var8.hasNext()) {
+ this.blockEventCache[this.blockEventCacheIndex].add(var7);
+ return;
+ }
+
+ var9 = (BlockEventData) var8.next();
+ } while (!var9.equals(var7));
+ }
+
+ /**
+ * Send and apply locally all pending BlockEvents to each player with 64m radius
+ * of the event.
+ */
+ private void sendAndApplyBlockEvents() {
+ while (!this.blockEventCache[this.blockEventCacheIndex].isEmpty()) {
+ int var1 = this.blockEventCacheIndex;
+ this.blockEventCacheIndex ^= 1;
+ Iterator var2 = this.blockEventCache[var1].iterator();
+
+ while (var2.hasNext()) {
+ BlockEventData var3 = (BlockEventData) var2.next();
+
+ if (this.onBlockEventReceived(var3)) {
+ this.mcServer.getConfigurationManager().sendPacketToPlayersAroundPoint((double) var3.getX(),
+ (double) var3.getY(), (double) var3.getZ(), 64.0D, this.provider.dimensionId,
+ new Packet54PlayNoteBlock(var3.getX(), var3.getY(), var3.getZ(), var3.getBlockID(),
+ var3.getEventID(), var3.getEventParameter()));
+ }
+ }
+
+ this.blockEventCache[var1].clear();
+ }
+ }
+
+ /**
+ * Called to apply a pending BlockEvent to apply to the current world.
+ */
+ private boolean onBlockEventReceived(BlockEventData par1BlockEventData) {
+ int var2 = this.getBlockId(par1BlockEventData.getX(), par1BlockEventData.getY(), par1BlockEventData.getZ());
+ return var2 == par1BlockEventData.getBlockID() ? Block.blocksList[var2].onBlockEventReceived(this,
+ par1BlockEventData.getX(), par1BlockEventData.getY(), par1BlockEventData.getZ(),
+ par1BlockEventData.getEventID(), par1BlockEventData.getEventParameter()) : false;
+ }
+
+ /**
+ * Syncs all changes to disk and wait for completion.
+ */
+ public void flush() {
+ this.saveHandler.flush();
+ }
+
+ /**
+ * Updates all weather states.
+ */
+ protected void updateWeather() {
+ boolean var1 = this.isRaining();
+ super.updateWeather();
+
+ if (var1 != this.isRaining()) {
+ if (var1) {
+ this.mcServer.getConfigurationManager().sendPacketToAllPlayers(new Packet70GameEvent(2, 0));
+ } else {
+ this.mcServer.getConfigurationManager().sendPacketToAllPlayers(new Packet70GameEvent(1, 0));
+ }
+ }
+ }
+
+ /**
+ * Gets the MinecraftServer.
+ */
+ public MinecraftServer getMinecraftServer() {
+ return this.mcServer;
+ }
+
+ /**
+ * Gets the EntityTracker
+ */
+ public EntityTracker getEntityTracker() {
+ return this.theEntityTracker;
+ }
+
+ public PlayerManager getPlayerManager() {
+ return this.thePlayerManager;
+ }
+
+ public Teleporter getDefaultTeleporter() {
+ return this.field_85177_Q;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldServerMulti.java b/sp-server/src/main/java/net/minecraft/src/WorldServerMulti.java
new file mode 100644
index 0000000..46792d4
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldServerMulti.java
@@ -0,0 +1,19 @@
+package net.minecraft.src;
+
+import net.minecraft.server.MinecraftServer;
+
+public class WorldServerMulti extends WorldServer {
+ public WorldServerMulti(MinecraftServer par1MinecraftServer, ISaveHandler par2ISaveHandler, String par3Str,
+ int par4, WorldSettings par5WorldSettings, WorldServer par6WorldServer, ILogAgent par8ILogAgent) {
+ super(par1MinecraftServer, par2ISaveHandler, par3Str, par4, par5WorldSettings, par8ILogAgent);
+ this.mapStorage = par6WorldServer.mapStorage;
+ this.worldScoreboard = par6WorldServer.getScoreboard();
+ this.worldInfo = new DerivedWorldInfo(par6WorldServer.getWorldInfo());
+ }
+
+ /**
+ * Saves the chunks to disk.
+ */
+ protected void saveLevel() throws MinecraftException {
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldSettings.java b/sp-server/src/main/java/net/minecraft/src/WorldSettings.java
new file mode 100644
index 0000000..0db0d5f
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldSettings.java
@@ -0,0 +1,116 @@
+package net.minecraft.src;
+
+public final class WorldSettings {
+ /** The seed for the map. */
+ private final long seed;
+
+ /** The EnumGameType. */
+ private final EnumGameType theGameType;
+
+ /**
+ * Switch for the map features. 'true' for enabled, 'false' for disabled.
+ */
+ private final boolean mapFeaturesEnabled;
+
+ /** True if hardcore mode is enabled */
+ private final boolean hardcoreEnabled;
+ private final WorldType terrainType;
+
+ /** True if Commands (cheats) are allowed. */
+ private boolean commandsAllowed;
+
+ /** True if the Bonus Chest is enabled. */
+ private boolean bonusChestEnabled;
+ private String field_82751_h;
+
+ public WorldSettings(long par1, EnumGameType par3EnumGameType, boolean par4, boolean par5,
+ WorldType par6WorldType) {
+ this.field_82751_h = "";
+ this.seed = par1;
+ this.theGameType = par3EnumGameType;
+ this.mapFeaturesEnabled = par4;
+ this.hardcoreEnabled = par5;
+ this.terrainType = par6WorldType;
+ }
+
+ public WorldSettings(WorldInfo par1WorldInfo) {
+ this(par1WorldInfo.getSeed(), par1WorldInfo.getGameType(), par1WorldInfo.isMapFeaturesEnabled(),
+ par1WorldInfo.isHardcoreModeEnabled(), par1WorldInfo.getTerrainType());
+ }
+
+ /**
+ * Enables the bonus chest.
+ */
+ public WorldSettings enableBonusChest() {
+ this.bonusChestEnabled = true;
+ return this;
+ }
+
+ public WorldSettings enableCheats() {
+ this.commandsAllowed = true;
+ return this;
+ }
+
+ public WorldSettings func_82750_a(String par1Str) {
+ this.field_82751_h = par1Str;
+ return this;
+ }
+
+ /**
+ * Returns true if the Bonus Chest is enabled.
+ */
+ public boolean isBonusChestEnabled() {
+ return this.bonusChestEnabled;
+ }
+
+ /**
+ * Returns the seed for the world.
+ */
+ public long getSeed() {
+ return this.seed;
+ }
+
+ /**
+ * Gets the game type.
+ */
+ public EnumGameType getGameType() {
+ return this.theGameType;
+ }
+
+ /**
+ * Returns true if hardcore mode is enabled, otherwise false
+ */
+ public boolean getHardcoreEnabled() {
+ return this.hardcoreEnabled;
+ }
+
+ /**
+ * Get whether the map features (e.g. strongholds) generation is enabled or
+ * disabled.
+ */
+ public boolean isMapFeaturesEnabled() {
+ return this.mapFeaturesEnabled;
+ }
+
+ public WorldType getTerrainType() {
+ return this.terrainType;
+ }
+
+ /**
+ * Returns true if Commands (cheats) are allowed.
+ */
+ public boolean areCommandsAllowed() {
+ return this.commandsAllowed;
+ }
+
+ /**
+ * Gets the GameType by ID
+ */
+ public static EnumGameType getGameTypeById(int par0) {
+ return EnumGameType.getByID(par0);
+ }
+
+ public String func_82749_j() {
+ return this.field_82751_h;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WorldType.java b/sp-server/src/main/java/net/minecraft/src/WorldType.java
new file mode 100644
index 0000000..af12217
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WorldType.java
@@ -0,0 +1,98 @@
+package net.minecraft.src;
+
+public class WorldType {
+ /** List of world types. */
+ public static final WorldType[] worldTypes = new WorldType[16];
+
+ /** Default world type. */
+ public static final WorldType DEFAULT = (new WorldType(0, "default", 1)).setVersioned();
+
+ /** Flat world type. */
+ public static final WorldType FLAT = new WorldType(1, "flat");
+
+ /** Large Biome world Type. */
+ public static final WorldType LARGE_BIOMES = new WorldType(2, "largeBiomes");
+
+ /** Default (1.1) world type. */
+ public static final WorldType DEFAULT_1_1 = (new WorldType(8, "default_1_1", 0)).setCanBeCreated(false);
+
+ /** ID for this world type. */
+ private final int worldTypeId;
+ private final String worldType;
+
+ /** The int version of the ChunkProvider that generated this world. */
+ private final int generatorVersion;
+
+ /**
+ * Whether this world type can be generated. Normally true; set to false for
+ * out-of-date generator versions.
+ */
+ private boolean canBeCreated;
+
+ /** Whether this WorldType has a version or not. */
+ private boolean isWorldTypeVersioned;
+
+ private WorldType(int par1, String par2Str) {
+ this(par1, par2Str, 0);
+ }
+
+ private WorldType(int par1, String par2Str, int par3) {
+ this.worldType = par2Str;
+ this.generatorVersion = par3;
+ this.canBeCreated = true;
+ this.worldTypeId = par1;
+ worldTypes[par1] = this;
+ }
+
+ public String getWorldTypeName() {
+ return this.worldType;
+ }
+
+ /**
+ * Returns generatorVersion.
+ */
+ public int getGeneratorVersion() {
+ return this.generatorVersion;
+ }
+
+ public WorldType getWorldTypeForGeneratorVersion(int par1) {
+ return this == DEFAULT && par1 == 0 ? DEFAULT_1_1 : this;
+ }
+
+ /**
+ * Sets canBeCreated to the provided value, and returns this.
+ */
+ private WorldType setCanBeCreated(boolean par1) {
+ this.canBeCreated = par1;
+ return this;
+ }
+
+ /**
+ * Flags this world type as having an associated version.
+ */
+ private WorldType setVersioned() {
+ this.isWorldTypeVersioned = true;
+ return this;
+ }
+
+ /**
+ * Returns true if this world Type has a version associated with it.
+ */
+ public boolean isVersioned() {
+ return this.isWorldTypeVersioned;
+ }
+
+ public static WorldType parseWorldType(String par0Str) {
+ for (int var1 = 0; var1 < worldTypes.length; ++var1) {
+ if (worldTypes[var1] != null && worldTypes[var1].worldType.equalsIgnoreCase(par0Str)) {
+ return worldTypes[var1];
+ }
+ }
+
+ return null;
+ }
+
+ public int getWorldTypeID() {
+ return this.worldTypeId;
+ }
+}
diff --git a/sp-server/src/main/java/net/minecraft/src/WrongUsageException.java b/sp-server/src/main/java/net/minecraft/src/WrongUsageException.java
new file mode 100644
index 0000000..fa83809
--- /dev/null
+++ b/sp-server/src/main/java/net/minecraft/src/WrongUsageException.java
@@ -0,0 +1,7 @@
+package net.minecraft.src;
+
+public class WrongUsageException extends SyntaxErrorException {
+ public WrongUsageException(String par1Str, Object... par2ArrayOfObj) {
+ super(par1Str, par2ArrayOfObj);
+ }
+}
diff --git a/sp-server/src_aux/AnvilChunkLoader.java b/sp-server/src_aux/AnvilChunkLoader.java
new file mode 100644
index 0000000..302a73d
--- /dev/null
+++ b/sp-server/src_aux/AnvilChunkLoader.java
@@ -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;
+ }
+}
diff --git a/sp-server/src_aux/AnvilChunkLoaderPending.java b/sp-server/src_aux/AnvilChunkLoaderPending.java
new file mode 100644
index 0000000..df5d13d
--- /dev/null
+++ b/sp-server/src_aux/AnvilChunkLoaderPending.java
@@ -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;
+ }
+}
diff --git a/sp-server/src_aux/AnvilConverterData.java b/sp-server/src_aux/AnvilConverterData.java
new file mode 100644
index 0000000..3b4f89e
--- /dev/null
+++ b/sp-server/src_aux/AnvilConverterData.java
@@ -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;
+ }
+}
diff --git a/sp-server/src_aux/AnvilSaveConverter.java b/sp-server/src_aux/AnvilSaveConverter.java
new file mode 100644
index 0000000..b1bcb2a
--- /dev/null
+++ b/sp-server/src_aux/AnvilSaveConverter.java
@@ -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);
+ }
+ }
+}
diff --git a/sp-server/src_aux/AnvilSaveConverterFileFilter.java b/sp-server/src_aux/AnvilSaveConverterFileFilter.java
new file mode 100644
index 0000000..9d6a70d
--- /dev/null
+++ b/sp-server/src_aux/AnvilSaveConverterFileFilter.java
@@ -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");
+ }
+}
diff --git a/sp-server/src_aux/AnvilSaveHandler.java b/sp-server/src_aux/AnvilSaveHandler.java
new file mode 100644
index 0000000..00334a8
--- /dev/null
+++ b/sp-server/src_aux/AnvilSaveHandler.java
@@ -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();
+ }
+}
diff --git a/sp-server/src_aux/ChunkLoader.java b/sp-server/src_aux/ChunkLoader.java
new file mode 100644
index 0000000..e9b2209
--- /dev/null
+++ b/sp-server/src_aux/ChunkLoader.java
@@ -0,0 +1,122 @@
+package net.minecraft.src;
+
+public class ChunkLoader {
+ public static AnvilConverterData load(NBTTagCompound par0NBTTagCompound) {
+ int var1 = par0NBTTagCompound.getInteger("xPos");
+ int var2 = par0NBTTagCompound.getInteger("zPos");
+ AnvilConverterData var3 = new AnvilConverterData(var1, var2);
+ var3.blocks = par0NBTTagCompound.getByteArray("Blocks");
+ var3.data = new NibbleArrayReader(par0NBTTagCompound.getByteArray("Data"), 7);
+ var3.skyLight = new NibbleArrayReader(par0NBTTagCompound.getByteArray("SkyLight"), 7);
+ var3.blockLight = new NibbleArrayReader(par0NBTTagCompound.getByteArray("BlockLight"), 7);
+ var3.heightmap = par0NBTTagCompound.getByteArray("HeightMap");
+ var3.terrainPopulated = par0NBTTagCompound.getBoolean("TerrainPopulated");
+ var3.entities = par0NBTTagCompound.getTagList("Entities");
+ var3.tileEntities = par0NBTTagCompound.getTagList("TileEntities");
+ var3.tileTicks = par0NBTTagCompound.getTagList("TileTicks");
+
+ try {
+ var3.lastUpdated = par0NBTTagCompound.getLong("LastUpdate");
+ } catch (ClassCastException var5) {
+ var3.lastUpdated = (long) par0NBTTagCompound.getInteger("LastUpdate");
+ }
+
+ return var3;
+ }
+
+ public static void convertToAnvilFormat(AnvilConverterData par0AnvilConverterData,
+ NBTTagCompound par1NBTTagCompound, WorldChunkManager par2WorldChunkManager) {
+ par1NBTTagCompound.setInteger("xPos", par0AnvilConverterData.x);
+ par1NBTTagCompound.setInteger("zPos", par0AnvilConverterData.z);
+ par1NBTTagCompound.setLong("LastUpdate", par0AnvilConverterData.lastUpdated);
+ int[] var3 = new int[par0AnvilConverterData.heightmap.length];
+
+ for (int var4 = 0; var4 < par0AnvilConverterData.heightmap.length; ++var4) {
+ var3[var4] = par0AnvilConverterData.heightmap[var4];
+ }
+
+ par1NBTTagCompound.setIntArray("HeightMap", var3);
+ par1NBTTagCompound.setBoolean("TerrainPopulated", par0AnvilConverterData.terrainPopulated);
+ NBTTagList var16 = new NBTTagList("Sections");
+ int var7;
+
+ for (int var5 = 0; var5 < 8; ++var5) {
+ boolean var6 = true;
+
+ for (var7 = 0; var7 < 16 && var6; ++var7) {
+ int var8 = 0;
+
+ while (var8 < 16 && var6) {
+ int var9 = 0;
+
+ while (true) {
+ if (var9 < 16) {
+ int var10 = var7 << 11 | var9 << 7 | var8 + (var5 << 4);
+ byte var11 = par0AnvilConverterData.blocks[var10];
+
+ if (var11 == 0) {
+ ++var9;
+ continue;
+ }
+
+ var6 = false;
+ }
+
+ ++var8;
+ break;
+ }
+ }
+ }
+
+ if (!var6) {
+ byte[] var19 = new byte[4096];
+ NibbleArray var20 = new NibbleArray(var19.length, 4);
+ NibbleArray var21 = new NibbleArray(var19.length, 4);
+ NibbleArray var22 = new NibbleArray(var19.length, 4);
+
+ for (int var23 = 0; var23 < 16; ++var23) {
+ for (int var12 = 0; var12 < 16; ++var12) {
+ for (int var13 = 0; var13 < 16; ++var13) {
+ int var14 = var23 << 11 | var13 << 7 | var12 + (var5 << 4);
+ byte var15 = par0AnvilConverterData.blocks[var14];
+ var19[var12 << 8 | var13 << 4 | var23] = (byte) (var15 & 255);
+ var20.set(var23, var12, var13,
+ par0AnvilConverterData.data.get(var23, var12 + (var5 << 4), var13));
+ var21.set(var23, var12, var13,
+ par0AnvilConverterData.skyLight.get(var23, var12 + (var5 << 4), var13));
+ var22.set(var23, var12, var13,
+ par0AnvilConverterData.blockLight.get(var23, var12 + (var5 << 4), var13));
+ }
+ }
+ }
+
+ NBTTagCompound var24 = new NBTTagCompound();
+ var24.setByte("Y", (byte) (var5 & 255));
+ var24.setByteArray("Blocks", var19);
+ var24.setByteArray("Data", var20.data);
+ var24.setByteArray("SkyLight", var21.data);
+ var24.setByteArray("BlockLight", var22.data);
+ var16.appendTag(var24);
+ }
+ }
+
+ par1NBTTagCompound.setTag("Sections", var16);
+ byte[] var17 = new byte[256];
+
+ for (int var18 = 0; var18 < 16; ++var18) {
+ for (var7 = 0; var7 < 16; ++var7) {
+ var17[var7 << 4
+ | var18] = (byte) (par2WorldChunkManager.getBiomeGenAt(par0AnvilConverterData.x << 4 | var18,
+ par0AnvilConverterData.z << 4 | var7).biomeID & 255);
+ }
+ }
+
+ par1NBTTagCompound.setByteArray("Biomes", var17);
+ par1NBTTagCompound.setTag("Entities", par0AnvilConverterData.entities);
+ par1NBTTagCompound.setTag("TileEntities", par0AnvilConverterData.tileEntities);
+
+ if (par0AnvilConverterData.tileTicks != null) {
+ par1NBTTagCompound.setTag("TileTicks", par0AnvilConverterData.tileTicks);
+ }
+ }
+}
diff --git a/sp-server/src_aux/DedicatedServer.java b/sp-server/src_aux/DedicatedServer.java
new file mode 100644
index 0000000..7b46f5e
--- /dev/null
+++ b/sp-server/src_aux/DedicatedServer.java
@@ -0,0 +1,368 @@
+package net.minecraft.src;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Random;
+import net.minecraft.server.MinecraftServer;
+
+public class DedicatedServer extends MinecraftServer implements IServer {
+ private final List pendingCommandList = Collections.synchronizedList(new ArrayList());
+ private final ILogAgent field_98131_l;
+ private RConThreadQuery theRConThreadQuery;
+ private RConThreadMain theRConThreadMain;
+ private PropertyManager settings;
+ private boolean canSpawnStructures;
+ private EnumGameType gameType;
+ private NetworkListenThread networkThread;
+ private boolean guiIsEnabled = false;
+
+ public DedicatedServer(File par1File) {
+ super(par1File);
+ this.field_98131_l = new LogAgent("Minecraft-Server", (String) null,
+ (new File(par1File, "server.log")).getAbsolutePath());
+ new DedicatedServerSleepThread(this);
+ }
+
+ /**
+ * Initialises the server and starts it.
+ */
+ protected boolean startServer() throws IOException {
+ DedicatedServerCommandThread var1 = new DedicatedServerCommandThread(this);
+ var1.setDaemon(true);
+ var1.start();
+ this.getLogAgent().func_98233_a("Starting minecraft server version 1.5.2");
+
+ if (Runtime.getRuntime().maxMemory() / 1024L / 1024L < 512L) {
+ this.getLogAgent().func_98236_b(
+ "To start the server with more ram, launch it as \"java -Xmx1024M -Xms1024M -jar minecraft_server.jar\"");
+ }
+
+ this.getLogAgent().func_98233_a("Loading properties");
+ this.settings = new PropertyManager(new File("server.properties"), this.getLogAgent());
+
+ if (this.isSinglePlayer()) {
+ this.setHostname("127.0.0.1");
+ } else {
+ this.setOnlineMode(this.settings.getBooleanProperty("online-mode", true));
+ this.setHostname(this.settings.getStringProperty("server-ip", ""));
+ }
+
+ this.setCanSpawnAnimals(this.settings.getBooleanProperty("spawn-animals", true));
+ this.setCanSpawnNPCs(this.settings.getBooleanProperty("spawn-npcs", true));
+ this.setAllowPvp(this.settings.getBooleanProperty("pvp", true));
+ this.setAllowFlight(this.settings.getBooleanProperty("allow-flight", false));
+ this.setTexturePack(this.settings.getStringProperty("texture-pack", ""));
+ this.setMOTD(this.settings.getStringProperty("motd", "A Minecraft Server"));
+ this.func_104055_i(this.settings.getBooleanProperty("force-gamemode", false));
+
+ if (this.settings.getIntProperty("difficulty", 1) < 0) {
+ this.settings.setProperty("difficulty", Integer.valueOf(0));
+ } else if (this.settings.getIntProperty("difficulty", 1) > 3) {
+ this.settings.setProperty("difficulty", Integer.valueOf(3));
+ }
+
+ this.canSpawnStructures = this.settings.getBooleanProperty("generate-structures", true);
+ int var2 = this.settings.getIntProperty("gamemode", EnumGameType.SURVIVAL.getID());
+ this.gameType = WorldSettings.getGameTypeById(var2);
+ this.getLogAgent().func_98233_a("Default game type: " + this.gameType);
+ InetAddress var3 = null;
+
+ if (this.getServerHostname().length() > 0) {
+ var3 = InetAddress.getByName(this.getServerHostname());
+ }
+
+ if (this.getServerPort() < 0) {
+ this.setServerPort(this.settings.getIntProperty("server-port", 25565));
+ }
+
+ this.getLogAgent().func_98233_a("Generating keypair");
+ this.setKeyPair(CryptManager.generateKeyPair());
+ this.getLogAgent()
+ .func_98233_a("Starting Minecraft server on "
+ + (this.getServerHostname().length() == 0 ? "*" : this.getServerHostname()) + ":"
+ + this.getServerPort());
+
+ try {
+ this.networkThread = new DedicatedServerListenThread(this, var3, this.getServerPort());
+ } catch (IOException var16) {
+ this.getLogAgent().func_98236_b("**** FAILED TO BIND TO PORT!");
+ this.getLogAgent().logWarningFormatted("The exception was: {0}", new Object[] { var16.toString() });
+ this.getLogAgent().func_98236_b("Perhaps a server is already running on that port?");
+ return false;
+ }
+
+ if (!this.isServerInOnlineMode()) {
+ this.getLogAgent().func_98236_b("**** SERVER IS RUNNING IN OFFLINE/INSECURE MODE!");
+ this.getLogAgent().func_98236_b("The server will make no attempt to authenticate usernames. Beware.");
+ this.getLogAgent().func_98236_b(
+ "While this makes the game possible to play without internet access, it also opens up the ability for hackers to connect with any username they choose.");
+ this.getLogAgent()
+ .func_98236_b("To change this, set \"online-mode\" to \"true\" in the server.properties file.");
+ }
+
+ this.setConfigurationManager(new DedicatedPlayerList(this));
+ long var4 = System.nanoTime();
+
+ if (this.getFolderName() == null) {
+ this.setFolderName(this.settings.getStringProperty("level-name", "world"));
+ }
+
+ String var6 = this.settings.getStringProperty("level-seed", "");
+ String var7 = this.settings.getStringProperty("level-type", "DEFAULT");
+ String var8 = this.settings.getStringProperty("generator-settings", "");
+ long var9 = (new Random()).nextLong();
+
+ if (var6.length() > 0) {
+ try {
+ long var11 = Long.parseLong(var6);
+
+ if (var11 != 0L) {
+ var9 = var11;
+ }
+ } catch (NumberFormatException var15) {
+ var9 = (long) var6.hashCode();
+ }
+ }
+
+ WorldType var17 = WorldType.parseWorldType(var7);
+
+ if (var17 == null) {
+ var17 = WorldType.DEFAULT;
+ }
+
+ this.setBuildLimit(this.settings.getIntProperty("max-build-height", 256));
+ this.setBuildLimit((this.getBuildLimit() + 8) / 16 * 16);
+ this.setBuildLimit(MathHelper.clamp_int(this.getBuildLimit(), 64, 256));
+ this.settings.setProperty("max-build-height", Integer.valueOf(this.getBuildLimit()));
+ this.getLogAgent().func_98233_a("Preparing level \"" + this.getFolderName() + "\"");
+ this.loadAllWorlds(this.getFolderName(), this.getFolderName(), var9, var17, var8);
+ long var12 = System.nanoTime() - var4;
+ String var14 = String.format("%.3fs", new Object[] { Double.valueOf((double) var12 / 1.0E9D) });
+ this.getLogAgent().func_98233_a("Done (" + var14 + ")! For help, type \"help\" or \"?\"");
+
+ if (this.settings.getBooleanProperty("enable-query", false)) {
+ this.getLogAgent().func_98233_a("Starting GS4 status listener");
+ this.theRConThreadQuery = new RConThreadQuery(this);
+ this.theRConThreadQuery.startThread();
+ }
+
+ if (this.settings.getBooleanProperty("enable-rcon", false)) {
+ this.getLogAgent().func_98233_a("Starting remote control listener");
+ this.theRConThreadMain = new RConThreadMain(this);
+ this.theRConThreadMain.startThread();
+ }
+
+ return true;
+ }
+
+ public boolean canStructuresSpawn() {
+ return this.canSpawnStructures;
+ }
+
+ public EnumGameType getGameType() {
+ return this.gameType;
+ }
+
+ /**
+ * Defaults to "1" (Easy) for the dedicated server, defaults to "2" (Normal) on
+ * the client.
+ */
+ public int getDifficulty() {
+ return this.settings.getIntProperty("difficulty", 1);
+ }
+
+ /**
+ * Defaults to false.
+ */
+ public boolean isHardcore() {
+ return this.settings.getBooleanProperty("hardcore", false);
+ }
+
+ /**
+ * Called on exit from the main run() loop.
+ */
+ protected void finalTick(CrashReport par1CrashReport) {
+ while (this.isServerRunning()) {
+ this.executePendingCommands();
+
+ try {
+ Thread.sleep(10L);
+ } catch (InterruptedException var3) {
+ var3.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * Adds the server info, including from theWorldServer, to the crash report.
+ */
+ public CrashReport addServerInfoToCrashReport(CrashReport par1CrashReport) {
+ par1CrashReport = super.addServerInfoToCrashReport(par1CrashReport);
+ par1CrashReport.func_85056_g().addCrashSectionCallable("Is Modded", new CallableType(this));
+ par1CrashReport.func_85056_g().addCrashSectionCallable("Type", new CallableServerType(this));
+ return par1CrashReport;
+ }
+
+ /**
+ * Directly calls System.exit(0), instantly killing the program.
+ */
+ protected void systemExitNow() {
+ System.exit(0);
+ }
+
+ public void updateTimeLightAndEntities() {
+ super.updateTimeLightAndEntities();
+ this.executePendingCommands();
+ }
+
+ public boolean getAllowNether() {
+ return this.settings.getBooleanProperty("allow-nether", true);
+ }
+
+ public boolean allowSpawnMonsters() {
+ return this.settings.getBooleanProperty("spawn-monsters", true);
+ }
+
+ public void addServerStatsToSnooper(PlayerUsageSnooper par1PlayerUsageSnooper) {
+ par1PlayerUsageSnooper.addData("whitelist_enabled",
+ Boolean.valueOf(this.getDedicatedPlayerList().isWhiteListEnabled()));
+ par1PlayerUsageSnooper.addData("whitelist_count",
+ Integer.valueOf(this.getDedicatedPlayerList().getWhiteListedPlayers().size()));
+ super.addServerStatsToSnooper(par1PlayerUsageSnooper);
+ }
+
+ /**
+ * Returns whether snooping is enabled or not.
+ */
+ public boolean isSnooperEnabled() {
+ return this.settings.getBooleanProperty("snooper-enabled", true);
+ }
+
+ public void addPendingCommand(String par1Str, ICommandSender par2ICommandSender) {
+ this.pendingCommandList.add(new ServerCommand(par1Str, par2ICommandSender));
+ }
+
+ public void executePendingCommands() {
+ while (!this.pendingCommandList.isEmpty()) {
+ ServerCommand var1 = (ServerCommand) this.pendingCommandList.remove(0);
+ this.getCommandManager().executeCommand(var1.sender, var1.command);
+ }
+ }
+
+ public boolean isDedicatedServer() {
+ return true;
+ }
+
+ public DedicatedPlayerList getDedicatedPlayerList() {
+ return (DedicatedPlayerList) super.getConfigurationManager();
+ }
+
+ public NetworkListenThread getNetworkThread() {
+ return this.networkThread;
+ }
+
+ /**
+ * Gets an integer property. If it does not exist, set it to the specified
+ * value.
+ */
+ public int getIntProperty(String par1Str, int par2) {
+ return this.settings.getIntProperty(par1Str, par2);
+ }
+
+ /**
+ * Gets a string property. If it does not exist, set it to the specified value.
+ */
+ public String getStringProperty(String par1Str, String par2Str) {
+ return this.settings.getStringProperty(par1Str, par2Str);
+ }
+
+ /**
+ * Gets a boolean property. If it does not exist, set it to the specified value.
+ */
+ public boolean getBooleanProperty(String par1Str, boolean par2) {
+ return this.settings.getBooleanProperty(par1Str, par2);
+ }
+
+ /**
+ * Saves an Object with the given property name.
+ */
+ public void setProperty(String par1Str, Object par2Obj) {
+ this.settings.setProperty(par1Str, par2Obj);
+ }
+
+ /**
+ * Saves all of the server properties to the properties file.
+ */
+ public void saveProperties() {
+ this.settings.saveProperties();
+ }
+
+ /**
+ * Returns the filename where server properties are stored
+ */
+ public String getSettingsFilename() {
+ File var1 = this.settings.getPropertiesFile();
+ return var1 != null ? var1.getAbsolutePath() : "No settings file";
+ }
+
+ public void enableGui() {
+ ServerGUI.initGUI(this);
+ this.guiIsEnabled = true;
+ }
+
+ public boolean getGuiEnabled() {
+ return this.guiIsEnabled;
+ }
+
+ /**
+ * On dedicated does nothing. On integrated, sets commandsAllowedForAll,
+ * gameType and allows external connections.
+ */
+ public String shareToLAN(EnumGameType par1EnumGameType, boolean par2) {
+ return "";
+ }
+
+ /**
+ * Return whether command blocks are enabled.
+ */
+ public boolean isCommandBlockEnabled() {
+ return this.settings.getBooleanProperty("enable-command-block", false);
+ }
+
+ /**
+ * Return the spawn protection area's size.
+ */
+ public int getSpawnProtectionSize() {
+ return this.settings.getIntProperty("spawn-protection", super.getSpawnProtectionSize());
+ }
+
+ public boolean func_96290_a(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer) {
+ if (par1World.provider.dimensionId != 0) {
+ return false;
+ } else if (this.getDedicatedPlayerList().getOps().isEmpty()) {
+ return false;
+ } else if (this.getDedicatedPlayerList().areCommandsAllowed(par5EntityPlayer.username)) {
+ return false;
+ } else if (this.getSpawnProtectionSize() <= 0) {
+ return false;
+ } else {
+ ChunkCoordinates var6 = par1World.getSpawnPoint();
+ int var7 = MathHelper.abs_int(par2 - var6.posX);
+ int var8 = MathHelper.abs_int(par4 - var6.posZ);
+ int var9 = Math.max(var7, var8);
+ return var9 <= this.getSpawnProtectionSize();
+ }
+ }
+
+ public ILogAgent getLogAgent() {
+ return this.field_98131_l;
+ }
+
+ public ServerConfigurationManager getConfigurationManager() {
+ return this.getDedicatedPlayerList();
+ }
+}
diff --git a/sp-server/src_aux/RegionFile.java b/sp-server/src_aux/RegionFile.java
new file mode 100644
index 0000000..bb4ff9a
--- /dev/null
+++ b/sp-server/src_aux/RegionFile.java
@@ -0,0 +1,284 @@
+package net.minecraft.src;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.util.ArrayList;
+import java.util.zip.DeflaterOutputStream;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.InflaterInputStream;
+
+public class RegionFile {
+ private static final byte[] emptySector = new byte[4096];
+ private final File fileName;
+ private RandomAccessFile dataFile;
+ private final int[] offsets = new int[1024];
+ private final int[] chunkTimestamps = new int[1024];
+ private ArrayList sectorFree;
+
+ /** McRegion sizeDelta */
+ private int sizeDelta;
+ private long lastModified = 0L;
+
+ public RegionFile(File par1File) {
+ this.fileName = par1File;
+ this.sizeDelta = 0;
+
+ try {
+ if (par1File.exists()) {
+ this.lastModified = par1File.lastModified();
+ }
+
+ this.dataFile = new RandomAccessFile(par1File, "rw");
+ int var2;
+
+ if (this.dataFile.length() < 4096L) {
+ for (var2 = 0; var2 < 1024; ++var2) {
+ this.dataFile.writeInt(0);
+ }
+
+ for (var2 = 0; var2 < 1024; ++var2) {
+ this.dataFile.writeInt(0);
+ }
+
+ this.sizeDelta += 8192;
+ }
+
+ if ((this.dataFile.length() & 4095L) != 0L) {
+ for (var2 = 0; (long) var2 < (this.dataFile.length() & 4095L); ++var2) {
+ this.dataFile.write(0);
+ }
+ }
+
+ var2 = (int) this.dataFile.length() / 4096;
+ this.sectorFree = new ArrayList(var2);
+ int var3;
+
+ for (var3 = 0; var3 < var2; ++var3) {
+ this.sectorFree.add(Boolean.valueOf(true));
+ }
+
+ this.sectorFree.set(0, Boolean.valueOf(false));
+ this.sectorFree.set(1, Boolean.valueOf(false));
+ this.dataFile.seek(0L);
+ int var4;
+
+ for (var3 = 0; var3 < 1024; ++var3) {
+ var4 = this.dataFile.readInt();
+ this.offsets[var3] = var4;
+
+ if (var4 != 0 && (var4 >> 8) + (var4 & 255) <= this.sectorFree.size()) {
+ for (int var5 = 0; var5 < (var4 & 255); ++var5) {
+ this.sectorFree.set((var4 >> 8) + var5, Boolean.valueOf(false));
+ }
+ }
+ }
+
+ for (var3 = 0; var3 < 1024; ++var3) {
+ var4 = this.dataFile.readInt();
+ this.chunkTimestamps[var3] = var4;
+ }
+ } catch (IOException var6) {
+ var6.printStackTrace();
+ }
+ }
+
+ /**
+ * args: x, y - get uncompressed chunk stream from the region file
+ */
+ public synchronized DataInputStream getChunkDataInputStream(int par1, int par2) {
+ if (this.outOfBounds(par1, par2)) {
+ return null;
+ } else {
+ try {
+ int var3 = this.getOffset(par1, par2);
+
+ if (var3 == 0) {
+ return null;
+ } else {
+ int var4 = var3 >> 8;
+ int var5 = var3 & 255;
+
+ if (var4 + var5 > this.sectorFree.size()) {
+ return null;
+ } else {
+ this.dataFile.seek((long) (var4 * 4096));
+ int var6 = this.dataFile.readInt();
+
+ if (var6 > 4096 * var5) {
+ return null;
+ } else if (var6 <= 0) {
+ return null;
+ } else {
+ byte var7 = this.dataFile.readByte();
+ byte[] var8;
+
+ if (var7 == 1) {
+ var8 = new byte[var6 - 1];
+ this.dataFile.read(var8);
+ return new DataInputStream(
+ new BufferedInputStream(new GZIPInputStream(new ByteArrayInputStream(var8))));
+ } else if (var7 == 2) {
+ var8 = new byte[var6 - 1];
+ this.dataFile.read(var8);
+ return new DataInputStream(new BufferedInputStream(
+ new InflaterInputStream(new ByteArrayInputStream(var8))));
+ } else {
+ return null;
+ }
+ }
+ }
+ }
+ } catch (IOException var9) {
+ return null;
+ }
+ }
+ }
+
+ /**
+ * args: x, z - get an output stream used to write chunk data, data is on disk
+ * when the returned stream is closed
+ */
+ public DataOutputStream getChunkDataOutputStream(int par1, int par2) {
+ return this.outOfBounds(par1, par2) ? null
+ : new DataOutputStream(new DeflaterOutputStream(new RegionFileChunkBuffer(this, par1, par2)));
+ }
+
+ /**
+ * args: x, z, data, length - write chunk data at (x, z) to disk
+ */
+ protected synchronized void write(int par1, int par2, byte[] par3ArrayOfByte, int par4) {
+ try {
+ int var5 = this.getOffset(par1, par2);
+ int var6 = var5 >> 8;
+ int var7 = var5 & 255;
+ int var8 = (par4 + 5) / 4096 + 1;
+
+ if (var8 >= 256) {
+ return;
+ }
+
+ if (var6 != 0 && var7 == var8) {
+ this.write(var6, par3ArrayOfByte, par4);
+ } else {
+ int var9;
+
+ for (var9 = 0; var9 < var7; ++var9) {
+ this.sectorFree.set(var6 + var9, Boolean.valueOf(true));
+ }
+
+ var9 = this.sectorFree.indexOf(Boolean.valueOf(true));
+ int var10 = 0;
+ int var11;
+
+ if (var9 != -1) {
+ for (var11 = var9; var11 < this.sectorFree.size(); ++var11) {
+ if (var10 != 0) {
+ if (((Boolean) this.sectorFree.get(var11)).booleanValue()) {
+ ++var10;
+ } else {
+ var10 = 0;
+ }
+ } else if (((Boolean) this.sectorFree.get(var11)).booleanValue()) {
+ var9 = var11;
+ var10 = 1;
+ }
+
+ if (var10 >= var8) {
+ break;
+ }
+ }
+ }
+
+ if (var10 >= var8) {
+ var6 = var9;
+ this.setOffset(par1, par2, var9 << 8 | var8);
+
+ for (var11 = 0; var11 < var8; ++var11) {
+ this.sectorFree.set(var6 + var11, Boolean.valueOf(false));
+ }
+
+ this.write(var6, par3ArrayOfByte, par4);
+ } else {
+ this.dataFile.seek(this.dataFile.length());
+ var6 = this.sectorFree.size();
+
+ for (var11 = 0; var11 < var8; ++var11) {
+ this.dataFile.write(emptySector);
+ this.sectorFree.add(Boolean.valueOf(false));
+ }
+
+ this.sizeDelta += 4096 * var8;
+ this.write(var6, par3ArrayOfByte, par4);
+ this.setOffset(par1, par2, var6 << 8 | var8);
+ }
+ }
+
+ this.setChunkTimestamp(par1, par2, (int) (System.currentTimeMillis() / 1000L));
+ } catch (IOException var12) {
+ var12.printStackTrace();
+ }
+ }
+
+ /**
+ * args: sectorNumber, data, length - write the chunk data to this RegionFile
+ */
+ private void write(int par1, byte[] par2ArrayOfByte, int par3) throws IOException {
+ this.dataFile.seek((long) (par1 * 4096));
+ this.dataFile.writeInt(par3 + 1);
+ this.dataFile.writeByte(2);
+ this.dataFile.write(par2ArrayOfByte, 0, par3);
+ }
+
+ /**
+ * args: x, z - check region bounds
+ */
+ private boolean outOfBounds(int par1, int par2) {
+ return par1 < 0 || par1 >= 32 || par2 < 0 || par2 >= 32;
+ }
+
+ /**
+ * args: x, y - get chunk's offset in region file
+ */
+ private int getOffset(int par1, int par2) {
+ return this.offsets[par1 + par2 * 32];
+ }
+
+ /**
+ * args: x, z, - true if chunk has been saved / converted
+ */
+ public boolean isChunkSaved(int par1, int par2) {
+ return this.getOffset(par1, par2) != 0;
+ }
+
+ /**
+ * args: x, z, offset - sets the chunk's offset in the region file
+ */
+ private void setOffset(int par1, int par2, int par3) throws IOException {
+ this.offsets[par1 + par2 * 32] = par3;
+ this.dataFile.seek((long) ((par1 + par2 * 32) * 4));
+ this.dataFile.writeInt(par3);
+ }
+
+ /**
+ * args: x, z, timestamp - sets the chunk's write timestamp
+ */
+ private void setChunkTimestamp(int par1, int par2, int par3) throws IOException {
+ this.chunkTimestamps[par1 + par2 * 32] = par3;
+ this.dataFile.seek((long) (4096 + (par1 + par2 * 32) * 4));
+ this.dataFile.writeInt(par3);
+ }
+
+ /**
+ * close this RegionFile and prevent further writes
+ */
+ public void close() throws IOException {
+ if (this.dataFile != null) {
+ this.dataFile.close();
+ }
+ }
+}
diff --git a/sp-server/src_aux/RegionFileCache.java b/sp-server/src_aux/RegionFileCache.java
new file mode 100644
index 0000000..9d67f19
--- /dev/null
+++ b/sp-server/src_aux/RegionFileCache.java
@@ -0,0 +1,75 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+public class RegionFileCache {
+ /** A map containing Files as keys and RegionFiles as values */
+ private static final Map regionsByFilename = new HashMap();
+
+ public static synchronized RegionFile createOrLoadRegionFile(File par0File, int par1, int par2) {
+ File var3 = new File(par0File, "region");
+ File var4 = new File(var3, "r." + (par1 >> 5) + "." + (par2 >> 5) + ".mca");
+ RegionFile var5 = (RegionFile) regionsByFilename.get(var4);
+
+ if (var5 != null) {
+ return var5;
+ } else {
+ if (!var3.exists()) {
+ var3.mkdirs();
+ }
+
+ if (regionsByFilename.size() >= 256) {
+ clearRegionFileReferences();
+ }
+
+ RegionFile var6 = new RegionFile(var4);
+ regionsByFilename.put(var4, var6);
+ return var6;
+ }
+ }
+
+ /**
+ * clears region file references
+ */
+ public static synchronized void clearRegionFileReferences() {
+ Iterator var0 = regionsByFilename.values().iterator();
+
+ while (var0.hasNext()) {
+ RegionFile var1 = (RegionFile) var0.next();
+
+ try {
+ if (var1 != null) {
+ var1.close();
+ }
+ } catch (IOException var3) {
+ var3.printStackTrace();
+ }
+ }
+
+ regionsByFilename.clear();
+ }
+
+ /**
+ * Returns an input stream for the specified chunk. Args: worldDir, chunkX,
+ * chunkZ
+ */
+ public static DataInputStream getChunkInputStream(File par0File, int par1, int par2) {
+ RegionFile var3 = createOrLoadRegionFile(par0File, par1, par2);
+ return var3.getChunkDataInputStream(par1 & 31, par2 & 31);
+ }
+
+ /**
+ * Returns an output stream for the specified chunk. Args: worldDir, chunkX,
+ * chunkZ
+ */
+ public static DataOutputStream getChunkOutputStream(File par0File, int par1, int par2) {
+ RegionFile var3 = createOrLoadRegionFile(par0File, par1, par2);
+ return var3.getChunkDataOutputStream(par1 & 31, par2 & 31);
+ }
+}
diff --git a/sp-server/src_aux/RegionFileChunkBuffer.java b/sp-server/src_aux/RegionFileChunkBuffer.java
new file mode 100644
index 0000000..c14f2d3
--- /dev/null
+++ b/sp-server/src_aux/RegionFileChunkBuffer.java
@@ -0,0 +1,22 @@
+package net.minecraft.src;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+class RegionFileChunkBuffer extends ByteArrayOutputStream {
+ private int chunkX;
+ private int chunkZ;
+
+ final RegionFile regionFile;
+
+ public RegionFileChunkBuffer(RegionFile par1RegionFile, int par2, int par3) {
+ super(8096);
+ this.regionFile = par1RegionFile;
+ this.chunkX = par2;
+ this.chunkZ = par3;
+ }
+
+ public void close() throws IOException {
+ this.regionFile.write(this.chunkX, this.chunkZ, this.buf, this.count);
+ }
+}
diff --git a/sp-server/src_aux/SaveFormatOld.java b/sp-server/src_aux/SaveFormatOld.java
new file mode 100644
index 0000000..ac883f6
--- /dev/null
+++ b/sp-server/src_aux/SaveFormatOld.java
@@ -0,0 +1,141 @@
+package net.minecraft.src;
+
+import java.io.File;
+import java.io.FileInputStream;
+
+public class SaveFormatOld implements ISaveFormat {
+ /**
+ * Reference to the File object representing the directory for the world saves
+ */
+ protected final File savesDirectory;
+
+ public SaveFormatOld(File par1File) {
+ if (!par1File.exists()) {
+ par1File.mkdirs();
+ }
+
+ this.savesDirectory = par1File;
+ }
+
+ public void flushCache() {
+ }
+
+ /**
+ * gets the world info
+ */
+ public WorldInfo getWorldInfo(String par1Str) {
+ File var2 = new File(this.savesDirectory, par1Str);
+
+ if (!var2.exists()) {
+ return null;
+ } else {
+ File var3 = new File(var2, "level.dat");
+ NBTTagCompound var4;
+ NBTTagCompound var5;
+
+ if (var3.exists()) {
+ try {
+ var4 = CompressedStreamTools.readCompressed(new FileInputStream(var3));
+ var5 = var4.getCompoundTag("Data");
+ return new WorldInfo(var5);
+ } catch (Exception var7) {
+ var7.printStackTrace();
+ }
+ }
+
+ var3 = new File(var2, "level.dat_old");
+
+ if (var3.exists()) {
+ try {
+ var4 = CompressedStreamTools.readCompressed(new FileInputStream(var3));
+ var5 = var4.getCompoundTag("Data");
+ return new WorldInfo(var5);
+ } catch (Exception var6) {
+ var6.printStackTrace();
+ }
+ }
+
+ return null;
+ }
+ }
+
+ /**
+ * @args: Takes one argument - the name of the directory of the world to
+ * delete. @desc: Delete the world by deleting the associated directory
+ * recursively.
+ */
+ public boolean deleteWorldDirectory(String par1Str) {
+ File var2 = new File(this.savesDirectory, par1Str);
+
+ if (!var2.exists()) {
+ return true;
+ } else {
+ System.out.println("Deleting level " + par1Str);
+
+ for (int var3 = 1; var3 <= 5; ++var3) {
+ System.out.println("Attempt " + var3 + "...");
+
+ if (deleteFiles(var2.listFiles())) {
+ break;
+ }
+
+ System.out.println("Unsuccessful in deleting contents.");
+
+ if (var3 < 5) {
+ try {
+ Thread.sleep(500L);
+ } catch (InterruptedException var5) {
+ ;
+ }
+ }
+ }
+
+ return var2.delete();
+ }
+ }
+
+ /**
+ * @args: Takes one argument - the list of files and directories to
+ * delete. @desc: Deletes the files and directory listed in the list
+ * recursively.
+ */
+ protected static boolean deleteFiles(File[] par0ArrayOfFile) {
+ for (int var1 = 0; var1 < par0ArrayOfFile.length; ++var1) {
+ File var2 = par0ArrayOfFile[var1];
+ System.out.println("Deleting " + var2);
+
+ if (var2.isDirectory() && !deleteFiles(var2.listFiles())) {
+ System.out.println("Couldn\'t delete directory " + var2);
+ return false;
+ }
+
+ if (!var2.delete()) {
+ System.out.println("Couldn\'t delete file " + var2);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns back a loader for the specified save directory
+ */
+ public ISaveHandler getSaveLoader(String par1Str, boolean par2) {
+ return new SaveHandler(this.savesDirectory, par1Str, par2);
+ }
+
+ /**
+ * gets if the map is old chunk saving (true) or McRegion (false)
+ */
+ public boolean isOldMapFormat(String par1Str) {
+ return false;
+ }
+
+ /**
+ * converts the map to mcRegion
+ */
+ public boolean convertMapFormat(String par1Str, IProgressUpdate par2IProgressUpdate) {
+ return false;
+ }
+}
diff --git a/sp-server/src_aux/SaveHandler.java b/sp-server/src_aux/SaveHandler.java
new file mode 100644
index 0000000..6240892
--- /dev/null
+++ b/sp-server/src_aux/SaveHandler.java
@@ -0,0 +1,287 @@
+package net.minecraft.src;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import net.minecraft.server.MinecraftServer;
+
+public class SaveHandler implements ISaveHandler, IPlayerFileData {
+ /** The directory in which to save world data. */
+ private final File worldDirectory;
+
+ /** The directory in which to save player data. */
+ private final File playersDirectory;
+ private final File mapDataDir;
+
+ /**
+ * The time in milliseconds when this field was initialized. Stored in the
+ * session lock file.
+ */
+ private final long initializationTime = System.currentTimeMillis();
+
+ /** The directory name of the world */
+ private final String saveDirectoryName;
+
+ public SaveHandler(File par1File, String par2Str, boolean par3) {
+ this.worldDirectory = new File(par1File, par2Str);
+ this.worldDirectory.mkdirs();
+ this.playersDirectory = new File(this.worldDirectory, "players");
+ this.mapDataDir = new File(this.worldDirectory, "data");
+ this.mapDataDir.mkdirs();
+ this.saveDirectoryName = par2Str;
+
+ if (par3) {
+ this.playersDirectory.mkdirs();
+ }
+
+ this.setSessionLock();
+ }
+
+ /**
+ * Creates a session lock file for this process
+ */
+ private void setSessionLock() {
+ try {
+ File var1 = new File(this.worldDirectory, "session.lock");
+ DataOutputStream var2 = new DataOutputStream(new FileOutputStream(var1));
+
+ try {
+ var2.writeLong(this.initializationTime);
+ } finally {
+ var2.close();
+ }
+ } catch (IOException var7) {
+ var7.printStackTrace();
+ throw new RuntimeException("Failed to check session lock, aborting");
+ }
+ }
+
+ /**
+ * Gets the File object corresponding to the base directory of this world.
+ */
+ protected File getWorldDirectory() {
+ return this.worldDirectory;
+ }
+
+ /**
+ * Checks the session lock to prevent save collisions
+ */
+ public void checkSessionLock() throws MinecraftException {
+ try {
+ File var1 = new File(this.worldDirectory, "session.lock");
+ DataInputStream var2 = new DataInputStream(new FileInputStream(var1));
+
+ try {
+ if (var2.readLong() != this.initializationTime) {
+ throw new MinecraftException("The save is being accessed from another location, aborting");
+ }
+ } finally {
+ var2.close();
+ }
+ } catch (IOException var7) {
+ throw new MinecraftException("Failed to check session lock, aborting");
+ }
+ }
+
+ /**
+ * initializes and returns the chunk loader for the specified world provider
+ */
+ public IChunkLoader getChunkLoader(WorldProvider par1WorldProvider) {
+ throw new RuntimeException("Old Chunk Storage is no longer supported.");
+ }
+
+ /**
+ * Loads and returns the world info
+ */
+ public WorldInfo loadWorldInfo() {
+ File var1 = new File(this.worldDirectory, "level.dat");
+ NBTTagCompound var2;
+ NBTTagCompound var3;
+
+ if (var1.exists()) {
+ try {
+ var2 = CompressedStreamTools.readCompressed(new FileInputStream(var1));
+ var3 = var2.getCompoundTag("Data");
+ return new WorldInfo(var3);
+ } catch (Exception var5) {
+ var5.printStackTrace();
+ }
+ }
+
+ var1 = new File(this.worldDirectory, "level.dat_old");
+
+ if (var1.exists()) {
+ try {
+ var2 = CompressedStreamTools.readCompressed(new FileInputStream(var1));
+ var3 = var2.getCompoundTag("Data");
+ return new WorldInfo(var3);
+ } catch (Exception var4) {
+ var4.printStackTrace();
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Saves the given World Info with the given NBTTagCompound as the Player.
+ */
+ public void saveWorldInfoWithPlayer(WorldInfo par1WorldInfo, NBTTagCompound par2NBTTagCompound) {
+ NBTTagCompound var3 = par1WorldInfo.cloneNBTCompound(par2NBTTagCompound);
+ NBTTagCompound var4 = new NBTTagCompound();
+ var4.setTag("Data", var3);
+
+ try {
+ File var5 = new File(this.worldDirectory, "level.dat_new");
+ File var6 = new File(this.worldDirectory, "level.dat_old");
+ File var7 = new File(this.worldDirectory, "level.dat");
+ CompressedStreamTools.writeCompressed(var4, new FileOutputStream(var5));
+
+ if (var6.exists()) {
+ var6.delete();
+ }
+
+ var7.renameTo(var6);
+
+ if (var7.exists()) {
+ var7.delete();
+ }
+
+ var5.renameTo(var7);
+
+ if (var5.exists()) {
+ var5.delete();
+ }
+ } catch (Exception var8) {
+ var8.printStackTrace();
+ }
+ }
+
+ /**
+ * used to update level.dat from old format to MCRegion format
+ */
+ public void saveWorldInfo(WorldInfo par1WorldInfo) {
+ NBTTagCompound var2 = par1WorldInfo.getNBTTagCompound();
+ NBTTagCompound var3 = new NBTTagCompound();
+ var3.setTag("Data", var2);
+
+ try {
+ File var4 = new File(this.worldDirectory, "level.dat_new");
+ File var5 = new File(this.worldDirectory, "level.dat_old");
+ File var6 = new File(this.worldDirectory, "level.dat");
+ CompressedStreamTools.writeCompressed(var3, new FileOutputStream(var4));
+
+ if (var5.exists()) {
+ var5.delete();
+ }
+
+ var6.renameTo(var5);
+
+ if (var6.exists()) {
+ var6.delete();
+ }
+
+ var4.renameTo(var6);
+
+ if (var4.exists()) {
+ var4.delete();
+ }
+ } catch (Exception var7) {
+ var7.printStackTrace();
+ }
+ }
+
+ /**
+ * Writes the player data to disk from the specified PlayerEntityMP.
+ */
+ public void writePlayerData(EntityPlayer par1EntityPlayer) {
+ try {
+ NBTTagCompound var2 = new NBTTagCompound();
+ par1EntityPlayer.writeToNBT(var2);
+ File var3 = new File(this.playersDirectory, par1EntityPlayer.username + ".dat.tmp");
+ File var4 = new File(this.playersDirectory, par1EntityPlayer.username + ".dat");
+ CompressedStreamTools.writeCompressed(var2, new FileOutputStream(var3));
+
+ if (var4.exists()) {
+ var4.delete();
+ }
+
+ var3.renameTo(var4);
+ } catch (Exception var5) {
+ MinecraftServer.getServer().getLogAgent()
+ .func_98236_b("Failed to save player data for " + par1EntityPlayer.username);
+ }
+ }
+
+ /**
+ * Reads the player data from disk into the specified PlayerEntityMP.
+ */
+ public NBTTagCompound readPlayerData(EntityPlayer par1EntityPlayer) {
+ NBTTagCompound var2 = this.getPlayerData(par1EntityPlayer.username);
+
+ if (var2 != null) {
+ par1EntityPlayer.readFromNBT(var2);
+ }
+
+ return var2;
+ }
+
+ /**
+ * Gets the player data for the given playername as a NBTTagCompound.
+ */
+ public NBTTagCompound getPlayerData(String par1Str) {
+ try {
+ File var2 = new File(this.playersDirectory, par1Str + ".dat");
+
+ if (var2.exists()) {
+ return CompressedStreamTools.readCompressed(new FileInputStream(var2));
+ }
+ } catch (Exception var3) {
+ MinecraftServer.getServer().getLogAgent().func_98236_b("Failed to load player data for " + par1Str);
+ }
+
+ return null;
+ }
+
+ public IPlayerFileData getPlayerNBTManager() {
+ return this;
+ }
+
+ /**
+ * Returns an array of usernames for which player.dat exists for.
+ */
+ public String[] getAvailablePlayerDat() {
+ String[] var1 = this.playersDirectory.list();
+
+ for (int var2 = 0; var2 < var1.length; ++var2) {
+ if (var1[var2].endsWith(".dat")) {
+ var1[var2] = var1[var2].substring(0, var1[var2].length() - 4);
+ }
+ }
+
+ return var1;
+ }
+
+ /**
+ * Called to flush all changes to disk, waiting for them to complete.
+ */
+ public void flush() {
+ }
+
+ /**
+ * Gets the file location of the given map
+ */
+ public File getMapFileFromName(String par1Str) {
+ return new File(this.mapDataDir, par1Str + ".dat");
+ }
+
+ /**
+ * Returns the name of the directory where world information is saved.
+ */
+ public String getWorldDirectoryName() {
+ return this.saveDirectoryName;
+ }
+}
diff --git a/sp-server/src_aux/ServerListenThread.java b/sp-server/src_aux/ServerListenThread.java
new file mode 100644
index 0000000..99a204b
--- /dev/null
+++ b/sp-server/src_aux/ServerListenThread.java
@@ -0,0 +1,106 @@
+package net.minecraft.src;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+
+import net.lax1dude.eaglercraft.sp.WorkerListenThread;
+
+public class ServerListenThread extends Thread {
+ private final List pendingConnections = Collections.synchronizedList(new ArrayList());
+
+ /**
+ * This map stores a list of InetAddresses and the last time which they
+ * connected at
+ */
+ private final HashMap recentConnections = new HashMap();
+ private int connectionCounter = 0;
+ private final ServerSocket myServerSocket;
+ private WorkerListenThread myNetworkListenThread;
+ private final InetAddress myServerAddress;
+ private final int myPort;
+
+ public ServerListenThread(WorkerListenThread par1NetworkListenThread, InetAddress par2InetAddress, int par3)
+ throws IOException {
+ super("Listen thread");
+ this.myNetworkListenThread = par1NetworkListenThread;
+ this.myPort = par3;
+ this.myServerSocket = new ServerSocket(par3, 0, par2InetAddress);
+ this.myServerAddress = par2InetAddress == null ? this.myServerSocket.getInetAddress() : par2InetAddress;
+ this.myServerSocket.setPerformancePreferences(0, 2, 1);
+ }
+
+ public void processPendingConnections() {
+ List var1 = this.pendingConnections;
+
+ synchronized (this.pendingConnections) {
+ for (int var2 = 0; var2 < this.pendingConnections.size(); ++var2) {
+ NetLoginHandler var3 = (NetLoginHandler) this.pendingConnections.get(var2);
+
+ try {
+ var3.tryLogin();
+ } catch (Exception var6) {
+ var3.kickUser("Internal server error");
+ this.myNetworkListenThread.getServer().getLogAgent().logWarningException(
+ "Failed to handle packet for " + var3.getUsernameAndAddress() + ": " + var6, var6);
+ }
+
+ if (var3.finishedProcessing) {
+ this.pendingConnections.remove(var2--);
+ }
+
+ var3.myTCPConnection.wakeThreads();
+ }
+ }
+ }
+
+ public void run() {
+ while (this.myNetworkListenThread.isListening) {
+ try {
+ Socket var1 = this.myServerSocket.accept();
+ NetLoginHandler var2 = new NetLoginHandler(this.myNetworkListenThread.getServer(), var1,
+ "Connection #" + this.connectionCounter++);
+ this.addPendingConnection(var2);
+ } catch (IOException var3) {
+ var3.printStackTrace();
+ }
+ }
+
+ this.myNetworkListenThread.getServer().getLogAgent().func_98233_a("Closing listening thread");
+ }
+
+ private void addPendingConnection(NetLoginHandler par1NetLoginHandler) {
+ if (par1NetLoginHandler == null) {
+ throw new IllegalArgumentException("Got null pendingconnection!");
+ } else {
+ List var2 = this.pendingConnections;
+
+ synchronized (this.pendingConnections) {
+ this.pendingConnections.add(par1NetLoginHandler);
+ }
+ }
+ }
+
+ public void func_71769_a(InetAddress par1InetAddress) {
+ if (par1InetAddress != null) {
+ HashMap var2 = this.recentConnections;
+
+ synchronized (this.recentConnections) {
+ this.recentConnections.remove(par1InetAddress);
+ }
+ }
+ }
+
+ public void func_71768_b() {
+ try {
+ this.myServerSocket.close();
+ } catch (Throwable var2) {
+ ;
+ }
+ }
+}
diff --git a/sp-server/src_aux/TcpConnection.java b/sp-server/src_aux/TcpConnection.java
new file mode 100644
index 0000000..96efe06
--- /dev/null
+++ b/sp-server/src_aux/TcpConnection.java
@@ -0,0 +1,484 @@
+package net.minecraft.src;
+
+import java.io.BufferedOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.SocketException;
+import java.security.PrivateKey;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+import javax.crypto.SecretKey;
+
+public class TcpConnection implements INetworkManager {
+ public static AtomicInteger field_74471_a = new AtomicInteger();
+ public static AtomicInteger field_74469_b = new AtomicInteger();
+
+ /** The object used for synchronization on the send queue. */
+ private final Object sendQueueLock = new Object();
+ private final ILogAgent field_98215_i;
+
+ /** The socket used by this network manager. */
+ private Socket networkSocket;
+
+ /** The InetSocketAddress of the remote endpoint */
+ private final SocketAddress remoteSocketAddress;
+
+ /** The input stream connected to the socket. */
+ private volatile DataInputStream socketInputStream;
+
+ /** The output stream connected to the socket. */
+ private volatile DataOutputStream socketOutputStream;
+
+ /** Whether the network is currently operational. */
+ private volatile boolean isRunning = true;
+
+ /**
+ * Whether this network manager is currently terminating (and should ignore
+ * further errors).
+ */
+ private volatile boolean isTerminating = false;
+
+ /**
+ * Linked list of packets that have been read and are awaiting processing.
+ */
+ private List readPackets = Collections.synchronizedList(new ArrayList());
+
+ /** Linked list of packets awaiting sending. */
+ private List dataPackets = Collections.synchronizedList(new ArrayList());
+
+ /** Linked list of packets with chunk data that are awaiting sending. */
+ private List chunkDataPackets = Collections.synchronizedList(new ArrayList());
+
+ /** A reference to the NetHandler object. */
+ private NetHandler theNetHandler;
+
+ /**
+ * Whether this server is currently terminating. If this is a client, this is
+ * always false.
+ */
+ private boolean isServerTerminating = false;
+
+ /** The thread used for writing. */
+ private Thread writeThread;
+
+ /** The thread used for reading. */
+ private Thread readThread;
+
+ /** A String indicating why the network has shutdown. */
+ private String terminationReason = "";
+ private Object[] field_74480_w;
+ private int field_74490_x = 0;
+
+ /**
+ * The length in bytes of the packets in both send queues (data and chunkData).
+ */
+ private int sendQueueByteLength = 0;
+ public static int[] field_74470_c = new int[256];
+ public static int[] field_74467_d = new int[256];
+ public int field_74468_e = 0;
+ boolean isInputBeingDecrypted = false;
+ boolean isOutputEncrypted = false;
+ private SecretKey sharedKeyForEncryption = null;
+ private PrivateKey field_74463_A = null;
+
+ /**
+ * Delay for sending pending chunk data packets (as opposed to pending non-chunk
+ * data packets)
+ */
+ private int chunkDataPacketsDelay = 50;
+
+ public TcpConnection(ILogAgent par1ILogAgent, Socket par2Socket, String par3Str, NetHandler par4NetHandler,
+ PrivateKey par5PrivateKey) throws IOException {
+ this.field_74463_A = par5PrivateKey;
+ this.networkSocket = par2Socket;
+ this.field_98215_i = par1ILogAgent;
+ this.remoteSocketAddress = par2Socket.getRemoteSocketAddress();
+ this.theNetHandler = par4NetHandler;
+
+ try {
+ par2Socket.setSoTimeout(30000);
+ par2Socket.setTrafficClass(24);
+ } catch (SocketException var7) {
+ System.err.println(var7.getMessage());
+ }
+
+ this.socketInputStream = new DataInputStream(par2Socket.getInputStream());
+ this.socketOutputStream = new DataOutputStream(new BufferedOutputStream(par2Socket.getOutputStream(), 5120));
+ this.readThread = new TcpReaderThread(this, par3Str + " read thread");
+ this.writeThread = new TcpWriterThread(this, par3Str + " write thread");
+ this.readThread.start();
+ this.writeThread.start();
+ }
+
+ /**
+ * Sets the NetHandler for this NetworkManager. Server-only.
+ */
+ public void setNetHandler(NetHandler par1NetHandler) {
+ this.theNetHandler = par1NetHandler;
+ }
+
+ /**
+ * Adds the packet to the correct send queue (chunk data packets go to a
+ * separate queue).
+ */
+ public void addToSendQueue(Packet par1Packet) {
+ if (!this.isServerTerminating) {
+ Object var2 = this.sendQueueLock;
+
+ synchronized (this.sendQueueLock) {
+ this.sendQueueByteLength += par1Packet.getPacketSize() + 1;
+ this.dataPackets.add(par1Packet);
+ }
+ }
+ }
+
+ /**
+ * Sends a data packet if there is one to send, or sends a chunk data packet if
+ * there is one and the counter is up, or does nothing.
+ */
+ private boolean sendPacket() {
+ boolean var1 = false;
+
+ try {
+ int[] var10000;
+ int var10001;
+ Packet var2;
+
+ if (this.field_74468_e == 0 || !this.dataPackets.isEmpty() && System.currentTimeMillis()
+ - ((Packet) this.dataPackets.get(0)).creationTimeMillis >= (long) this.field_74468_e) {
+ var2 = this.func_74460_a(false);
+
+ if (var2 != null) {
+ Packet.writePacket(var2, this.socketOutputStream);
+
+ if (var2 instanceof Packet252SharedKey && !this.isOutputEncrypted) {
+ if (!this.theNetHandler.isServerHandler()) {
+ this.sharedKeyForEncryption = ((Packet252SharedKey) var2).getSharedKey();
+ }
+
+ this.encryptOuputStream();
+ }
+
+ var10000 = field_74467_d;
+ var10001 = var2.getPacketId();
+ var10000[var10001] += var2.getPacketSize() + 1;
+ var1 = true;
+ }
+ }
+
+ if (this.chunkDataPacketsDelay-- <= 0 && (this.field_74468_e == 0
+ || !this.chunkDataPackets.isEmpty() && System.currentTimeMillis() - ((Packet) this.chunkDataPackets
+ .get(0)).creationTimeMillis >= (long) this.field_74468_e)) {
+ var2 = this.func_74460_a(true);
+
+ if (var2 != null) {
+ Packet.writePacket(var2, this.socketOutputStream);
+ var10000 = field_74467_d;
+ var10001 = var2.getPacketId();
+ var10000[var10001] += var2.getPacketSize() + 1;
+ this.chunkDataPacketsDelay = 0;
+ var1 = true;
+ }
+ }
+
+ return var1;
+ } catch (Exception var3) {
+ if (!this.isTerminating) {
+ this.onNetworkError(var3);
+ }
+
+ return false;
+ }
+ }
+
+ private Packet func_74460_a(boolean par1) {
+ Packet var2 = null;
+ List var3 = par1 ? this.chunkDataPackets : this.dataPackets;
+ Object var4 = this.sendQueueLock;
+
+ synchronized (this.sendQueueLock) {
+ while (!var3.isEmpty() && var2 == null) {
+ var2 = (Packet) var3.remove(0);
+ this.sendQueueByteLength -= var2.getPacketSize() + 1;
+
+ if (this.func_74454_a(var2, par1)) {
+ var2 = null;
+ }
+ }
+
+ return var2;
+ }
+ }
+
+ private boolean func_74454_a(Packet par1Packet, boolean par2) {
+ if (!par1Packet.isRealPacket()) {
+ return false;
+ } else {
+ List var3 = par2 ? this.chunkDataPackets : this.dataPackets;
+ Iterator var4 = var3.iterator();
+ Packet var5;
+
+ do {
+ if (!var4.hasNext()) {
+ return false;
+ }
+
+ var5 = (Packet) var4.next();
+ } while (var5.getPacketId() != par1Packet.getPacketId());
+
+ return par1Packet.containsSameEntityIDAs(var5);
+ }
+ }
+
+ /**
+ * Wakes reader and writer threads
+ */
+ public void wakeThreads() {
+ if (this.readThread != null) {
+ this.readThread.interrupt();
+ }
+
+ if (this.writeThread != null) {
+ this.writeThread.interrupt();
+ }
+ }
+
+ /**
+ * Reads a single packet from the input stream and adds it to the read queue. If
+ * no packet is read, it shuts down the network.
+ */
+ private boolean readPacket() {
+ boolean var1 = false;
+
+ try {
+ Packet var2 = Packet.readPacket(this.field_98215_i, this.socketInputStream,
+ this.theNetHandler.isServerHandler(), this.networkSocket);
+
+ if (var2 != null) {
+ if (var2 instanceof Packet252SharedKey && !this.isInputBeingDecrypted) {
+ if (this.theNetHandler.isServerHandler()) {
+ this.sharedKeyForEncryption = ((Packet252SharedKey) var2).getSharedKey(this.field_74463_A);
+ }
+
+ this.decryptInputStream();
+ }
+
+ int[] var10000 = field_74470_c;
+ int var10001 = var2.getPacketId();
+ var10000[var10001] += var2.getPacketSize() + 1;
+
+ if (!this.isServerTerminating) {
+ if (var2.canProcessAsync() && this.theNetHandler.canProcessPacketsAsync()) {
+ this.field_74490_x = 0;
+ var2.processPacket(this.theNetHandler);
+ } else {
+ this.readPackets.add(var2);
+ }
+ }
+
+ var1 = true;
+ } else {
+ this.networkShutdown("disconnect.endOfStream", new Object[0]);
+ }
+
+ return var1;
+ } catch (Exception var3) {
+ if (!this.isTerminating) {
+ this.onNetworkError(var3);
+ }
+
+ return false;
+ }
+ }
+
+ /**
+ * Used to report network errors and causes a network shutdown.
+ */
+ private void onNetworkError(Exception par1Exception) {
+ par1Exception.printStackTrace();
+ this.networkShutdown("disconnect.genericReason",
+ new Object[] { "Internal exception: " + par1Exception.toString() });
+ }
+
+ /**
+ * Shuts down the network with the specified reason. Closes all streams and
+ * sockets, spawns NetworkMasterThread to stop reading and writing threads.
+ */
+ public void networkShutdown(String par1Str, Object... par2ArrayOfObj) {
+ if (this.isRunning) {
+ this.isTerminating = true;
+ this.terminationReason = par1Str;
+ this.field_74480_w = par2ArrayOfObj;
+ this.isRunning = false;
+ (new TcpMasterThread(this)).start();
+
+ try {
+ this.socketInputStream.close();
+ } catch (Throwable var6) {
+ ;
+ }
+
+ try {
+ this.socketOutputStream.close();
+ } catch (Throwable var5) {
+ ;
+ }
+
+ try {
+ this.networkSocket.close();
+ } catch (Throwable var4) {
+ ;
+ }
+
+ this.socketInputStream = null;
+ this.socketOutputStream = null;
+ this.networkSocket = null;
+ }
+ }
+
+ /**
+ * Checks timeouts and processes all pending read packets.
+ */
+ public void processReadPackets() {
+ if (this.sendQueueByteLength > 2097152) {
+ this.networkShutdown("disconnect.overflow", new Object[0]);
+ }
+
+ if (this.readPackets.isEmpty()) {
+ if (this.field_74490_x++ == 1200) {
+ this.networkShutdown("disconnect.timeout", new Object[0]);
+ }
+ } else {
+ this.field_74490_x = 0;
+ }
+
+ int var1 = 1000;
+
+ while (!this.readPackets.isEmpty() && var1-- >= 0) {
+ Packet var2 = (Packet) this.readPackets.remove(0);
+ var2.processPacket(this.theNetHandler);
+ }
+
+ this.wakeThreads();
+
+ if (this.isTerminating && this.readPackets.isEmpty()) {
+ this.theNetHandler.handleErrorMessage(this.terminationReason, this.field_74480_w);
+ }
+ }
+
+ /**
+ * Returns the socket address of the remote side. Server-only.
+ */
+ public SocketAddress getRemoteAddress() {
+ return this.remoteSocketAddress;
+ }
+
+ /**
+ * Shuts down the server. (Only actually used on the server)
+ */
+ public void serverShutdown() {
+ if (!this.isServerTerminating) {
+ this.wakeThreads();
+ this.isServerTerminating = true;
+ this.readThread.interrupt();
+ (new TcpMonitorThread(this)).start();
+ }
+ }
+
+ private void decryptInputStream() throws IOException {
+ this.isInputBeingDecrypted = true;
+ InputStream var1 = this.networkSocket.getInputStream();
+ this.socketInputStream = new DataInputStream(
+ CryptManager.decryptInputStream(this.sharedKeyForEncryption, var1));
+ }
+
+ /**
+ * flushes the stream and replaces it with an encryptedOutputStream
+ */
+ private void encryptOuputStream() throws IOException {
+ this.socketOutputStream.flush();
+ this.isOutputEncrypted = true;
+ BufferedOutputStream var1 = new BufferedOutputStream(
+ CryptManager.encryptOuputStream(this.sharedKeyForEncryption, this.networkSocket.getOutputStream()),
+ 5120);
+ this.socketOutputStream = new DataOutputStream(var1);
+ }
+
+ /**
+ * Returns the number of chunk data packets waiting to be sent.
+ */
+ public int getNumChunkDataPackets() {
+ return this.chunkDataPackets.size();
+ }
+
+ public Socket getSocket() {
+ return this.networkSocket;
+ }
+
+ /**
+ * Whether the network is operational.
+ */
+ static boolean isRunning(TcpConnection par0TcpConnection) {
+ return par0TcpConnection.isRunning;
+ }
+
+ /**
+ * Is the server terminating? Client side aways returns false.
+ */
+ static boolean isServerTerminating(TcpConnection par0TcpConnection) {
+ return par0TcpConnection.isServerTerminating;
+ }
+
+ /**
+ * Static accessor to readPacket.
+ */
+ static boolean readNetworkPacket(TcpConnection par0TcpConnection) {
+ return par0TcpConnection.readPacket();
+ }
+
+ /**
+ * Static accessor to sendPacket.
+ */
+ static boolean sendNetworkPacket(TcpConnection par0TcpConnection) {
+ return par0TcpConnection.sendPacket();
+ }
+
+ static DataOutputStream getOutputStream(TcpConnection par0TcpConnection) {
+ return par0TcpConnection.socketOutputStream;
+ }
+
+ /**
+ * Gets whether the Network manager is terminating.
+ */
+ static boolean isTerminating(TcpConnection par0TcpConnection) {
+ return par0TcpConnection.isTerminating;
+ }
+
+ /**
+ * Sends the network manager an error
+ */
+ static void sendError(TcpConnection par0TcpConnection, Exception par1Exception) {
+ par0TcpConnection.onNetworkError(par1Exception);
+ }
+
+ /**
+ * Returns the read thread.
+ */
+ static Thread getReadThread(TcpConnection par0TcpConnection) {
+ return par0TcpConnection.readThread;
+ }
+
+ /**
+ * Returns the write thread.
+ */
+ static Thread getWriteThread(TcpConnection par0TcpConnection) {
+ return par0TcpConnection.writeThread;
+ }
+}
diff --git a/sp-server/src_aux/TcpMasterThread.java b/sp-server/src_aux/TcpMasterThread.java
new file mode 100644
index 0000000..4ffb658
--- /dev/null
+++ b/sp-server/src_aux/TcpMasterThread.java
@@ -0,0 +1,34 @@
+package net.minecraft.src;
+
+class TcpMasterThread extends Thread {
+ final TcpConnection theTcpConnection;
+
+ TcpMasterThread(TcpConnection par1TcpConnection) {
+ this.theTcpConnection = par1TcpConnection;
+ }
+
+ @SuppressWarnings("deprecation")
+ public void run() {
+ try {
+ Thread.sleep(5000L);
+
+ if (TcpConnection.getReadThread(this.theTcpConnection).isAlive()) {
+ try {
+ TcpConnection.getReadThread(this.theTcpConnection).stop();
+ } catch (Throwable var3) {
+ ;
+ }
+ }
+
+ if (TcpConnection.getWriteThread(this.theTcpConnection).isAlive()) {
+ try {
+ TcpConnection.getWriteThread(this.theTcpConnection).stop();
+ } catch (Throwable var2) {
+ ;
+ }
+ }
+ } catch (InterruptedException var4) {
+ var4.printStackTrace();
+ }
+ }
+}
diff --git a/sp-server/src_aux/TcpMonitorThread.java b/sp-server/src_aux/TcpMonitorThread.java
new file mode 100644
index 0000000..9b223a8
--- /dev/null
+++ b/sp-server/src_aux/TcpMonitorThread.java
@@ -0,0 +1,22 @@
+package net.minecraft.src;
+
+class TcpMonitorThread extends Thread {
+ final TcpConnection theTcpConnection;
+
+ TcpMonitorThread(TcpConnection par1TcpConnection) {
+ this.theTcpConnection = par1TcpConnection;
+ }
+
+ public void run() {
+ try {
+ Thread.sleep(2000L);
+
+ if (TcpConnection.isRunning(this.theTcpConnection)) {
+ TcpConnection.getWriteThread(this.theTcpConnection).interrupt();
+ this.theTcpConnection.networkShutdown("disconnect.closed", new Object[0]);
+ }
+ } catch (Exception var2) {
+ var2.printStackTrace();
+ }
+ }
+}
diff --git a/sp-server/src_aux/TcpReaderThread.java b/sp-server/src_aux/TcpReaderThread.java
new file mode 100644
index 0000000..f65f890
--- /dev/null
+++ b/sp-server/src_aux/TcpReaderThread.java
@@ -0,0 +1,31 @@
+package net.minecraft.src;
+
+class TcpReaderThread extends Thread {
+ final TcpConnection theTcpConnection;
+
+ TcpReaderThread(TcpConnection par1TcpConnection, String par2Str) {
+ super(par2Str);
+ this.theTcpConnection = par1TcpConnection;
+ }
+
+ public void run() {
+ TcpConnection.field_74471_a.getAndIncrement();
+
+ try {
+ while (TcpConnection.isRunning(this.theTcpConnection)
+ && !TcpConnection.isServerTerminating(this.theTcpConnection)) {
+ while (true) {
+ if (!TcpConnection.readNetworkPacket(this.theTcpConnection)) {
+ try {
+ sleep(2L);
+ } catch (InterruptedException var5) {
+ ;
+ }
+ }
+ }
+ }
+ } finally {
+ TcpConnection.field_74471_a.getAndDecrement();
+ }
+ }
+}
diff --git a/sp-server/src_aux/TcpWriterThread.java b/sp-server/src_aux/TcpWriterThread.java
new file mode 100644
index 0000000..c3bd28b
--- /dev/null
+++ b/sp-server/src_aux/TcpWriterThread.java
@@ -0,0 +1,46 @@
+package net.minecraft.src;
+
+import java.io.IOException;
+
+class TcpWriterThread extends Thread {
+ final TcpConnection theTcpConnection;
+
+ TcpWriterThread(TcpConnection par1TcpConnection, String par2Str) {
+ super(par2Str);
+ this.theTcpConnection = par1TcpConnection;
+ }
+
+ public void run() {
+ TcpConnection.field_74469_b.getAndIncrement();
+
+ try {
+ while (TcpConnection.isRunning(this.theTcpConnection)) {
+ boolean var1;
+
+ for (var1 = false; TcpConnection.sendNetworkPacket(this.theTcpConnection); var1 = true) {
+ ;
+ }
+
+ try {
+ if (var1 && TcpConnection.getOutputStream(this.theTcpConnection) != null) {
+ TcpConnection.getOutputStream(this.theTcpConnection).flush();
+ }
+ } catch (IOException var8) {
+ if (!TcpConnection.isTerminating(this.theTcpConnection)) {
+ TcpConnection.sendError(this.theTcpConnection, var8);
+ }
+
+ var8.printStackTrace();
+ }
+
+ try {
+ sleep(2L);
+ } catch (InterruptedException var7) {
+ ;
+ }
+ }
+ } finally {
+ TcpConnection.field_74469_b.getAndDecrement();
+ }
+ }
+}