mirror of
https://github.com/GTNewHorizons/bdlib.git
synced 2026-10-25 20:22:25 +00:00
Preparing for public release
This commit is contained in:
commit
9156249843
60 files changed
+2825
No files matched your search
@@ -0,0 +1,9 @@
|
||||
/.gradle
|
||||
/build
|
||||
/deps
|
||||
/eclipse
|
||||
/out
|
||||
|
||||
*.ipr
|
||||
*.iml
|
||||
*.iws
|
||||
@@ -0,0 +1,87 @@
|
||||
Minecraft Mod Public License
|
||||
============================
|
||||
|
||||
Version 1.0.1
|
||||
|
||||
0. Definitions
|
||||
--------------
|
||||
|
||||
Minecraft: Denotes a copy of the Minecraft game licensed by Mojang AB
|
||||
|
||||
User: Anybody that interacts with the software in one of the following ways:
|
||||
- play
|
||||
- decompile
|
||||
- recompile or compile
|
||||
- modify
|
||||
- distribute
|
||||
|
||||
Mod: The mod code designated by the present license, in source form, binary
|
||||
form, as obtained standalone, as part of a wider distribution or resulting from
|
||||
the compilation of the original or modified sources.
|
||||
|
||||
Dependency: Code required for the mod to work properly. This includes
|
||||
dependencies required to compile the code as well as any file or modification
|
||||
that is explicitely or implicitely required for the mod to be working.
|
||||
|
||||
1. Scope
|
||||
--------
|
||||
|
||||
The present license is granted to any user of the mod. As a prerequisite,
|
||||
a user must own a legally acquired copy of Minecraft
|
||||
|
||||
2. Liability
|
||||
------------
|
||||
|
||||
This mod is provided 'as is' with no warranties, implied or otherwise. The owner
|
||||
of this mod takes no responsibility for any damages incurred from the use of
|
||||
this mod. This mod alters fundamental parts of the Minecraft game, parts of
|
||||
Minecraft may not work with this mod installed. All damages caused from the use
|
||||
or misuse of this mad fall on the user.
|
||||
|
||||
3. Play rights
|
||||
--------------
|
||||
|
||||
The user is allowed to install this mod on a client or a server and to play
|
||||
without restriction.
|
||||
|
||||
4. Modification rights
|
||||
----------------------
|
||||
|
||||
The user has the right to decompile the source code, look at either the
|
||||
decompiled version or the original source code, and to modify it.
|
||||
|
||||
5. Derivation rights
|
||||
--------------------
|
||||
|
||||
The user has the rights to derive code from this mod, that is to say to
|
||||
write code that extends or instanciate the mod classes or interfaces, refer to
|
||||
its objects, or calls its functions. This code is known as "derived" code, and
|
||||
can be licensed under a license different from this mod.
|
||||
|
||||
6. Distribution of original or modified copy rights
|
||||
---------------------------------------------------
|
||||
|
||||
Is subject to distribution rights this entire mod in its various forms. This
|
||||
include:
|
||||
- original binary or source forms of this mod files
|
||||
- modified versions of these binaries or source files, as well as binaries
|
||||
resulting from source modifications
|
||||
- patch to its source or binary files
|
||||
- any copy of a portion of its binary source files
|
||||
|
||||
The user is allowed to redistribute this mod partially, in totality, or
|
||||
included in a distribution.
|
||||
|
||||
When distributing binary files, the user must provide means to obtain its
|
||||
entire set of sources or modified sources at no costs.
|
||||
|
||||
All distributions of this mod must remain licensed under the MMPL.
|
||||
|
||||
All dependencies that this mod have on other mods or classes must be licensed
|
||||
under conditions comparable to this version of MMPL, with the exception of the
|
||||
Minecraft code and the mod loading framework (e.g. ModLoader, ModLoaderMP or
|
||||
Bukkit).
|
||||
|
||||
Modified version of binaries and sources, as well as files containing sections
|
||||
copied from this mod, should be distributed under the terms of the present
|
||||
license.
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven {
|
||||
name = "bdew"
|
||||
url = "http://jenkins.bdew.net/maven"
|
||||
}
|
||||
maven {
|
||||
name = "forge"
|
||||
url = "http://files.minecraftforge.net/maven"
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
classpath 'net.minecraftforge.gradle:ForgeGradle:1.0-SNAPSHOT'
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'forge'
|
||||
apply plugin: 'scala'
|
||||
|
||||
version = "0.9.0"
|
||||
|
||||
if (project.hasProperty('buildnum')) {
|
||||
project.version = project.version + '.' + project.buildnum
|
||||
} else {
|
||||
project.version = project.version + '-dev'
|
||||
}
|
||||
|
||||
group = "net.bdew"
|
||||
archivesBaseName = "bdlib"
|
||||
|
||||
minecraft {
|
||||
version = "1.6.4-9.11.1.964"
|
||||
}
|
||||
|
||||
import org.apache.tools.ant.filters.ReplaceTokens
|
||||
|
||||
def myTokens = [BdLibVer: project.version]
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
scala {
|
||||
srcDir 'src'
|
||||
}
|
||||
resources {
|
||||
srcDir 'resources'
|
||||
}
|
||||
}
|
||||
processed {
|
||||
scala {
|
||||
srcDir 'build/stage'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
task stage(type: Sync) {
|
||||
from sourceSets.main.scala
|
||||
into 'build/stage'
|
||||
filter(ReplaceTokens, tokens: myTokens)
|
||||
}
|
||||
|
||||
compileScala {
|
||||
source = sourceSets.processed.scala
|
||||
dependsOn stage
|
||||
}
|
||||
|
||||
processResources {
|
||||
from(sourceSets.main.resources.srcDirs) {
|
||||
include 'mcmod.info'
|
||||
filter(ReplaceTokens, tokens: myTokens)
|
||||
}
|
||||
|
||||
from(sourceSets.main.resources.srcDirs) {
|
||||
exclude 'mcmod.info'
|
||||
}
|
||||
}
|
||||
|
||||
task sourceJar(type: Jar) {
|
||||
from sourceSets.main.allSource
|
||||
}
|
||||
|
||||
task deobfJar(type: Jar) {
|
||||
from sourceSets.main.output
|
||||
}
|
||||
|
||||
jar {
|
||||
appendix = 'universal'
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives sourceJar
|
||||
archives deobfJar
|
||||
}
|
||||
|
||||
apply plugin: 'maven-publish'
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
maven(MavenPublication) {
|
||||
artifact deobfJar
|
||||
|
||||
artifact sourceJar {
|
||||
classifier "sources"
|
||||
}
|
||||
}
|
||||
}
|
||||
repositories {
|
||||
maven {
|
||||
url "file://var/www/maven"
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
BIN
Binary file not shown.
+6
@@ -0,0 +1,6 @@
|
||||
#Thu Nov 28 11:30:59 IST 2013
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=http\://services.gradle.org/distributions/gradle-1.9-bin.zip
|
||||
@@ -0,0 +1,164 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# 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
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
esac
|
||||
|
||||
# For Cygwin, ensure paths are in UNIX format before anything is touched.
|
||||
if $cygwin ; then
|
||||
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
||||
fi
|
||||
|
||||
# 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\"`/" >&-
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >&-
|
||||
|
||||
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" ] ; 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, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
|
||||
# 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=$((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
|
||||
|
||||
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
|
||||
function splitJvmOpts() {
|
||||
JVM_OPTS=("$@")
|
||||
}
|
||||
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
||||
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
||||
|
||||
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
||||
Vendored
+90
@@ -0,0 +1,90 @@
|
||||
@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
|
||||
|
||||
@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=
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@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 init
|
||||
|
||||
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 init
|
||||
|
||||
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
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windowz variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
if "%@eval[2+2]" == "4" goto 4NT_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
goto execute
|
||||
|
||||
:4NT_args
|
||||
@rem Get arguments from the 4NT Shell from JP Software
|
||||
set CMD_LINE_ARGS=%$
|
||||
|
||||
: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 %CMD_LINE_ARGS%
|
||||
|
||||
: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
|
||||
@@ -0,0 +1,20 @@
|
||||
[
|
||||
{
|
||||
"modid": "bdlib",
|
||||
"name": "BD Lib",
|
||||
"description": "",
|
||||
"version": "@BdLibVer@",
|
||||
"url": "bdew.net/mods/",
|
||||
"updateUrl": "",
|
||||
"authorList": [
|
||||
"bdew"
|
||||
],
|
||||
"credits": "",
|
||||
"logoFile": "",
|
||||
"screenshots": [
|
||||
],
|
||||
"parent":"",
|
||||
"dependencies": [
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,11 @@
|
||||
package net.bdew.lib
|
||||
|
||||
import cpw.mods.fml.common.Mod
|
||||
import cpw.mods.fml.common.event.FMLPreInitializationEvent
|
||||
|
||||
@Mod(modid = "bdlib", version = "@BdLibVer@", modLanguage = "scala")
|
||||
object BdLib {
|
||||
def preInit(ev: FMLPreInitializationEvent) {
|
||||
ev.getModLog.info("bdlib @BdLibVer@ loaded")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib
|
||||
|
||||
class EventBase[T] extends {
|
||||
var listeners = Seq.empty[T]
|
||||
def listen(x: T) = listeners :+= x
|
||||
def hasListeners = listeners.size > 0
|
||||
}
|
||||
|
||||
class Event0 extends EventBase[() => Unit] {
|
||||
def trigger() = for (x <- listeners) x()
|
||||
}
|
||||
|
||||
class Event1[T] extends EventBase[(T) => Unit] {
|
||||
def trigger(p1: T) = for (x <- listeners) x(p1)
|
||||
}
|
||||
|
||||
class Event2[T, R] extends EventBase[(T, R) => Unit] {
|
||||
def trigger(p1: T, p2: R) = for (x <- listeners) x(p1, p2)
|
||||
}
|
||||
|
||||
object Event {
|
||||
def apply(t: Unit) = new Event0
|
||||
def apply[T] = new Event1[T]
|
||||
def apply[T, R] = new Event2[T, R]
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib
|
||||
|
||||
import cpw.mods.fml.common.registry.GameRegistry
|
||||
import net.minecraft.nbt.{NBTTagCompound, NBTTagList}
|
||||
import net.minecraft.util.StatCollector
|
||||
import net.minecraft.item.ItemStack
|
||||
import cpw.mods.fml.common.versioning.{ArtifactVersion, VersionParser}
|
||||
import cpw.mods.fml.common.Loader
|
||||
import net.minecraftforge.oredict.ShapedOreRecipe
|
||||
|
||||
object Misc {
|
||||
def iterNbtList[X](list: NBTTagList) =
|
||||
for (i <- 0 until list.tagCount()) yield list.tagAt(i).asInstanceOf[X]
|
||||
|
||||
def toLocal(s: String) = StatCollector.translateToLocal(s)
|
||||
def toLocalF(s: String, params: Any*) = StatCollector.translateToLocal(s).format(params: _*)
|
||||
|
||||
def flattenRecipe(pattern: Seq[String], items: Map[Char, AnyRef]) =
|
||||
pattern ++ items.map {
|
||||
case (k, v) => Seq(new Character(k), v)
|
||||
}.flatten
|
||||
|
||||
def wrapTag(n: String, f: (NBTTagCompound) => Any)(t: NBTTagCompound) {
|
||||
val p = t.getCompoundTag(n)
|
||||
f(p)
|
||||
t.setCompoundTag(n, p)
|
||||
}
|
||||
|
||||
def addRecipe(result: ItemStack, pattern: Seq[String], items: Map[Char, AnyRef]) =
|
||||
GameRegistry.addRecipe(result, flattenRecipe(pattern, items): _*)
|
||||
|
||||
def addRecipeOD(result: ItemStack, pattern: Seq[String], items: Map[Char, AnyRef]) =
|
||||
GameRegistry.addRecipe(new ShapedOreRecipe(result, flattenRecipe(pattern, items): _*))
|
||||
|
||||
def min[T](vals: T*)(implicit o: Ordering[T]): T = vals.min(o)
|
||||
def max[T](vals: T*)(implicit o: Ordering[T]): T = vals.max(o)
|
||||
|
||||
def clamp[T](value: T, min: T, max: T)(implicit o: Ordering[T]): T = if (o.gt(value,max)) max else if (o.lt(value,min)) min else value
|
||||
|
||||
def iterSome[T](list: Seq[T], indexes: Iterable[Int]): Iterable[T] = for (i <- indexes) yield list(i)
|
||||
def iterSomeEnum[T](list: Seq[T], indexes: Iterable[Int]): Iterable[(Int, T)] = for (i <- indexes) yield i -> list(i)
|
||||
|
||||
def filterType[T](from: Iterable[_], cls: Class[T]) = from.filter(cls.isInstance).asInstanceOf[Iterable[T]]
|
||||
|
||||
def haveModVersion(spec: String): Boolean = {
|
||||
val req = VersionParser.parseVersionReference(spec)
|
||||
val modid = req.getLabel
|
||||
|
||||
if (!Loader.instance.getIndexedModList.containsKey(modid)) return false
|
||||
|
||||
val found: ArtifactVersion = Loader.instance.getIndexedModList.get(modid).getProcessedVersion
|
||||
|
||||
if (found == null || !req.containsVersion(found)) return false
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.block
|
||||
|
||||
import net.minecraft.block.{ITileEntityProvider, Block}
|
||||
import net.minecraft.world.{IBlockAccess, World}
|
||||
import net.minecraft.tileentity.TileEntity
|
||||
import cpw.mods.fml.common.FMLCommonHandler
|
||||
|
||||
trait HasTE[T] extends Block with ITileEntityProvider {
|
||||
val TEClass: Class[_ <: TileEntity]
|
||||
def createNewTileEntity(world: World): TileEntity = TEClass.newInstance()
|
||||
def getTE(w: IBlockAccess, x: Int, y: Int, z: Int): T = {
|
||||
var t = w.getBlockTileEntity(x, y, z)
|
||||
if ((t == null) || !TEClass.isInstance(t)) {
|
||||
FMLCommonHandler.instance().getFMLLogger.severe("Tile entity for block %s at (%d,%d,%d) is corrupt or missing - recreating".format(this, x, y, z))
|
||||
w match {
|
||||
case ww: World =>
|
||||
t = createNewTileEntity(ww)
|
||||
ww.setBlockTileEntity(x, y, z, t)
|
||||
case _ =>
|
||||
sys.error("Unable to recreate TE")
|
||||
}
|
||||
}
|
||||
return t.asInstanceOf[T]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.data
|
||||
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
import net.bdew.lib.data.base.{UpdateKind, TileDataSlots, DataSlotVal}
|
||||
|
||||
case class DataSlotBoolean(name: String, parent: TileDataSlots, default: Boolean = false) extends DataSlotVal[Boolean] {
|
||||
var cval = default
|
||||
def save(t: NBTTagCompound, kind: UpdateKind.Value) = t.setBoolean(name, cval)
|
||||
def load(t: NBTTagCompound, kind: UpdateKind.Value) = cval = t.getBoolean(name)
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.data
|
||||
|
||||
import net.bdew.lib.data.base.{TileDataSlots, UpdateKind, DataSlotVal}
|
||||
import net.minecraftforge.common.ForgeDirection
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
|
||||
case class DataSlotDirection(name: String, parent: TileDataSlots) extends DataSlotVal[ForgeDirection] {
|
||||
var cval = ForgeDirection.UP
|
||||
def save(t: NBTTagCompound, kind: UpdateKind.Value) = t.setByte(name, cval.ordinal().toByte)
|
||||
def load(t: NBTTagCompound, kind: UpdateKind.Value) = cval = ForgeDirection.getOrientation(t.getByte(name))
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.data
|
||||
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
import net.bdew.lib.data.base.{UpdateKind, TileDataSlots, DataSlotNumeric}
|
||||
|
||||
case class DataSlotFloat(name: String, parent: TileDataSlots, default: Float = 0) extends DataSlotNumeric[Float](default) {
|
||||
def save(t: NBTTagCompound, kind: UpdateKind.Value) = t.setFloat(name, cval)
|
||||
def load(t: NBTTagCompound, kind: UpdateKind.Value) = cval = t.getFloat(name)
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.data
|
||||
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
import net.bdew.lib.data.base.{UpdateKind, TileDataSlots, DataSlotNumeric}
|
||||
|
||||
case class DataSlotInt(name: String, parent: TileDataSlots, default: Int = 0) extends DataSlotNumeric[Int](default) {
|
||||
def save(t: NBTTagCompound, kind: UpdateKind.Value) = t.setInteger(name, cval)
|
||||
def load(t: NBTTagCompound, kind: UpdateKind.Value) = cval = t.getInteger(name)
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.data
|
||||
|
||||
import net.bdew.lib.data.base.{TileDataSlots, UpdateKind, DataSlotVal}
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
import net.minecraft.item.ItemStack
|
||||
|
||||
case class DataSlotItemStack(name: String, parent: TileDataSlots) extends DataSlotVal[ItemStack] {
|
||||
var cval: ItemStack = null
|
||||
|
||||
override def update(v: ItemStack) = {
|
||||
if (!ItemStack.areItemStacksEqual(v, cval)) {
|
||||
cval = if (v == null) null else v.copy()
|
||||
parent.dataSlotChanged(this)
|
||||
}
|
||||
}
|
||||
|
||||
def save(t: NBTTagCompound, kind: UpdateKind.Value) = {
|
||||
val tag = new NBTTagCompound()
|
||||
if (cval != null) cval.writeToNBT(tag)
|
||||
t.setCompoundTag(name, tag)
|
||||
}
|
||||
def load(t: NBTTagCompound, kind: UpdateKind.Value) = cval = ItemStack.loadItemStackFromNBT(t.getCompoundTag(name))
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.data
|
||||
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
import net.bdew.lib.data.base.{UpdateKind, TileDataSlots, DataSlotVal}
|
||||
|
||||
case class DataSlotString(name: String, parent: TileDataSlots, default: String = null) extends DataSlotVal[String] {
|
||||
var cval: String = default
|
||||
def save(t: NBTTagCompound, kind: UpdateKind.Value) = if (cval != null) t.setString(name, cval)
|
||||
def load(t: NBTTagCompound, kind: UpdateKind.Value) = cval = if (t.hasKey(name)) t.getString(name) else null
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.data
|
||||
|
||||
import net.minecraftforge.fluids.{IFluidTank, FluidTank, FluidStack}
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
import net.bdew.lib.data.base.{UpdateKind, TileDataSlots, DataSlot}
|
||||
|
||||
abstract class DataSlotTankBase(sz: Int) extends FluidTank(sz) with IFluidTank with DataSlot {
|
||||
var oldStack: FluidStack = null
|
||||
var size: Int
|
||||
|
||||
parent.serverTick.listen(checkUpdate)
|
||||
|
||||
updateKind = Set(UpdateKind.GUI, UpdateKind.SAVE)
|
||||
|
||||
def checkUpdate() {
|
||||
if (!isSame(oldStack, fluid)) {
|
||||
oldStack = if (fluid == null) null else fluid.copy()
|
||||
parent.dataSlotChanged(this)
|
||||
}
|
||||
}
|
||||
|
||||
def isSame(v1: FluidStack, v2: FluidStack): Boolean = {
|
||||
if (v1 == null && v2 == null) return true
|
||||
if (v1 == null || v2 == null) return false
|
||||
return v1.isFluidStackIdentical(v2)
|
||||
}
|
||||
|
||||
def save(t: NBTTagCompound, k: UpdateKind.Value) {
|
||||
val tag = new NBTTagCompound()
|
||||
writeToNBT(tag)
|
||||
if (k == UpdateKind.GUI)
|
||||
tag.setInteger("size", size)
|
||||
t.setCompoundTag(name, tag)
|
||||
}
|
||||
|
||||
def load(t: NBTTagCompound, k: UpdateKind.Value) {
|
||||
val tag = t.getCompoundTag(name)
|
||||
readFromNBT(tag)
|
||||
if (k == UpdateKind.GUI)
|
||||
size = tag.getInteger("size")
|
||||
}
|
||||
}
|
||||
|
||||
case class DataSlotTank(name: String, parent: TileDataSlots, var size: Int) extends DataSlotTankBase(size)
|
||||
|
||||
case class DataSlotTankRestricted(name: String, parent: TileDataSlots, var size: Int, fluidID: Int) extends DataSlotTankBase(size) {
|
||||
def fill(amount: Int, doFill: Boolean) = super.fill(new FluidStack(fluidID, amount), doFill)
|
||||
|
||||
override def fill(resource: FluidStack, doFill: Boolean): Int = {
|
||||
if ((resource != null) && (resource.fluidID != fluidID)) return 0
|
||||
return super.fill(resource, doFill)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.data.base
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayerMP
|
||||
import net.bdew.lib.gui.BaseContainer
|
||||
import net.minecraft.inventory.ICrafting
|
||||
|
||||
trait ContainerDataSlots extends BaseContainer {
|
||||
val dataSource: TileDataSlots
|
||||
var lastSentChange = dataSource.lastChange
|
||||
|
||||
override def addCraftingToCrafters(crafter: ICrafting) {
|
||||
super.addCraftingToCrafters(crafter)
|
||||
if (crafter.isInstanceOf[EntityPlayerMP]) {
|
||||
val pkt = dataSource.getDataSlotPacket
|
||||
crafter.asInstanceOf[EntityPlayerMP].playerNetServerHandler.sendPacketToPlayer(pkt)
|
||||
}
|
||||
}
|
||||
|
||||
override def detectAndSendChanges() {
|
||||
super.detectAndSendChanges()
|
||||
// only send updates every 10 ticks
|
||||
if (dataSource.lastChange >= lastSentChange + 10 || (dataSource.lastChange > lastSentChange && lastSentChange + 10 < dataSource.worldObj.getTotalWorldTime)) {
|
||||
lastSentChange = dataSource.lastChange
|
||||
val pkt = dataSource.getDataSlotPacket
|
||||
|
||||
for (player <- players)
|
||||
player.playerNetServerHandler.sendPacketToPlayer(pkt)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.data.base
|
||||
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
|
||||
/**
|
||||
* Base trait for all data slots
|
||||
*/
|
||||
trait DataSlot {
|
||||
/**
|
||||
* Tile Entity that owns this slot
|
||||
* Accessed in constructor, so should be in parameters or a lazy val, otherwise will crash
|
||||
*/
|
||||
val parent: TileDataSlots
|
||||
|
||||
/**
|
||||
* Unique name
|
||||
* Accessed in constructor, so should be in parameters or a lazy val, otherwise will crash
|
||||
*/
|
||||
val name: String
|
||||
|
||||
parent.dataSlots += (name -> this)
|
||||
|
||||
// Where should it sync
|
||||
var updateKind = Set(UpdateKind.GUI)
|
||||
|
||||
def save(t: NBTTagCompound, kind: UpdateKind.Value)
|
||||
def load(t: NBTTagCompound, kind: UpdateKind.Value)
|
||||
|
||||
def setUpdate(vals: UpdateKind.Value*): this.type = {
|
||||
updateKind = vals.toSet
|
||||
return this
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.data.base
|
||||
|
||||
/**
|
||||
* Base class for data slots that hold numeric values
|
||||
* adds convinience operators to modify the value
|
||||
*/
|
||||
|
||||
abstract class DataSlotNumeric[T](default: T)(implicit n: Numeric[T]) extends DataSlotVal[T] {
|
||||
var cval = default
|
||||
def +=(that: T) = update(n.plus(cval, that))
|
||||
def -=(that: T) = update(n.minus(cval, that))
|
||||
def *=(that: T) = update(n.times(cval, that))
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.data.base
|
||||
|
||||
/**
|
||||
* Base class for data slots that hold values with ordering operators, adds more convinience operators
|
||||
* TODO: Do i need this? normal operators can be used with the implicit conversion
|
||||
*/
|
||||
abstract class DataSlotOrdered[T](implicit n: Ordering[T]) extends DataSlotVal[T] {
|
||||
def :>(that: T) = n.compare(cval, that) > 0
|
||||
def :<(that: T) = n.compare(cval, that) < 0
|
||||
def :>=(that: T) = n.compare(cval, that) >= 0
|
||||
def :<=(that: T) = n.compare(cval, that) <= 0
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.data.base
|
||||
|
||||
import language.implicitConversions
|
||||
|
||||
/**
|
||||
* Base trait for data slots that hold primitive values
|
||||
* Defines some convinience operators to access the value and an implicit conversion to the value
|
||||
*/
|
||||
|
||||
trait DataSlotVal[T] extends DataSlot {
|
||||
var cval: T
|
||||
|
||||
def isSame(v: T) = v == cval
|
||||
|
||||
def :=(that: T) = update(that)
|
||||
|
||||
def :!=(that: T) = cval != that
|
||||
def :==(that: T) = cval == that
|
||||
|
||||
def update(v: T) {
|
||||
if (!isSame(v)) {
|
||||
cval = v
|
||||
parent.dataSlotChanged(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object DataSlotVal {
|
||||
implicit def slot2val[T](slot: DataSlotVal[T]): T = slot.cval
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.data.base
|
||||
|
||||
import net.minecraft.network.packet.Packet132TileEntityData
|
||||
import scala.collection.mutable
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
import net.bdew.lib.tile.TileExtended
|
||||
|
||||
trait TileDataSlots extends TileExtended {
|
||||
val dataSlots = mutable.HashMap.empty[String, DataSlot]
|
||||
var lastChange = 0L
|
||||
|
||||
final val TRACE = true
|
||||
|
||||
def doSave(kind: UpdateKind.Value, t: NBTTagCompound) {
|
||||
for ((n, s) <- dataSlots if s.updateKind.contains(kind)) {
|
||||
s.save(t, kind)
|
||||
if (TRACE) printf("%s: %s S=> %s\n".format(kind, n, t.getTag(n)))
|
||||
}
|
||||
}
|
||||
|
||||
def doLoad(kind: UpdateKind.Value, t: NBTTagCompound) {
|
||||
for ((n, s) <- dataSlots if s.updateKind.contains(kind)) {
|
||||
if (TRACE) printf("%s: %s L<= %s\n".format(kind, n, t.getTag(n)))
|
||||
s.load(t, kind)
|
||||
}
|
||||
}
|
||||
|
||||
persistSave.listen(doSave(UpdateKind.SAVE, _))
|
||||
persistLoad.listen(doLoad(UpdateKind.SAVE, _))
|
||||
sendClientUpdate.listen(doSave(UpdateKind.WORLD, _))
|
||||
handleClientUpdate.listen(doLoad(UpdateKind.WORLD, _))
|
||||
|
||||
def dataSlotChanged(slot: DataSlot) {
|
||||
if (worldObj != null) {
|
||||
if (slot.updateKind.contains(UpdateKind.GUI))
|
||||
lastChange = worldObj.getTotalWorldTime
|
||||
if (slot.updateKind.contains(UpdateKind.WORLD))
|
||||
worldObj.markBlockForUpdate(xCoord, yCoord, zCoord)
|
||||
if (slot.updateKind.contains(UpdateKind.SAVE))
|
||||
worldObj.markTileEntityChunkModified(xCoord, yCoord, zCoord, this)
|
||||
}
|
||||
}
|
||||
|
||||
def getDataSlotPacket: Packet132TileEntityData = {
|
||||
val tag = new NBTTagCompound()
|
||||
doSave(UpdateKind.GUI, tag)
|
||||
return new Packet132TileEntityData(this.xCoord, this.yCoord, this.zCoord, ACT_GUI, tag)
|
||||
}
|
||||
|
||||
override protected def extDataPacket(id: Int, data: NBTTagCompound) {
|
||||
if (id == ACT_GUI)
|
||||
doLoad(UpdateKind.GUI, data)
|
||||
super.extDataPacket(id, data)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.data.base
|
||||
|
||||
object UpdateKind extends Enumeration {
|
||||
val WORLD = Value("WORLD")
|
||||
val GUI = Value("GUI")
|
||||
val SAVE = Value("SAVE")
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.gui
|
||||
|
||||
import net.minecraft.inventory.{IInventory, Slot, Container}
|
||||
import net.minecraft.entity.player.{EntityPlayerMP, EntityPlayer, InventoryPlayer}
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.bdew.lib.items.ItemUtils
|
||||
import net.bdew.lib.Misc
|
||||
|
||||
abstract class BaseContainer(te: IInventory) extends Container {
|
||||
|
||||
import scala.collection.JavaConversions._
|
||||
|
||||
def players = Misc.filterType(crafters, classOf[EntityPlayerMP])
|
||||
|
||||
protected def bindPlayerInventory(inv: InventoryPlayer, xOffs: Int, yOffsInv: Int, yOffsHotbar: Int) {
|
||||
for (i <- 0 until 3; j <- 0 until 9)
|
||||
addSlotToContainer(new Slot(inv, j + i * 9 + 9, xOffs + j * 18, yOffsInv + i * 18))
|
||||
|
||||
for (i <- 0 until 9)
|
||||
addSlotToContainer(new Slot(inv, i, xOffs + i * 18, yOffsHotbar))
|
||||
}
|
||||
|
||||
override def transferStackInSlot(player: EntityPlayer, slot: Int): ItemStack = {
|
||||
var stack = getSlot(slot).getStack
|
||||
if (getSlot(slot).inventory == player.inventory) {
|
||||
stack = ItemUtils.addStackToSlots(stack, te, 0 until te.getSizeInventory, true)
|
||||
} else {
|
||||
stack = ItemUtils.addStackToSlots(stack, player.inventory, 9 until player.inventory.mainInventory.length, true)
|
||||
// Only put in hotbar if the rest is full
|
||||
if (stack != null)
|
||||
stack = ItemUtils.addStackToSlots(stack, player.inventory, 0 until 9, true)
|
||||
}
|
||||
getSlot(slot).putStack(stack)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.gui
|
||||
|
||||
import net.minecraft.client.gui.inventory.GuiContainer
|
||||
import net.minecraft.inventory.Container
|
||||
import scala.collection.mutable
|
||||
import net.minecraft.client.gui.GuiButton
|
||||
import net.bdew.lib.gui.widgets.Widget
|
||||
import net.minecraft.util.ResourceLocation
|
||||
import org.lwjgl.opengl.GL11
|
||||
|
||||
abstract class BaseScreen(cont: Container, xSz: Int, ySz: Int) extends GuiContainer(cont) {
|
||||
xSize = xSz
|
||||
ySize = ySz
|
||||
|
||||
val widgets = mutable.MutableList.empty[Widget]
|
||||
val texture: ResourceLocation
|
||||
|
||||
def rect = new Rect(guiLeft, guiTop, xSize, ySize)
|
||||
|
||||
def getFontRenderer = fontRenderer
|
||||
|
||||
override def initGui() {
|
||||
super.initGui()
|
||||
widgets.clear()
|
||||
buttonList.clear()
|
||||
}
|
||||
|
||||
def addButton[T <: GuiButton](w: T): T = {
|
||||
buttonList.asInstanceOf[java.util.ArrayList[GuiButton]].add(w)
|
||||
return w
|
||||
}
|
||||
|
||||
def addWidget[T <: Widget](w: T): T = {
|
||||
widgets += w
|
||||
w.parent = this
|
||||
return w
|
||||
}
|
||||
|
||||
protected override def keyTyped(c: Char, i: Int) {
|
||||
for (w <- widgets)
|
||||
if (w.keyTyped(c, i))
|
||||
return
|
||||
super.keyTyped(c, i)
|
||||
}
|
||||
|
||||
protected override def mouseClicked(x: Int, y: Int, bt: Int) {
|
||||
super.mouseClicked(x, y, bt)
|
||||
val p = new Point(x, y) - rect.origin
|
||||
for (w <- widgets if w.rect.contains(p))
|
||||
w.mouseClicked(p - w.rect.origin, bt)
|
||||
}
|
||||
|
||||
protected override def drawGuiContainerForegroundLayer(x: Int, y: Int) {
|
||||
for (w <- widgets)
|
||||
w.draw()
|
||||
}
|
||||
|
||||
protected override def drawScreen(x: Int, y: Int, f: Float) {
|
||||
super.drawScreen(x, y, f)
|
||||
|
||||
val tip = mutable.MutableList.empty[String]
|
||||
|
||||
val p = new Point(x, y) - rect.origin
|
||||
for (w <- widgets if w.rect.contains(p))
|
||||
w.handleTooltip(p - w.rect.origin, tip)
|
||||
|
||||
import collection.JavaConversions._
|
||||
|
||||
if (tip.size > 0)
|
||||
drawHoveringText(tip, x, y, fontRenderer)
|
||||
}
|
||||
|
||||
protected def drawGuiContainerBackgroundLayer(f: Float, i: Int, j: Int) {
|
||||
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F)
|
||||
mc.renderEngine.bindTexture(texture)
|
||||
val x = (width - xSize) / 2
|
||||
val y = (height - ySize) / 2
|
||||
this.drawTexturedModalRect(x, y, 0, 0, xSize, ySize)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.gui
|
||||
|
||||
object Direction extends Enumeration {
|
||||
type Direction = Value
|
||||
val UP = Value("UP")
|
||||
val DOWN = Value("UP")
|
||||
val LEFT = Value("UP")
|
||||
val RIGHT = Value("UP")
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.gui
|
||||
|
||||
class Point(val x: Int, val y: Int) {
|
||||
def this(p: Point) = this(p.x, p.y)
|
||||
def +(that: Point) = new Point(this.x + that.x, this.y + that.y)
|
||||
def -(that: Point) = new Point(this.x - that.x, this.y - that.y)
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.gui
|
||||
|
||||
class Rect(val x: Int, val y: Int, val w: Int, val h: Int) {
|
||||
def this(p: Point, w: Int, h: Int) = this(p.x, p.y, w, h)
|
||||
def contains(p: Point) = p.x >= x && p.y >= y && p.x <= x + w && p.y <= y + h
|
||||
def origin = new Point(x, y)
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.gui
|
||||
|
||||
import net.minecraft.inventory.IInventory
|
||||
import net.minecraft.inventory.Slot
|
||||
import net.minecraft.item.ItemStack
|
||||
|
||||
class SlotValidating(inv: IInventory, slot: Int, x: Int, y: Int) extends Slot(inv, slot, x, y) {
|
||||
override def isItemValid(stack: ItemStack) = inventory.isItemValidForSlot(getSlotIndex, stack)
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.gui
|
||||
|
||||
import net.minecraft.util.ResourceLocation
|
||||
|
||||
class TextureLocation(val resource: ResourceLocation, val p: Point) extends Point(p.x, p.y) {
|
||||
def this(resource: ResourceLocation, x: Int, y: Int) = this(resource, new Point(x, y))
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.gui.widgets
|
||||
|
||||
import scala.collection.mutable
|
||||
import net.bdew.lib.gui.{Point, BaseScreen, Rect}
|
||||
import net.minecraft.util.ResourceLocation
|
||||
import net.minecraft.client.Minecraft
|
||||
|
||||
trait Widget {
|
||||
val rect: Rect
|
||||
var parent: BaseScreen = null
|
||||
def handleTooltip(p: Point, tip: mutable.MutableList[String]) {}
|
||||
def mouseClicked(p: Point, button: Int) {}
|
||||
def keyTyped(c: Char, i: Int): Boolean = false
|
||||
def draw() {}
|
||||
|
||||
def bindTexture(res: ResourceLocation) = Minecraft.getMinecraft.renderEngine.bindTexture(res)
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.gui.widgets
|
||||
|
||||
import net.bdew.lib.gui.{TextureLocation, Rect}
|
||||
import net.bdew.lib.gui.Direction
|
||||
import net.bdew.lib.data.base.DataSlotNumeric
|
||||
|
||||
class WidgetFillDataslot[T](val rect: Rect, val texture: TextureLocation, dir: Direction.Direction, dslot: DataSlotNumeric[T], maxval: T)(implicit num: Numeric[T]) extends Widget {
|
||||
|
||||
def getFillArea(max: Int): Int = (num.toFloat(dslot) / num.toFloat(maxval) * max).round
|
||||
|
||||
override def draw() {
|
||||
bindTexture(texture.resource)
|
||||
dir match {
|
||||
case Direction.UP =>
|
||||
val fill = getFillArea(rect.h)
|
||||
parent.drawTexturedModalRect(rect.x, rect.y + rect.h - fill, texture.x, texture.y + rect.h - fill, rect.w, fill)
|
||||
case Direction.DOWN =>
|
||||
val fill = getFillArea(rect.h)
|
||||
parent.drawTexturedModalRect(rect.x, rect.y, texture.x, texture.y, rect.w, fill)
|
||||
case Direction.LEFT =>
|
||||
val fill = getFillArea(rect.w)
|
||||
parent.drawTexturedModalRect(rect.x + rect.w - fill, rect.y, texture.x + rect.w - fill, texture.y, fill, rect.h)
|
||||
case Direction.RIGHT =>
|
||||
val fill = getFillArea(rect.w)
|
||||
parent.drawTexturedModalRect(rect.x, rect.y, texture.x, texture.y, fill, rect.h)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.gui.widgets
|
||||
|
||||
import net.bdew.lib.gui.{Point, TextureLocation, Rect}
|
||||
import net.bdew.lib.data.DataSlotTankBase
|
||||
import scala.collection.mutable
|
||||
import net.minecraft.client.renderer.texture.TextureMap
|
||||
import java.text.DecimalFormat
|
||||
import net.bdew.lib.Misc
|
||||
import org.lwjgl.opengl.GL11
|
||||
|
||||
class WidgetFluidGauge(val rect: Rect, overlay: TextureLocation, dslot: DataSlotTankBase) extends Widget {
|
||||
val formater = new DecimalFormat("#,###")
|
||||
|
||||
override def handleTooltip(p: Point, tip: mutable.MutableList[String]) {
|
||||
if (dslot.getFluid != null) {
|
||||
tip += dslot.getFluid.getFluid.getLocalizedName
|
||||
tip += "%s/%s mB".format(formater.format(dslot.getFluidAmount), formater.format(dslot.getCapacity))
|
||||
} else {
|
||||
tip += Misc.toLocal("gendustry.label.empty")
|
||||
}
|
||||
}
|
||||
|
||||
override def draw() {
|
||||
GL11.glEnable(GL11.GL_BLEND)
|
||||
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA)
|
||||
|
||||
val fstack = dslot.getFluid
|
||||
if (fstack != null && fstack.getFluid.getStillIcon != null) {
|
||||
val icon = fstack.getFluid.getStillIcon
|
||||
bindTexture(TextureMap.locationBlocksTexture)
|
||||
var fillHeight: Int = (rect.h * fstack.amount / dslot.getCapacity).round
|
||||
var yStart: Int = 0
|
||||
|
||||
while (fillHeight > 0) {
|
||||
if (fillHeight > 16) {
|
||||
parent.drawTexturedModelRectFromIcon(rect.x, rect.y + rect.h - 16 - yStart, icon, 16, 16)
|
||||
fillHeight -= 16
|
||||
} else {
|
||||
parent.drawTexturedModelRectFromIcon(rect.x, rect.y + rect.h - fillHeight - yStart, icon, 16, fillHeight)
|
||||
fillHeight = 0
|
||||
}
|
||||
yStart = yStart + 16
|
||||
}
|
||||
}
|
||||
|
||||
GL11.glDisable(GL11.GL_BLEND)
|
||||
|
||||
bindTexture(overlay.resource)
|
||||
parent.drawTexturedModalRect(rect.x, rect.y, overlay.x, overlay.y, rect.w, rect.h)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.gui.widgets
|
||||
|
||||
import net.bdew.lib.gui.Rect
|
||||
|
||||
class WidgetLabel(text: String, x: Int, y: Int, color: Int) extends Widget {
|
||||
val rect: Rect = new Rect(x, y, 0, 0)
|
||||
override def draw() {
|
||||
parent.getFontRenderer.drawString(text, x, y, color)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.gui.widgets
|
||||
|
||||
import net.bdew.lib.gui.{Point, Direction, TextureLocation, Rect}
|
||||
import net.bdew.lib.data.DataSlotFloat
|
||||
import scala.collection.mutable
|
||||
|
||||
class WidgetProgressBar(rect: Rect, texture: TextureLocation, dslot: DataSlotFloat) extends WidgetFillDataslot[Float](rect, texture, Direction.RIGHT, dslot, 1) {
|
||||
override def handleTooltip(p: Point, tip: mutable.MutableList[String]) = tip += "%.0f".format(dslot.cval * 100) + "%"
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.gui.widgets
|
||||
|
||||
import net.minecraft.client.gui.{FontRenderer, GuiTextField}
|
||||
import net.bdew.lib.gui.{Point, Rect}
|
||||
|
||||
class WidgetTextEdit(val rect: Rect, fr: FontRenderer) extends GuiTextField(fr, rect.x, rect.y, rect.w, rect.h) with Widget {
|
||||
override def mouseClicked(p: Point, button: Int) = super.mouseClicked(p.x + rect.x, p.y + rect.y, button)
|
||||
override def keyTyped(c: Char, i: Int): Boolean = super.textboxKeyTyped(c, i)
|
||||
override def draw() = super.drawTextBox()
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.items
|
||||
|
||||
import net.minecraft.entity.item.EntityItem
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.world.World
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
import net.minecraft.inventory.IInventory
|
||||
import net.bdew.lib.Misc
|
||||
|
||||
object ItemUtils {
|
||||
def throwItemAt(world: World, x: Int, y: Int, z: Int, stack: ItemStack) {
|
||||
if ((stack == null) || world.isRemote) return
|
||||
val dx = world.rand.nextFloat * 0.8
|
||||
val dy = world.rand.nextFloat * 0.8
|
||||
val dz = world.rand.nextFloat * 0.8
|
||||
val entityitem: EntityItem = new EntityItem(world, x + dx, y + dy, z + dz, stack)
|
||||
entityitem.motionX = world.rand.nextGaussian * 0.05
|
||||
entityitem.motionY = world.rand.nextGaussian * 0.05 + 0.2
|
||||
entityitem.motionZ = world.rand.nextGaussian * 0.05
|
||||
world.spawnEntityInWorld(entityitem)
|
||||
}
|
||||
|
||||
def dropItemToPlayer(world: World, player: EntityPlayer, stack: ItemStack) {
|
||||
if ((stack == null) || world.isRemote) return
|
||||
world.spawnEntityInWorld(new EntityItem(world, player.posX, player.posY, player.posZ, stack))
|
||||
}
|
||||
|
||||
def isSameItem(stack1: ItemStack, stack2: ItemStack): Boolean = {
|
||||
if (stack1 == null || stack2 == null)
|
||||
return stack1 == stack2
|
||||
if (stack1.itemID != stack2.itemID)
|
||||
return false
|
||||
if (stack1.getHasSubtypes && stack2.getItemDamage != stack1.getItemDamage)
|
||||
return false
|
||||
return ItemStack.areItemStackTagsEqual(stack2, stack1)
|
||||
}
|
||||
|
||||
def addStackToSlots(stack: ItemStack, inv: IInventory, slots: Iterable[Int], checkvalid: Boolean): ItemStack = {
|
||||
if (stack == null) return null
|
||||
|
||||
// Try merging into existing slots
|
||||
for (slot <- slots if (!checkvalid || inv.isItemValidForSlot(slot, stack)) && isSameItem(stack, inv.getStackInSlot(slot))) {
|
||||
val target = inv.getStackInSlot(slot)
|
||||
val toAdd = Misc.min(target.getMaxStackSize - target.stackSize, inv.getInventoryStackLimit - target.stackSize, stack.stackSize)
|
||||
if (toAdd >= stack.stackSize) {
|
||||
target.stackSize += stack.stackSize
|
||||
stack.stackSize = 0
|
||||
inv.onInventoryChanged()
|
||||
return null
|
||||
} else if (toAdd > 0) {
|
||||
target.stackSize += toAdd
|
||||
stack.stackSize -= toAdd
|
||||
inv.onInventoryChanged()
|
||||
}
|
||||
}
|
||||
|
||||
// Now find empty slots and stick any leftovers there
|
||||
for (slot <- slots if (!checkvalid || inv.isItemValidForSlot(slot, stack)) && inv.getStackInSlot(slot) == null) {
|
||||
if (inv.getInventoryStackLimit < stack.stackSize) {
|
||||
inv.setInventorySlotContents(slot, stack.splitStack(inv.getInventoryStackLimit))
|
||||
} else {
|
||||
inv.setInventorySlotContents(slot, stack.copy())
|
||||
stack.stackSize = 0
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
return stack
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.recipes
|
||||
|
||||
/**
|
||||
* Base class for everything that can be resolved to ItemStack or recipe component
|
||||
* Actual processing is in:
|
||||
* * [[net.bdew.lib.recipes.RecipeLoader.getRecipeComponent]]
|
||||
* * [[net.bdew.lib.recipes.RecipeLoader.getConcreteStack]]
|
||||
* * [[net.bdew.lib.recipes.RecipeLoader.getAllConcreteStacks]]
|
||||
*
|
||||
*/
|
||||
abstract class StackRef
|
||||
|
||||
/**
|
||||
* Ore Dictionary reference
|
||||
* Syntax: OD:{identifier}
|
||||
* Parser: [[net.bdew.lib.recipes.RecipeParser.specOD]]
|
||||
* @param id OD entry name
|
||||
*/
|
||||
case class StackOreDict(id: String) extends StackRef
|
||||
|
||||
/**
|
||||
* Mod item reference [[cpw.mods.fml.common.registry.GameRegistry.findItemStack]]
|
||||
* Syntax: {modID}:{name}
|
||||
* Parser: [[net.bdew.lib.recipes.RecipeParser.specModStack]]
|
||||
* @param mod modId of owner mod
|
||||
* @param id name of the stack
|
||||
*/
|
||||
case class StackMod(mod: String, id: String) extends StackRef
|
||||
|
||||
/**
|
||||
* Vanilla block reference
|
||||
* Syntax: B:{name} [@ {meta}]
|
||||
* Parser: [[net.bdew.lib.recipes.RecipeParser.specMcBlock]]
|
||||
* @param name Unlocalized name (without "tile.")
|
||||
* @param meta Metadata / Damage
|
||||
*/
|
||||
case class StackMCBlock(name: String, meta: Int) extends StackRef
|
||||
|
||||
/**
|
||||
* Vanilla item reference
|
||||
* Syntax: I:{name} [@ {meta}]
|
||||
* Parser: [[net.bdew.lib.recipes.RecipeParser.specMcItem]]
|
||||
* @param name Unlocalized name (without "item.")
|
||||
* @param meta Metadata / Damage
|
||||
*/
|
||||
case class StackMCItem(name: String, meta: Int) extends StackRef
|
||||
|
||||
/**
|
||||
* Reference to an Item/Block/ItemStack pulic static field
|
||||
* Syntax: {path}.{to}.{class}[{field}] [@ {meta}]
|
||||
* Parser: [[net.bdew.lib.recipes.RecipeParser.specReflect]]
|
||||
* @param cls Class name
|
||||
* @param field Field name
|
||||
* @param meta Metadata / Damage (Ignored for ItemStacks)
|
||||
*/
|
||||
case class StackReflect(cls: String, field: String, meta: Int) extends StackRef
|
||||
|
||||
/**
|
||||
* Reference to an Item/Block/ItemStack pulic static getter
|
||||
* Syntax: {path}.{to}.{class}.{method}({string}) [@ {meta}]
|
||||
* Parser: [[net.bdew.lib.recipes.RecipeParser.specGetter]]
|
||||
* @param cls Class name
|
||||
* @param method Method name
|
||||
* @param name Parameter to getter
|
||||
* @param meta Metadata / Damage (Ignored for ItemStacks)
|
||||
*/
|
||||
case class StackGetter(cls: String, method: String, name: String, meta: Int) extends StackRef
|
||||
|
||||
/**
|
||||
* Macro reference to a previous definition
|
||||
* Syntax: ${char}
|
||||
* Parser: [[net.bdew.lib.recipes.RecipeParser.specMacro]]
|
||||
* @param id The underlying character
|
||||
*/
|
||||
case class StackMacro(id: Char) extends StackRef
|
||||
|
||||
/**
|
||||
* Base class for statements
|
||||
* Actual processing is in [[net.bdew.lib.recipes.RecipeLoader.processStatement]]
|
||||
*/
|
||||
abstract class Statement
|
||||
|
||||
/**
|
||||
* Character assignment
|
||||
* Syntax: {char} = {ref}
|
||||
* Parser: [[net.bdew.lib.recipes.RecipeParser.charSpec]]
|
||||
* @param char Character to assign
|
||||
* @param spec ItemStack Reference
|
||||
*/
|
||||
case class StCharAssign(char: Char, spec: StackRef) extends Statement
|
||||
|
||||
/**
|
||||
* Define class macro
|
||||
* Syntax: def {id} = {name}
|
||||
* Parser: [[net.bdew.lib.recipes.RecipeParser.classMacro]]
|
||||
* @param id Macro identifier
|
||||
* @param cls Class name
|
||||
*/
|
||||
case class StClassMacro(id: String, cls: String) extends Statement
|
||||
|
||||
/**
|
||||
* Conditional block - checks if mod is loaded
|
||||
* Syntax: ifMod {string} { {statements} } [else { {statements} }]
|
||||
* Parser: [[net.bdew.lib.recipes.RecipeParser.ifMod]]
|
||||
* @param mod mod and version to check [[cpw.mods.fml.common.versioning.VersionParser]]
|
||||
* @param thn Statements to run if present
|
||||
* @param els Statements to run otherwise
|
||||
*/
|
||||
case class StIfHaveMod(mod: String, thn: List[Statement], els: List[Statement]) extends Statement
|
||||
|
||||
/**
|
||||
* Conditional block - checks if mod is loaded
|
||||
* Syntax: ifOreDict {string} { {statements} } [else { {statements} }]
|
||||
* Parser: [[net.bdew.lib.recipes.RecipeParser.ifOreDict]]
|
||||
* @param id Ore Dictionary Entry
|
||||
* @param thn Statements to run if present
|
||||
* @param els Statements to run otherwise
|
||||
*/
|
||||
case class StIfHaveOD(id: String, thn: List[Statement], els: List[Statement]) extends Statement
|
||||
|
||||
/**
|
||||
* Shaped recipe definition
|
||||
*
|
||||
* Syntax:
|
||||
* XXX
|
||||
* XXX => {result} [* {count}]
|
||||
* XXX
|
||||
*
|
||||
* Parser: [[net.bdew.lib.recipes.RecipeParser.recipeShaped3x3]]
|
||||
*
|
||||
* Syntax:
|
||||
* XX
|
||||
* XX => {result} [* {count}]
|
||||
*
|
||||
* Parser: [[net.bdew.lib.recipes.RecipeParser.recipeShaped2x2]]
|
||||
*
|
||||
* Syntax: XXX XXX XXX => {result} [* {count}]
|
||||
* Parser: [[net.bdew.lib.recipes.RecipeParser.recipeShaped9]]
|
||||
*
|
||||
* @param rec Recipe pattern
|
||||
* @param res Result reference
|
||||
* @param cnt Number of output items
|
||||
*/
|
||||
case class StRecipeShaped(rec: Seq[String], res: StackRef, cnt: Int) extends Statement
|
||||
|
||||
/**
|
||||
* Shapeless recipe definition
|
||||
* Syntax: shapeless: {characters} => {result} [* {count}]
|
||||
* Parser: [[net.bdew.lib.recipes.RecipeParser.recipeShapeless]]
|
||||
*
|
||||
* @param rec Recipe pattehrn
|
||||
* @param res Result reference
|
||||
* @param cnt Number of output items
|
||||
*/
|
||||
case class StRecipeShapeless(rec: String, res: StackRef, cnt: Int) extends Statement
|
||||
|
||||
/**
|
||||
* Smelting recipe definition
|
||||
* Syntax: smelt: {input} => {output}, {XP}
|
||||
* Parser [[net.bdew.lib.recipes.RecipeParser.recipeSmelting]]
|
||||
*
|
||||
* @param in Input Stack
|
||||
* @param out Output Stack
|
||||
* @param cnt Output Count
|
||||
* @param xp XP for smelting
|
||||
*/
|
||||
case class StSmeltRecipe(in: StackRef, out: StackRef, cnt: Int, xp: Float) extends Statement
|
||||
|
||||
/**
|
||||
* Used in statement processing to abort the current statement and show an error without a stack trace
|
||||
*/
|
||||
class StatementError(msg: String) extends Exception(msg)
|
||||
@@ -0,0 +1,319 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.recipes
|
||||
|
||||
import java.io.Reader
|
||||
import net.minecraft.item.{Item, ItemStack}
|
||||
import net.bdew.lib.Misc
|
||||
import net.minecraft.block.Block
|
||||
import cpw.mods.fml.common.registry.GameRegistry
|
||||
import net.minecraftforge.oredict.{ShapelessOreRecipe, OreDictionary}
|
||||
import java.util.logging.Logger
|
||||
import cpw.mods.fml.common.FMLLog
|
||||
import net.minecraft.item.crafting.FurnaceRecipes
|
||||
|
||||
/**
|
||||
* Main recipe loader class
|
||||
* The input file is parsed by [[net.bdew.lib.recipes.RecipeParser]]
|
||||
* Into a list of [[net.bdew.lib.recipes.Statement]] subclasses
|
||||
* That are then executed here
|
||||
*/
|
||||
|
||||
class RecipeLoader {
|
||||
|
||||
/**
|
||||
* Create a new parser, override in subclasses to use an extended parser
|
||||
* @return New ConfigParser (or subclass) instance
|
||||
*/
|
||||
def newParser() = new RecipeParser()
|
||||
|
||||
val log: Logger = Logger.getLogger("RecipeLoader")
|
||||
log.setParent(FMLLog.getLogger)
|
||||
|
||||
/**
|
||||
* Current map of recipe characters to parser item references
|
||||
*/
|
||||
val currCharMap = collection.mutable.Map.empty[Char, StackRef].withDefault(x => error("Undefined recipe character '%s'", x))
|
||||
|
||||
/**
|
||||
* Current map of class macros
|
||||
*/
|
||||
val currClassMacros = collection.mutable.Map.empty[String, String].withDefault(x => error("Undefined class macro '%s'", x))
|
||||
|
||||
/**
|
||||
* Triggers an error with formatted string
|
||||
*/
|
||||
def error(msg: String, params: Any*) = throw new StatementError(msg.format(params: _*))
|
||||
|
||||
/**
|
||||
* Looks up a recipe component
|
||||
* @param s Parser ItemStack reference
|
||||
* @return ItemStack or String that can be used as recipe components in MC functions
|
||||
*/
|
||||
def getRecipeComponent(s: StackRef): AnyRef = s match {
|
||||
case StackOreDict(id) => id
|
||||
case StackMacro(ch) => getRecipeComponent(currCharMap(ch))
|
||||
case _ => getConcreteStack(s)
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve class name if it's a macro
|
||||
*/
|
||||
def getRealClassName(s: String): String = {
|
||||
if (s.startsWith("$")) {
|
||||
return currClassMacros(s.stripPrefix("$"))
|
||||
}
|
||||
return s
|
||||
}
|
||||
/**
|
||||
* Sanitize items from reflection
|
||||
* @param x The item
|
||||
* @param source Human readable source (used in errors and warnings)
|
||||
* @param meta Metadata or damage
|
||||
* @param cnt Stack size
|
||||
* @return
|
||||
*/
|
||||
def sanitizeReflectedItem(x: AnyRef, source: String, meta: Int, cnt: Int): ItemStack = x match {
|
||||
case x: ItemStack =>
|
||||
val l = x.copy()
|
||||
l.stackSize = cnt
|
||||
if (meta != OreDictionary.WILDCARD_VALUE && meta != l.getItemDamage) {
|
||||
log.warning("%s requested with meta %d but specifies %d".format(source, meta, l.getItemDamage))
|
||||
l.setItemDamage(meta)
|
||||
}
|
||||
return l
|
||||
case x: Item =>
|
||||
return new ItemStack(x, cnt, meta)
|
||||
case x: Block =>
|
||||
return new ItemStack(x, cnt, meta)
|
||||
case _ =>
|
||||
error("%s is %s which cannot be translated to an ItemStack", source, x.getClass.getName)
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches an ItemStack using reflection from static fields
|
||||
* Item and Block instaces are converted to ItemStacks
|
||||
* @param clsName Name of class to fetch from (can be a class macro)
|
||||
* @param fldName Field name
|
||||
* @param meta Metadata or damage
|
||||
* @param cnt Stack size
|
||||
* @return Matching itemstack
|
||||
*/
|
||||
def reflectStack(clsName: String, fldName: String, meta: Int, cnt: Int): ItemStack = {
|
||||
val realName = getRealClassName(clsName)
|
||||
val cls = Class.forName(realName)
|
||||
val fld = cls.getField(fldName).get(null)
|
||||
return sanitizeReflectedItem(fld, "%s.%s".format(realName, fldName), meta, cnt)
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches an ItemStack using reflection from static getters
|
||||
* Item and Block instaces are converted to ItemStacks
|
||||
* @param clsName Name of class to fetch from (can be a class macro)
|
||||
* @param method Method name
|
||||
* @param param Parameter to method
|
||||
* @param meta Metadata or damage
|
||||
* @param cnt Stack size
|
||||
* @return Matching itemstack
|
||||
*/
|
||||
def reflectStackGetter(clsName: String, method: String, param: String, meta: Int, cnt: Int): ItemStack = {
|
||||
var realName: String = clsName
|
||||
var realMethod: String = method
|
||||
|
||||
//Some acrobatics to allow use with macros, even bare ones like $foo(bar)
|
||||
|
||||
if ((realName.length == 0) && realMethod.startsWith("$")) {
|
||||
val v = getRealClassName(realMethod).split('.').reverse
|
||||
realName = v.tail.reverse.mkString(".")
|
||||
realMethod = v.head
|
||||
}
|
||||
if (realName.startsWith("$")) {
|
||||
realName = getRealClassName(clsName)
|
||||
}
|
||||
|
||||
val cls = Class.forName(realName)
|
||||
val meth = cls.getMethod(realMethod, classOf[String])
|
||||
val res = meth.invoke(null, param)
|
||||
return sanitizeReflectedItem(res, "%s.%s(%s)".format(realName, realMethod, param), meta, cnt)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all possible ItemStacks that match a reference
|
||||
* Currently everything except OreDictionary references just returns one item
|
||||
* @param s Parser ItemStack reference
|
||||
* @param cnt Stack size
|
||||
* @return List of matching ItemStacks
|
||||
*/
|
||||
def getAllConcreteStacks(s: StackRef, cnt: Int = 1): Iterable[ItemStack] = s match {
|
||||
case StackOreDict(id) =>
|
||||
import scala.collection.JavaConversions._
|
||||
val c = OreDictionary.getOres(id).map(_.copy())
|
||||
c.foreach(_.stackSize = cnt)
|
||||
return c
|
||||
case _ => Seq(getConcreteStack(s))
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an ItemStack that match a reference
|
||||
* This is the main StackRef resolution method
|
||||
* @param s Parser ItemStack reference
|
||||
* @param cnt Stack size
|
||||
* @return A matching ItemStack
|
||||
*/
|
||||
def getConcreteStack(s: StackRef, cnt: Int = 1): ItemStack = s match {
|
||||
case StackOreDict(id) =>
|
||||
val l = OreDictionary.getOres(id)
|
||||
if (l.size == 0) error("Concrete ItemStack requested for OD entry '%s' that is empty", id)
|
||||
val s = l.get(0).copy()
|
||||
s.stackSize = cnt
|
||||
log.info("Concrete ItemStack for OD entry '%s' -> %s".format(id, s))
|
||||
return s
|
||||
case StackMacro(ch) => getConcreteStack(currCharMap(ch), cnt)
|
||||
case StackMod(mod, id) =>
|
||||
val i = GameRegistry.findItemStack(mod, id, cnt)
|
||||
if (i == null) error("Item %s:%s not found", mod, id)
|
||||
i
|
||||
case StackMCBlock(id, meta) => new ItemStack(Vanilla.blocks(id), cnt, meta)
|
||||
case StackMCItem(id, meta) => new ItemStack(Vanilla.items(id), cnt, meta)
|
||||
case StackReflect(cls, field, meta) => reflectStack(cls, field, meta, cnt)
|
||||
case StackGetter(cls, method, param, meta) => reflectStackGetter(cls, method, param, meta, cnt)
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up all characters used in the recipe
|
||||
* @param s The pattern
|
||||
* @return Map from character to recipe components and a boolean that means OD-aware methods should be used
|
||||
*/
|
||||
def resolveRecipeComponents(s: Iterable[Char]): (Map[Char, AnyRef], Boolean) = {
|
||||
var comp = Map.empty[Char, AnyRef]
|
||||
var needOd = false
|
||||
for (x <- s if !comp.contains(x) && x != '_') {
|
||||
if (!currCharMap.contains(x)) error("Character %s is undefined", x)
|
||||
val r = getRecipeComponent(currCharMap(x))
|
||||
if (r.isInstanceOf[String]) needOd = true
|
||||
log.info("%s -> %s".format(x, r))
|
||||
comp += (x -> r)
|
||||
}
|
||||
return (comp, needOd)
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a single statement, override this to add more statements
|
||||
* @param s The statement
|
||||
*/
|
||||
def processStatement(s: Statement): Unit = s match {
|
||||
case StCharAssign(c, r) =>
|
||||
currCharMap(c) = r
|
||||
log.info("Added %s = %s".format(c, r))
|
||||
|
||||
case StClassMacro(id, cls) =>
|
||||
currClassMacros(id) = cls
|
||||
log.info("Added def %s = %s".format(id, cls))
|
||||
|
||||
case StIfHaveMod(mod, thn, els) =>
|
||||
if (Misc.haveModVersion(mod)) {
|
||||
log.info("ifMod: %s found".format(mod))
|
||||
processStatementsSafe(thn)
|
||||
} else {
|
||||
log.info("ifMod: %s not found".format(mod))
|
||||
processStatementsSafe(els)
|
||||
}
|
||||
|
||||
case StIfHaveOD(od, thn, els) =>
|
||||
if (OreDictionary.getOres(od).size() > 0) {
|
||||
log.info("ifOreDict: %s found".format(od))
|
||||
processStatementsSafe(thn)
|
||||
} else {
|
||||
log.info("ifOreDict: %s not found".format(od))
|
||||
processStatementsSafe(els)
|
||||
}
|
||||
|
||||
case StRecipeShaped(rec, res, cnt) =>
|
||||
log.info("Adding shaped recipe %s => %s * %d".format(rec, res, cnt))
|
||||
val (comp, needOd) = resolveRecipeComponents(rec.mkString(""))
|
||||
val resStack = getConcreteStack(res, cnt)
|
||||
|
||||
if (resStack.getItemDamage == OreDictionary.WILDCARD_VALUE) {
|
||||
log.info("Result meta is unset, defaulting to 0")
|
||||
resStack.setItemDamage(0)
|
||||
}
|
||||
|
||||
if (needOd)
|
||||
Misc.addRecipeOD(resStack, rec, comp)
|
||||
else
|
||||
Misc.addRecipe(resStack, rec, comp)
|
||||
|
||||
log.info("Done... result=%s, od=%s".format(resStack, needOd))
|
||||
|
||||
case StRecipeShapeless(rec, res, cnt) =>
|
||||
log.info("Adding shapeless recipe %s => %s * %d".format(rec, res, cnt))
|
||||
val (comp, needOd) = resolveRecipeComponents(rec)
|
||||
val resStack = getConcreteStack(res, cnt)
|
||||
val recTrans = rec.toCharArray.map(comp(_))
|
||||
|
||||
if (resStack.getItemDamage == OreDictionary.WILDCARD_VALUE) {
|
||||
log.info("Result meta is unset, defaulting to 0")
|
||||
resStack.setItemDamage(0)
|
||||
}
|
||||
|
||||
if (needOd)
|
||||
GameRegistry.addRecipe(new ShapelessOreRecipe(resStack, recTrans: _*))
|
||||
else
|
||||
GameRegistry.addShapelessRecipe(resStack, recTrans: _*)
|
||||
|
||||
log.info("Done... result=%s, od=%s".format(resStack, needOd))
|
||||
|
||||
case StSmeltRecipe(in, out, cnt, xp) =>
|
||||
log.info("Adding smelting recipe %s => %s * %d (%f xp)".format(in, out, cnt, xp))
|
||||
val outStack = getConcreteStack(out, cnt)
|
||||
if (outStack.getItemDamage == OreDictionary.WILDCARD_VALUE) {
|
||||
log.info("Result meta is unset, defaulting to 0")
|
||||
outStack.setItemDamage(0)
|
||||
}
|
||||
for (inStack <- getAllConcreteStacks(in, 1)) {
|
||||
if (inStack.getItemDamage == OreDictionary.WILDCARD_VALUE) {
|
||||
FurnaceRecipes.smelting.addSmelting(inStack.itemID, outStack, xp)
|
||||
log.info("added %d -> %s".format(inStack.itemID, outStack))
|
||||
} else {
|
||||
FurnaceRecipes.smelting.addSmelting(inStack.itemID, inStack.getItemDamage, outStack, xp)
|
||||
log.info("added %d@%d -> %s".format(inStack.itemID, inStack.getItemDamage, outStack))
|
||||
}
|
||||
}
|
||||
|
||||
case x =>
|
||||
log.severe("Can't process %s - this is a programing bug!".format(x))
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a list of statements and catch all exceptions
|
||||
* @param r The list to process
|
||||
*/
|
||||
def processStatementsSafe(r: List[Statement]): Unit = {
|
||||
for (s <- r) {
|
||||
try {
|
||||
processStatement(s)
|
||||
} catch {
|
||||
case e: StatementError =>
|
||||
log.severe("Error while processing %s: %s".format(s, e.getMessage))
|
||||
case e: Throwable =>
|
||||
log.severe("Error while processing %s: %s".format(s, e))
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def load(f: Reader) {
|
||||
log.info("Starting parsing")
|
||||
val r = newParser().doParse(f)
|
||||
log.info("Processing %d statements".format(r.size))
|
||||
processStatementsSafe(r)
|
||||
log.info("Done")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.recipes
|
||||
|
||||
import java.io.Reader
|
||||
|
||||
import scala.util.parsing.combinator._
|
||||
import org.apache.commons.lang3.StringEscapeUtils
|
||||
import net.minecraftforge.oredict.OreDictionary
|
||||
|
||||
class RecipeParser extends JavaTokenParsers {
|
||||
// Allows C-style comments
|
||||
protected override val whiteSpace = """(\s|//.*|(?m)/\*(\*(?!/)|[^*])*\*/)+""".r
|
||||
|
||||
// Simple integer without signs
|
||||
def int = "\\d+".r ^^ (_.toInt)
|
||||
|
||||
// Possible metadata suffix (defaults to wildcard value)
|
||||
def maybeMeta = ("@" ~> int).? ^^ (_.getOrElse(OreDictionary.WILDCARD_VALUE))
|
||||
|
||||
// Qualified class name
|
||||
def clsPath = (ident <~ ".").* ~ ident
|
||||
|
||||
// Single character usable in recipes (this could be extended)
|
||||
def recipeChar = "[a-zA-Z0-9]".r ^^ (_.charAt(0))
|
||||
|
||||
// Set of 3 characters for 3x3 recipes (underscore = empty)
|
||||
def recipeTriplet = repN(3, recipeChar | "_") ^^ (_.mkString(""))
|
||||
|
||||
// Set of 2 characters for 2x2 recipes
|
||||
def recipeDuplet = repN(2, recipeChar | "_") ^^ (_.mkString(""))
|
||||
|
||||
// Quoted string with escape characters
|
||||
def unescapeStr = stringLiteral ^^ { case x => StringEscapeUtils.unescapeJava(x.substring(1, x.length - 1)) }
|
||||
|
||||
// Identifier or quoted string
|
||||
def str = ident | unescapeStr
|
||||
|
||||
// === Item references ===
|
||||
|
||||
def specOD = "OD" ~> ":" ~> ident ^^ StackOreDict
|
||||
def specMcBlock = "B" ~> ":" ~> ident ~ maybeMeta ^^ { case b ~ m => StackMCBlock(b, m) }
|
||||
def specMcItem = "I" ~> ":" ~> ident ~ maybeMeta ^^ { case b ~ m => StackMCItem(b, m) }
|
||||
def specModStack = str ~ ":" ~ str ^^ { case m ~ c ~ n => StackMod(m, n) }
|
||||
def specMacro = "$" ~> recipeChar ^^ StackMacro
|
||||
|
||||
def specReflect = clsPath ~ ("[" ~> ident <~ "]") ~ maybeMeta ^^ {
|
||||
case (p ~ cl) ~ id ~ m => StackReflect((p :+ cl).mkString("."), id, m)
|
||||
}
|
||||
|
||||
def specGetter = clsPath ~ ("(" ~> str <~ ")") ~ maybeMeta ^^ {
|
||||
case (p ~ cl) ~ n ~ m => StackGetter(p.mkString("."), cl, n, m)
|
||||
}
|
||||
|
||||
def spec = specMcBlock | specMcItem | specOD | specModStack | specGetter | specReflect | specMacro
|
||||
|
||||
// Spec with possible number of items
|
||||
def specWithCount = spec ~ ("*" ~> int).?
|
||||
|
||||
// === Statements ===
|
||||
|
||||
def charSpec = recipeChar ~ "=" ~ spec ^^ {
|
||||
case ch ~ eq ~ spec => new StCharAssign(ch, spec)
|
||||
}
|
||||
|
||||
def classMacro = ("def" ~> ident <~ "=") ~ clsPath ^^ {
|
||||
case id ~ (p ~ cl) => StClassMacro(id, (p :+ cl).mkString("."))
|
||||
}
|
||||
|
||||
def ifMod = ("ifMod" ~> str) ~ ("{" ~> statements <~ "}") ~ ("else" ~> "{" ~> statements <~ "}").? ^^ {
|
||||
case mod ~ thn ~ els => new StIfHaveMod(mod, thn, els.getOrElse(List.empty[Statement]))
|
||||
}
|
||||
|
||||
def ifOreDict = ("ifOreDict" ~> str) ~ ("{" ~> statements <~ "}") ~ ("else" ~> "{" ~> statements <~ "}").? ^^ {
|
||||
case id ~ thn ~ els => new StIfHaveOD(id, thn, els.getOrElse(List.empty[Statement]))
|
||||
}
|
||||
|
||||
def recipeShaped3x3 = recipeTriplet ~ recipeTriplet ~ ("=>" ~> specWithCount) ~ recipeTriplet ^^ {
|
||||
case r1 ~ r2 ~ (res ~ n) ~ r3 => StRecipeShaped(Seq(r1, r2, r3), res, n.getOrElse(1))
|
||||
}
|
||||
|
||||
def recipeShaped2x2 = recipeDuplet ~ recipeDuplet ~ ("=>" ~> specWithCount) ^^ {
|
||||
case r1 ~ r2 ~ (res ~ n) => StRecipeShaped(Seq(r1, r2), res, n.getOrElse(1))
|
||||
}
|
||||
|
||||
def recipeShaped9 = recipeTriplet ~ recipeTriplet ~ recipeTriplet ~ ("=>" ~> specWithCount) ^^ {
|
||||
case r1 ~ r2 ~ r3 ~ (res ~ n) => StRecipeShaped(Seq(r1, r2, r3), res, n.getOrElse(1))
|
||||
}
|
||||
|
||||
def recipeShapeless = "shapeless" ~> ":" ~> recipeChar.+ ~ ("=>" ~> specWithCount) ^^ {
|
||||
case r ~ (res ~ n) => StRecipeShapeless(r.mkString(""), res, n.getOrElse(1))
|
||||
}
|
||||
|
||||
def recipeSmelting = "smelt" ~> ":" ~> spec ~ ("=>" ~> specWithCount) ~ ("," ~> decimalNumber).? ^^ {
|
||||
case in ~ (out ~ n) ~ xp => StSmeltRecipe(in, out, n.getOrElse(1), xp.getOrElse("0").toFloat)
|
||||
}
|
||||
|
||||
def statement: Parser[Statement] = (
|
||||
charSpec
|
||||
| classMacro
|
||||
| ifMod
|
||||
| recipeShaped3x3
|
||||
| recipeShaped2x2
|
||||
| recipeShaped9
|
||||
| recipeShapeless
|
||||
| recipeSmelting
|
||||
)
|
||||
|
||||
def statements = statement.*
|
||||
|
||||
def doParse(r: Reader): List[Statement] = {
|
||||
parseAll(statements, r) match {
|
||||
case Success(res, next) => return res
|
||||
case NoSuccess(msg, next) => sys.error("Config parsing failed at %s: %s".format(next.pos, msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.recipes
|
||||
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.item.Item
|
||||
import scala.reflect.ClassTag
|
||||
import java.lang.reflect.Modifier
|
||||
|
||||
object Vanilla {
|
||||
|
||||
// Maps of vanilla blocks and items (without tile. / item. prefixes)
|
||||
|
||||
lazy val blocks = mkMap[Block](_.getUnlocalizedName.stripPrefix("tile.")).withDefault(x => throw new StatementError("Block %s not found".format(x)))
|
||||
lazy val items = mkMap[Item](_.getUnlocalizedName.stripPrefix("item.")).withDefault(x => throw new StatementError("Item %s not found".format(x)))
|
||||
|
||||
/**
|
||||
* Generates the maps
|
||||
* @tparam T The base class
|
||||
* @param namer A function that converts objects to names
|
||||
*/
|
||||
private def mkMap[T](namer: T => String)(implicit t: ClassTag[T]) = {
|
||||
val c = t.runtimeClass
|
||||
// Grab all the fields
|
||||
c.getFields.filter(x => {
|
||||
// Keep only static fields that match the base Class
|
||||
c.isAssignableFrom(x.getType) && Modifier.isStatic(x.getModifiers)
|
||||
}).map(x => {
|
||||
// Retrieve the static value
|
||||
val f = x.get(null).asInstanceOf[T]
|
||||
// Convert to name -> object tuples
|
||||
namer(f) -> f
|
||||
}).toMap // and finally to a map
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.recipes.gencfg
|
||||
|
||||
abstract class CfgEntry
|
||||
|
||||
case class EntryDouble(v: Double) extends CfgEntry
|
||||
|
||||
case class EntryStr(v: String) extends CfgEntry
|
||||
|
||||
case class ConfigSection(pfx: String = "") extends CfgEntry with Iterable[(String, CfgEntry)] {
|
||||
var raw = Map.empty[String, CfgEntry].withDefault(x => sys.error("Config value '%s%s' is missing".format(pfx,x)))
|
||||
|
||||
def iterator: Iterator[(String, CfgEntry)] = raw.iterator
|
||||
def filterType[T<:CfgEntry](cls: Class[T]): Iterable[(String,T)] = raw.filter(x=>cls.isInstance(x._2)).map(x=>x.asInstanceOf[(String,T)])
|
||||
|
||||
def rawget[T](id: String, t: Class[T]): T = {
|
||||
val v = raw(id)
|
||||
if (t.isInstance(v))
|
||||
return v.asInstanceOf[T]
|
||||
else
|
||||
sys.error("Config value '%s%s' is of the wrong type, expected %s, got %s".format(pfx, id, t.getName, v.getClass.getName))
|
||||
}
|
||||
|
||||
def set(id: String, v: CfgEntry) = raw += id -> v
|
||||
|
||||
def getDouble(id: String) = rawget(id, classOf[EntryDouble]).v
|
||||
def getString(id: String) = rawget(id, classOf[EntryStr]).v
|
||||
def getSection(id: String) = rawget(id, classOf[ConfigSection])
|
||||
|
||||
|
||||
final val trueVals = Set("y", "true", "yes", "on")
|
||||
def getBoolean(id: String) = trueVals.contains(getString(id).toLowerCase)
|
||||
|
||||
def getOrAddSection(id: String) = {
|
||||
if (raw.isDefinedAt(id)) {
|
||||
rawget(id, classOf[ConfigSection])
|
||||
} else {
|
||||
val newSection = new ConfigSection(pfx + id + ".")
|
||||
set(id, newSection)
|
||||
newSection
|
||||
}
|
||||
}
|
||||
|
||||
def getInt(id: String) = getDouble(id).round.toInt
|
||||
def getFloat(id: String) = getDouble(id).toFloat
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.recipes.gencfg
|
||||
|
||||
import net.bdew.lib.recipes.Statement
|
||||
|
||||
abstract class CfgStatement
|
||||
|
||||
case class CfgVal(id: String, value: CfgEntry) extends CfgStatement
|
||||
|
||||
case class CfgSub(id: String, vals: List[CfgStatement]) extends CfgStatement
|
||||
|
||||
case class StCfg(id: String, vals: List[CfgStatement]) extends Statement
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.recipes.gencfg
|
||||
|
||||
import net.bdew.lib.recipes.{Statement, RecipeLoader}
|
||||
|
||||
trait GenericConfigLoader extends RecipeLoader {
|
||||
val cfgStore: ConfigSection
|
||||
|
||||
def processConfigStatement(section: ConfigSection, s: CfgStatement): Unit = s match {
|
||||
case CfgVal(id, v) =>
|
||||
log.info("Config: %s%s = %s".format(section.pfx, id, v))
|
||||
section.set(id, v)
|
||||
case CfgSub(id, st) => processConfigBlock(section.getOrAddSection(id), st)
|
||||
case x =>
|
||||
log.severe("Can't process %s - this is a programing bug!".format(x))
|
||||
}
|
||||
|
||||
def processConfigBlock(view: ConfigSection, block: List[CfgStatement]) = for (s <- block) processConfigStatement(view, s)
|
||||
|
||||
override def processStatement(s: Statement) = s match {
|
||||
case StCfg(id, st) => processConfigBlock(cfgStore.getOrAddSection(id), st)
|
||||
case _ => super.processStatement(s)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.recipes.gencfg
|
||||
|
||||
import net.bdew.lib.recipes.RecipeParser
|
||||
|
||||
trait GenericConfigParser extends RecipeParser {
|
||||
override def statement = statementCfg | super.statement
|
||||
def cfgStatementNum = ident ~ "=" ~ decimalNumber ^^ { case id ~ eq ~ n => CfgVal(id, EntryDouble(n.toDouble)) }
|
||||
def cfgStatementStr = ident ~ "=" ~ str ^^ { case id ~ eq ~ s => CfgVal(id, EntryStr(s)) }
|
||||
def cfgStatementSub = cfgBlock ^^ { case (id, st) => CfgSub(id, st) }
|
||||
|
||||
def cfgStatement = cfgStatementNum | cfgStatementStr | cfgStatementSub
|
||||
|
||||
// A bit of type acrobatics because this is recursive (via cfgStatementSub), the tuple is translated into the proper class in either cfgStatementSub or cfg
|
||||
def cfgBlock: Parser[(String, List[CfgStatement])] = "cfg" ~> ident ~ ("{" ~> cfgStatement.* <~ "}") ^^ { case id ~ st => (id, st) }
|
||||
|
||||
def statementCfg = cfgBlock ^^ { case (id, st) => StCfg(id, st) }
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.rotate
|
||||
|
||||
import cpw.mods.fml.relauncher.Side
|
||||
import cpw.mods.fml.relauncher.SideOnly
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.entity.EntityLivingBase
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.util.Icon
|
||||
import net.minecraft.util.MathHelper
|
||||
import net.minecraft.world.IBlockAccess
|
||||
import net.minecraft.world.World
|
||||
import net.minecraftforge.common.ForgeDirection
|
||||
import java.util.EnumSet
|
||||
|
||||
/**
|
||||
* Basic logic for block rotatation
|
||||
*/
|
||||
trait BaseRotateableBlock extends Block {
|
||||
|
||||
/**
|
||||
* Override this method to provide your textures, also called when rendering as item
|
||||
*/
|
||||
def getIcon(meta: Int, kind: IconType.Value): Icon
|
||||
|
||||
/**
|
||||
* Override this method to provide your textures, if you need to check other state
|
||||
*/
|
||||
def getIcon(world: IBlockAccess, x: Int, y: Int, z: Int, kind: IconType.Value): Icon = getIcon(world.getBlockMetadata(x, y, z), kind)
|
||||
|
||||
/**
|
||||
* Set of valid rotations, default is all of them
|
||||
*/
|
||||
def getValidFacings: EnumSet[ForgeDirection] = {
|
||||
return EnumSet.allOf(classOf[ForgeDirection])
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotation to show when it's unavailable (like rendering item in inventory)
|
||||
*/
|
||||
def getDefaultFacing: ForgeDirection = ForgeDirection.UP
|
||||
|
||||
/**
|
||||
* Those will be overrided to provide concrete storage
|
||||
*/
|
||||
def setFacing(world: World, x: Int, y: Int, z: Int, facing: ForgeDirection)
|
||||
def getFacing(world: IBlockAccess, x: Int, y: Int, z: Int): ForgeDirection
|
||||
|
||||
override def rotateBlock(worldObj: World, x: Int, y: Int, z: Int, axis: ForgeDirection): Boolean = {
|
||||
if (getValidFacings.contains(axis)) {
|
||||
setFacing(worldObj, x, y, z, axis)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
override def getIcon(side: Int, meta: Int): Icon = getIcon(meta, IconType.fromSideAndDir(side, getDefaultFacing))
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
override def getBlockTexture(world: IBlockAccess, x: Int, y: Int, z: Int, side: Int): Icon = getIcon(world, x, y, z, IconType.fromSideAndDir(side, getFacing(world, x, y, z)))
|
||||
|
||||
override def getValidRotations(worldObj: World, x: Int, y: Int, z: Int): Array[ForgeDirection] = getValidFacings.toArray(Array.empty[ForgeDirection])
|
||||
|
||||
override def onBlockPlacedBy(world: World, x: Int, y: Int, z: Int, ent: EntityLivingBase, stack: ItemStack) {
|
||||
val validRotations = getValidFacings
|
||||
var dir = getDefaultFacing
|
||||
if (ent != null) {
|
||||
val pitch: Int = Math.round(ent.rotationPitch)
|
||||
val yaw: Int = MathHelper.floor_double(ent.rotationYaw * 4.0F / 360.0F + 0.5D) & 3
|
||||
dir = yaw match {
|
||||
case _ if pitch >= 50 && validRotations.contains(ForgeDirection.UP) => ForgeDirection.UP
|
||||
case _ if pitch <= -50 && validRotations.contains(ForgeDirection.DOWN) => ForgeDirection.DOWN
|
||||
case 0 if validRotations.contains(ForgeDirection.NORTH) => ForgeDirection.NORTH
|
||||
case 1 if validRotations.contains(ForgeDirection.EAST) => ForgeDirection.EAST
|
||||
case 2 if validRotations.contains(ForgeDirection.SOUTH) => ForgeDirection.SOUTH
|
||||
case 3 if validRotations.contains(ForgeDirection.WEST) => ForgeDirection.WEST
|
||||
case _ => dir
|
||||
}
|
||||
}
|
||||
setFacing(world, x, y, z, dir)
|
||||
super.onBlockPlacedBy(world, x, y, z, ent, stack)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.rotate
|
||||
|
||||
import net.minecraftforge.common.ForgeDirection
|
||||
|
||||
object IconType extends Enumeration {
|
||||
val BACK = Value(0, "BACK")
|
||||
val FRONT = Value(1, "FRONT")
|
||||
val SIDE = Value(2, "SIDE")
|
||||
|
||||
def fromSideAndDir(side: Int, facing: ForgeDirection) = this(metaSideMap(side)(facing.ordinal))
|
||||
|
||||
val metaSideMap = Array(
|
||||
Array(1, 0, 2, 2, 2, 2),
|
||||
Array(0, 1, 2, 2, 2, 2),
|
||||
Array(2, 2, 1, 0, 2, 2),
|
||||
Array(2, 2, 0, 1, 2, 2),
|
||||
Array(2, 2, 2, 2, 1, 0),
|
||||
Array(2, 2, 2, 2, 0, 1))
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.rotate
|
||||
|
||||
import net.bdew.lib.data.base.{UpdateKind, TileDataSlots}
|
||||
import net.bdew.lib.data.DataSlotDirection
|
||||
|
||||
trait RotateableTile extends TileDataSlots {
|
||||
var rotation = DataSlotDirection("rotation", this).setUpdate(UpdateKind.SAVE, UpdateKind.WORLD)
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.rotate
|
||||
|
||||
import net.minecraft.block.ITileEntityProvider
|
||||
import net.minecraft.world.IBlockAccess
|
||||
import net.minecraft.world.World
|
||||
import net.minecraftforge.common.ForgeDirection
|
||||
import cpw.mods.fml.common.FMLCommonHandler
|
||||
|
||||
/**
|
||||
* Stores rotation data in tile entity. The TE should implement {@link RotateableTile}
|
||||
*/
|
||||
trait RotateableTileBlock extends BaseRotateableBlock with ITileEntityProvider {
|
||||
def setFacing(world: World, x: Int, y: Int, z: Int, facing: ForgeDirection) {
|
||||
world.getBlockTileEntity(x, y, z).asInstanceOf[RotateableTile].rotation := facing
|
||||
}
|
||||
|
||||
def getFacing(world: IBlockAccess, x: Int, y: Int, z: Int): ForgeDirection = {
|
||||
val te: RotateableTile = world.getBlockTileEntity(x, y, z).asInstanceOf[RotateableTile]
|
||||
if (te == null || te.rotation == null) {
|
||||
FMLCommonHandler.instance().getFMLLogger.warning("Failed gettig rocation for block at %d, %d, %d".format(x, y, z))
|
||||
return getDefaultFacing
|
||||
}
|
||||
return te.rotation
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.tile
|
||||
|
||||
trait Component {
|
||||
def added(p: TileExtended, name: String)
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.tile
|
||||
|
||||
import net.minecraft.tileentity.TileEntity
|
||||
import net.minecraftforge.fluids._
|
||||
import net.minecraftforge.common.ForgeDirection
|
||||
|
||||
trait ExposeTank extends TileEntity with IFluidHandler {
|
||||
def getTankFromDirection(dir: ForgeDirection): IFluidTank
|
||||
|
||||
def fill(from: ForgeDirection, resource: FluidStack, doFill: Boolean): Int = {
|
||||
val tank = getTankFromDirection(from)
|
||||
if (tank == null) return 0
|
||||
return tank.fill(resource, doFill)
|
||||
}
|
||||
|
||||
def drain(from: ForgeDirection, resource: FluidStack, doDrain: Boolean): FluidStack = {
|
||||
val tank = getTankFromDirection(from)
|
||||
if (tank == null || resource == null || !resource.isFluidEqual(tank.getFluid)) return null
|
||||
return tank.drain(resource.amount, doDrain)
|
||||
}
|
||||
|
||||
def drain(from: ForgeDirection, maxDrain: Int, doDrain: Boolean): FluidStack = {
|
||||
val tank = getTankFromDirection(from)
|
||||
if (tank == null) return null
|
||||
getTankFromDirection(from).drain(maxDrain, doDrain)
|
||||
}
|
||||
|
||||
def canFill(from: ForgeDirection, fluid: Fluid): Boolean = getTankFromDirection(from) != null
|
||||
|
||||
def canDrain(from: ForgeDirection, fluid: Fluid): Boolean = getTankFromDirection(from) != null
|
||||
|
||||
def getTankInfo(from: ForgeDirection): Array[FluidTankInfo] = {
|
||||
val tank = getTankFromDirection(from)
|
||||
if (tank == null) return Array.empty[FluidTankInfo]
|
||||
return Array(tank.getInfo)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.tile
|
||||
|
||||
import net.minecraft.tileentity.TileEntity
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
import net.minecraft.network.INetworkManager
|
||||
import net.minecraft.network.packet.Packet132TileEntityData
|
||||
import net.bdew.lib.Event
|
||||
|
||||
class TileExtended extends TileEntity {
|
||||
final val ACT_CLIENT = 1
|
||||
final val ACT_GUI = 2
|
||||
|
||||
var clientTick = Event()
|
||||
var serverTick = Event()
|
||||
var persistSave = Event[NBTTagCompound]
|
||||
var persistLoad = Event[NBTTagCompound]
|
||||
var sendClientUpdate = Event[NBTTagCompound]
|
||||
var handleClientUpdate = Event[NBTTagCompound]
|
||||
|
||||
def tickClient() {}
|
||||
def tickServer() {}
|
||||
|
||||
override final def writeToNBT(tag: NBTTagCompound) = {
|
||||
super.writeToNBT(tag)
|
||||
persistSave.trigger(tag)
|
||||
}
|
||||
|
||||
override final def readFromNBT(tag: NBTTagCompound) = {
|
||||
super.readFromNBT(tag)
|
||||
persistLoad.trigger(tag)
|
||||
}
|
||||
|
||||
override final def getDescriptionPacket: Packet132TileEntityData = {
|
||||
if (!sendClientUpdate.hasListeners) return null
|
||||
val tag = new NBTTagCompound
|
||||
sendClientUpdate.trigger(tag)
|
||||
return new Packet132TileEntityData(this.xCoord, this.yCoord, this.zCoord, ACT_CLIENT, tag)
|
||||
}
|
||||
|
||||
override final def onDataPacket(net: INetworkManager, pkt: Packet132TileEntityData) {
|
||||
if (pkt.actionType == ACT_CLIENT)
|
||||
handleClientUpdate.trigger(pkt.data)
|
||||
else
|
||||
extDataPacket(pkt.actionType, pkt.data)
|
||||
}
|
||||
|
||||
override final def updateEntity() {
|
||||
if (worldObj != null) {
|
||||
if (worldObj.isRemote) {
|
||||
tickClient()
|
||||
clientTick.trigger()
|
||||
} else {
|
||||
tickServer()
|
||||
serverTick.trigger()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected def extDataPacket(id: Int, data: NBTTagCompound) {}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.tile.inventory
|
||||
|
||||
import net.minecraft.inventory.IInventory
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
|
||||
trait BaseInventory extends IInventory {
|
||||
var inv: Array[ItemStack] = new Array(getSizeInventory)
|
||||
|
||||
def getStackInSlot(i: Int): ItemStack = inv(i)
|
||||
|
||||
def getInvName = ""
|
||||
|
||||
def isInvNameLocalized = false
|
||||
|
||||
def getInventoryStackLimit = 64
|
||||
|
||||
def isUseableByPlayer(player: EntityPlayer) = true
|
||||
|
||||
def openChest() = Unit
|
||||
|
||||
def closeChest() = Unit
|
||||
|
||||
def isItemValidForSlot(slot: Int, stack: ItemStack) = true
|
||||
|
||||
def decrStackSize(slot: Int, n: Int): ItemStack = {
|
||||
var item = inv(slot)
|
||||
if (item != null) {
|
||||
if (item.stackSize <= n) {
|
||||
inv(slot) = null
|
||||
onInventoryChanged()
|
||||
return item
|
||||
} else {
|
||||
var newstack = item.splitStack(n)
|
||||
if (item.stackSize == 0) {
|
||||
inv(slot) = null
|
||||
}
|
||||
onInventoryChanged()
|
||||
return newstack
|
||||
}
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
def getStackInSlotOnClosing(slot: Int): ItemStack = {
|
||||
var tmp = inv(slot)
|
||||
inv(slot) = null
|
||||
onInventoryChanged()
|
||||
return tmp
|
||||
}
|
||||
|
||||
def setInventorySlotContents(slot: Int, stack: ItemStack) = {
|
||||
inv(slot) = stack
|
||||
onInventoryChanged()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.tile.inventory
|
||||
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.world.World
|
||||
|
||||
trait BreakableInventoryBlock extends Block {
|
||||
override def breakBlock(world: World, x: Int, y: Int, z: Int, blockId: Int, meta: Int) {
|
||||
if (!world.isRemote) {
|
||||
val te = world.getBlockTileEntity(x, y, z).asInstanceOf[BreakableInventoryTile]
|
||||
if (te != null) {
|
||||
te.dropItems()
|
||||
}
|
||||
}
|
||||
super.breakBlock(world, x, y, z, blockId, meta)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.tile.inventory
|
||||
|
||||
import net.minecraft.tileentity.TileEntity
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.bdew.lib.items.ItemUtils
|
||||
|
||||
trait BreakableInventoryTile extends TileEntity with BaseInventory {
|
||||
def dropItems() {
|
||||
if (worldObj != null && !worldObj.isRemote) {
|
||||
for (stack <- inv if stack != null) {
|
||||
ItemUtils.throwItemAt(worldObj, xCoord, yCoord, zCoord, stack)
|
||||
}
|
||||
inv = new Array[ItemStack](inv.size)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.tile.inventory
|
||||
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.nbt.{NBTTagList, NBTTagCompound}
|
||||
import net.bdew.lib.Misc
|
||||
import net.bdew.lib.tile.TileExtended
|
||||
|
||||
trait PersistentInventoryTile extends TileExtended with BaseInventory {
|
||||
persistLoad.listen((tag: NBTTagCompound) => {
|
||||
inv = new Array[ItemStack](getSizeInventory)
|
||||
for (nbtItem <- Misc.iterNbtList[NBTTagCompound](tag.getTagList("Items"))) {
|
||||
val slot = nbtItem.getByte("Slot")
|
||||
if (slot >= 0 && slot < inv.size) {
|
||||
inv(slot) = ItemStack.loadItemStackFromNBT(nbtItem)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
persistSave.listen((tag: NBTTagCompound) => {
|
||||
val itemList = new NBTTagList
|
||||
for ((item, i) <- inv.view.zipWithIndex if item != null) {
|
||||
val itemNbt: NBTTagCompound = new NBTTagCompound
|
||||
itemNbt.setByte("Slot", i.asInstanceOf[Byte])
|
||||
item.writeToNBT(itemNbt)
|
||||
itemList.appendTag(itemNbt)
|
||||
}
|
||||
tag.setTag("Items", itemList)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.tile.inventory
|
||||
|
||||
import net.minecraft.inventory.ISidedInventory
|
||||
import net.minecraft.item.ItemStack
|
||||
|
||||
trait SidedInventory extends BaseInventory with ISidedInventory {
|
||||
var allowSided = false
|
||||
|
||||
def getAccessibleSlotsFromSide(side: Int): Array[Int] = (0 until inv.size).toArray
|
||||
|
||||
def canInsertItem(slot: Int, stack: ItemStack, side: Int) = allowSided && isItemValidForSlot(slot, stack)
|
||||
|
||||
def canExtractItem(slot: Int, stack: ItemStack, side: Int) = allowSided
|
||||
}
|
||||
Reference in new issue
Block a user