1.16 branch initialisation.

This commit is contained in:
stfwi 2020-08-02 15:35:05 +02:00
parent 8c2096befd
commit fc7062117a
2994 changed files with 24 additions and 116949 deletions

23
.gitignore vendored
View file

@ -1,4 +1,6 @@
_*
.classpath
.DS_Store
.gimp
.gradle
.idea
@ -6,8 +8,6 @@
.project
.settings
.vscode
.DS_Store
*~
*.iml
*.ipr
*.iws
@ -16,23 +16,30 @@
*.log
*.tmp
*.xcf
*~
/*.txt
/archive
/assets-src
/classes
/dev
/dist
/src/generated
/src/main/java/archive
/src/main/resources/assets/minecraft
/src/test
/tests
/tmp
tmp
bin
build
desktop.ini
eclipse
forge*changelog.txt
mcmodsrepo
out
run
signing.*
/*/src/generated
/*/src/main/java/archive
/*/src/main/resources/assets/minecraft
/*/tests
_*
/src/main/java/archive
/src/main/resources/assets/minecraft
tests
Thumbs.db
tmp

33
1.12/.gitignore vendored
View file

@ -1,33 +0,0 @@
bin
*.launch
.settings
.metadata
.classpath
.project
out
*.ipr
*.iws
*.iml
.idea
build
.gradle
*.tmp
*.log
*.jks
eclipse
run
tests
/dist
signing.*
src/main/java/archive
src/main/resources/assets/minecraft
.vscode
/classes
/dev
/tmp
/archive
/assets-src
.gimp
*.xcf
desktop.ini
/*.txt

View file

@ -1,89 +0,0 @@
# @file Makefile
# @author Stefan Wilhelm (wile)
# @license MIT
#
# GNU Make makefile based build relay.
# Note for reviewers/clones: This file is a auxiliary script for my setup.
# It's not needed to build the mod.
#
MOD_JAR_PREFIX=engineersdecor-
MOD_JAR=$(filter-out %-sources.jar,$(wildcard build/libs/${MOD_JAR_PREFIX}*.jar))
ifeq ($(OS),Windows_NT)
GRADLE=gradlew.bat --no-daemon
GRADLE_STOP=gradlew.bat --stop
DJS=djs
else
GRADLE=./gradlew --no-daemon
GRADLE_STOP=./gradlew --stop
DJS=djs
endif
TASK=$(DJS) ../meta/lib/tasks.js
wildcardr=$(foreach d,$(wildcard $1*),$(call wildcardr,$d/,$2) $(filter $(subst *,%,$2),$d))
#
# Targets
#
.PHONY: default mod init clean clean-all mrproper all run install sanitize dist-check dist dist-files start-server
default: mod
all: clean clean-all mod | install
mod:
@echo "[1.12] Building mod using gradle ..."
@$(GRADLE) build $(GRADLE_OPTS)
clean:
@echo "[1.12] Cleaning ..."
@rm -f build/libs/*
@$(GRADLE) clean
clean-all: clean
@echo "[1.12] Cleaning using gradle ..."
@rm -f dist/*
@rm -rf run/logs/
@rm -rf run/crash-reports/
@$(GRADLE) clean cleanCache
mrproper: clean-all
@rm -f meta/*.*
@rm -rf run/
@rm -rf out/
@rm -f .project
@rm -f .classpath
init:
@echo "[1.12] Initialising eclipse workspace using gradle ..."
@$(GRADLE) setupDecompWorkspace
run:
@echo "[1.12] Running client ..."
@$(GRADLE) runClient
sanitize:
@echo "[1.12] Running sanitising tasks ..."
@$(TASK) sanitize
@$(TASK) sync-languages
@$(TASK) version-check
@$(TASK) update-json
@git status -s .
install: $(MOD_JAR) |
@$(TASK) install
start-server: install
@$(TASK) start-server
dist-check:
@echo "[1.12] Running dist checks ..."
@$(TASK) dist-check
dist-files: clean-all init mod
@echo "[1.12] Distribution files ..."
@mkdir -p dist
@cp build/libs/$(MOD_JAR_PREFIX)* dist/
@$(TASK) dist
dist: sanitize dist-check dist-files

View file

@ -1,88 +0,0 @@
// @file build.gradle
// Engineer's decor mod gradle build relay (mc1.12.2)
//
buildscript {
repositories {
jcenter()
maven { url = "http://files.minecraftforge.net/maven" }
}
dependencies {
classpath 'net.minecraftforge.gradle:ForgeGradle:2.3-SNAPSHOT'
}
}
apply plugin: 'net.minecraftforge.gradle.forge'
apply plugin: 'idea'
sourceCompatibility = targetCompatibility = '1.8'
compileJava { // Need this here so eclipse task generates correctly.
sourceCompatibility = targetCompatibility = '1.8'
}
//-----------------------------------------------------------------------------
version = "${version_engineersdecor}"
group = "wile.engineersdecor"
archivesBaseName = "engineersdecor-${version_minecraft}"
def signing = { ->
def sp = new Properties()
sp.keystore_file = project.keystore_file
sp.keystore_alias = project.keystore_alias
sp.keystore_pass = project.keystore_pass
sp.keystore_keypass = project.keystore_keypass
sp.fingerprint_sha1 = project.fingerprint_sha1
if(file("signing.properties").exists()) file("signing.properties").withInputStream { sp.load(it) }
return sp
}()
def git_version = { ->
def stdout = new ByteArrayOutputStream()
exec {
commandLine 'git', 'log', '-1', '--format=%h'
standardOutput = stdout
}
return stdout.toString().trim()
}()
minecraft {
version = "${version_minecraft}-${version_forge}"
runDir = "run"
mappings = "stable_39"
replace '@MOD_BUILDID@', "#${git_version}"
replace '@MOD_SIGNSHA1@', signing.getProperty('fingerprint_sha1')
replace '@MOD_VERSION@', "${version_engineersdecor}"
replace '@MOD_MCVERSION@', "${version_minecraft}"
replaceIn "ModEngineersDecor.java"
}
repositories {
maven { name = "Progwml6 maven"; url = "https://dvs1.progwml6.com/files/maven/" } // JEI files
maven { name = "ModMaven"; url = "modmaven.k-4u.nl" } // JEI files, fallback
}
dependencies {
deobfProvided "mezz.jei:jei_${version_minecraft}:${version_jei}:api"
runtime "mezz.jei:jei_${version_minecraft}:${version_jei}"
}
processResources {
inputs.property "version", project.version
inputs.property "mcversion", project.minecraft.version
from(sourceSets.main.resources.srcDirs) {
include 'mcmod.info'
expand 'version':project.version, 'mcversion':project.minecraft.version
}
from(sourceSets.main.resources.srcDirs) {
exclude 'mcmod.info'
}
}
task signJar(type: SignJar, dependsOn: reobfJar) {
onlyIf { signing.getProperty("keystore_file") }
keyStore = signing.getProperty("keystore_file")
alias = signing.getProperty("keystore_alias")
storePass = signing.getProperty("keystore_pass")
keyPass = signing.getProperty("keystore_keypass")
inputFile = jar.archivePath
outputFile = jar.archivePath
}
build.dependsOn signJar
// EOF

View file

@ -1,7 +0,0 @@
# @file gradle.properties
org.gradle.daemon=false
org.gradle.jvmargs=-Xmx8G
version_minecraft=1.12.2
version_forge=14.23.5.2768
version_jei=4.10.0.198
version_engineersdecor=1.1.2-b1

Binary file not shown.

View file

@ -1,6 +0,0 @@
#Sun Nov 25 15:35:29 CET 2018
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-bin.zip

164
1.12/gradlew vendored
View file

@ -1,164 +0,0 @@
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((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 "$@"

90
1.12/gradlew.bat vendored
View file

@ -1,90 +0,0 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem 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=
@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 Windows 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

View file

@ -1,99 +0,0 @@
{
"homepage": "https://www.curseforge.com/minecraft/mc-mods/engineers-decor/",
"1.12.2": {
"1.1.1": "[R] Maintenance release.\n[F] Fixed Snow laying on Steel Mesh Fence (issue #107, thx TheTinyPebble).",
"1.1.1-b1": "[F] Fixed java related startup problem (issue #103, thx madmax3004, erebus42, StormbringerGTX, teagan75).",
"1.1.0": "[R] Maintenance Release build v1.1.0. Changes: * Compatibility fixes. * E-Furnace speed selection bug fixed. * Block Placer improvements. ~ v1.1.0-b3 [/] Version skipped for 1.12.2.",
"1.1.0-b2": "[F] Block Placer defers placements if collidable entities are in the way (issue #98, thx DrakoAlcarus).\n[F] Added Block verification during TE ticking in case devices are moved (issue #101, thx D0CTOR-ZED).",
"1.1.0-b1": "[F] Fixed Electrical Furnace speed sanitizing bug (issue #97, thx therobotmenace).\n[M] Changed Labeled Crate Nesting to circumvent server crashing in combination with the Sponge mod.",
"1.0.20": "[R] Release based on v1.0.20-b6. Release-to-release changes: * Manual back ported. * Steel Mesh Fence Gate back ported. * E-Furnace speed selection switch back ported. * Labeled Crate back ported. * Minor bug fixes, compatibility changes.",
"1.0.20-b6": "[F] Implemented compat related to issue #91.",
"1.0.20-b5": "[A] Back-ported Patchouli based Manual (you need to install Vazkii_'s Patchouli, too).\n[A] Back-ported Steel Mesh Fence Gate.\n[M] Minor back-porting compatibility refractoring.",
"1.0.20-b4": "[F] Fixed TE registration bug for Crate registry-optout (issue #91, thx tyon2006).",
"1.0.20-b3": "[/] Version skipped for 1.12.2.",
"1.0.20-b2": "[A] Backported Electrical Furnace GUI speed selection switch.\n[A] Backported Labeled Crate (storage crate with built-in item frame).",
"1.0.20-b1": "[/] Version skipped for 1.12.2.",
"1.0.19": "[R] Release based on v1.0.19-b4. Release-to-release changes: * Transfer fixes for Tree Cutter / Block Breaker, and Factory hopper. * Cleanups, feature backports * Visual fixes and improvements\n[A] Backport of status display for Tree Cutter, Block Breaker and Solar Panel.",
"1.0.19-b4": "[A] Creative tab opt-out visibility handling added (issue #90, thx pimalel233).",
"1.0.19-b3": "[A] Factory Hopper: Added bottom item handler (CR#227).",
"1.0.19-b2": "[F] Fixed Floor Grating item pass-through jitters (thx Cid).\n[M] Removed obsolete recipe collision testing recipes.",
"1.0.19-b1": "[F] Fixed Tree Cutter / Block Breaker not accepting small energy transfers (thx WindFox, issue #82).",
"1.0.18": "[R] Release based on v1.0.18-b2. Release-to-release changes: * Tree cutter config fixes. * Treated Wood Crafting Table mouse tweaks. * Lang updates.\n[M] Lang update ru_ru (PR#77, thanks Smollet777).",
"1.0.18-b2": "[A] Added Treated Wood Crafting table tweaks (ctrl-shift moves all same stacks from the inventory, mouse wheel over crafting slot increases/decreases crafting grid stacks).\n[F] EN Lang file fixed (issue #76, thx Riverstar907).\n[F] Fixed Tree Cutter not respecting power-required config (thx federsavo, issue #77).",
"1.0.18-b1": "[M] Lang ru_ru updated (Smollet777).",
"1.0.17": "[R] Release based on v1.0.17-b3. Release-to-release changes: * Milking machine added. * Reverse recipes for slab slices added. * Texture and model improvements. * Lang file updates. * Minor bug fixes. * Config options added.\n[M] Updated zh_cn lang file (scikirbypoke).\n[A] Added opt-out config for the Small Tree Cutter.",
"1.0.17-b3": "[F] Fixed Small Block Breaker facings to the horizontal range (issue #70, thx JimMiningWorm).",
"1.0.17-b2": "[A] Reverse recipes for slabs and slab slices added.\n[M] Inset Floor Edge Light slightly thinner, looks better.",
"1.0.17-b1": "[A] Added Milking Machine.\n[M] Window placement improved.\n[M] Made Pipe Valve textures slightly darker to fit IE pipes better when shaded.",
"1.0.16": "[R] Release based on v1.0.16-b3. Release-to-release changes: * Added Gas Concrete blocks/walls/stairs/slabs/slab slices. * Added Fluid Collection Funnel * Crafting yield for Clinker/Slag bricks increased. * Block Placer improvements (cocoa planting) and fixes. * Block breaker compat improvements and fixes. * Recipe compat auto detection fixes. * Feature opt-out and tweak config options for mod packs improved.",
"1.0.16-b3": "[M] Increased slag brick recipe yield to 8.\n[A] Small Block Placer can plant Cocoa.\n[F] Fixed Small Block Placer seed detection issue (issue #64, thx Federsavo).\n[F] Fixed incorrectly enabled alternative recipes for fluid accumulator and check valve when IE is installed.\n[M] Slightly nerfed the Small Solar Panel default peak power output (does not affect existing configurations).",
"1.0.16-b2": "[A] Added Gas Concrete (including slab, wall, stairs, and slab slice).\n[A] Added explicit RF-power-required option for Small Block Breaker and Small Tree Cutter (issue #63).\n[M] Increased clinker brick recipe yield to 8 for the master builders needs.\n[F] Fixed item-on-ground display glitch (issue #61, thx Federsavo for the hint).\n[F] Fixed sign bounding boxes (issue #62, thx angela/themartin).",
"1.0.16-b1": "[A] Added Fluid Collection Funnel.\n[A] Added config opt-outs for Breaker, Placer, Fluid Funnel, Mineral Smelter.\n[A] Added configs tweaks for Small Block Breaker and Small Tree Cutter (cffr#185).\n[F] Fixed Block Placer discarding item metadata/variants while placing (issue #60).\n[F] Fixed Block Breaker duping empty shulker boxes, model updated.",
"1.0.15": "[R] Release based on v1.0.15-b2. Release-to-release changes: * Added Small Block Breaker * Small Tree Cutter fixes and compatability improved. * Crafting table compat fixes.\n[M] Small Tree Cutter log detection bug fixed (issue #59).\n[M] Small Tree Cutter supports Menril chopping (issue #54).",
"1.0.15-b2": "[A] Added Small Block Breaker\n[M] Crafting Table: Allowing NBT \"Damage\" mismatch only items that are declared damagable (issue #56).\n[M] Tree Cutter: Loosened the strict mod namespace requirement for Dynamic Trees log detection (issue #52) to enable checking DT compat mod log blocks.",
"1.0.15-b1": "[A] Added Floor Edge Light.\n[A] Added Factory Block Placer and Planter.",
"1.0.14": "[R] Release based on v1.0.14-b1. Release-to-release changes: * Factory Hopper added. * Small Waste Incinerator improved. * Lang updates. * Recipe fixes.",
"1.0.14-b1": "[A] Factory Hopper added (configurable hopper and item collector).\n[M] Small Waste Incinerator Fifo shifting improved.\n[M] Lang file zh_cn updated (scikirbypoke, PR#53).\n[F] Fixed conditional recipe constant for redstone pipe valve (thx @albert_ac).",
"1.0.13": "[R] Release based on v1.0.13-b2. Release-to-release changes: * Small Tree Cutter device added. * Small Solar Panel added. * Steel Mesh Fence added. * Broad Window Sill added.",
"1.0.13-b2": "[A] Added Steel Mesh Fence.\n[A] Added Broad Window Sill.\n[A] Small Tree Cutter can chop Dynamic Trees, chops at tree trunk radius 7 or higher.",
"1.0.13-b1": "[A] Added Small Solar Panel.\n[A] Added Small Tree Cutter.",
"1.0.12": "[R] Release based on v1.0.12-b2. Release-to-release changes: * Crafting table: Recipe collision resolver added. Items are rendered on the table surface. * Small Mineral Smelter released. * Factory Dropper: Continuous dropping mode added. * Block opacity fixes, window model fixes. * Lang file updates.",
"1.0.12-b2": "[A] Crafting Table: Added recipe collision resolver, also applies to crafting history refabrication.\n[A] Crafting Table: Added rendering of placed items on the top surface of the table.\n[M] Lang files updated.",
"1.0.12-b1": "[A] Mineal Smelter non-experimental now.\n[M] Window submodels stripped (reopened issue #19, thx overchoice).\n[M] Opaque full block light opacity fixed (issue #50, thx Illomiurge).\n[M] Factory Dropper: Added pulse/continuous mode in GUI (issue #51, thx Aristine for the CR).",
"1.0.11": "[R] Release based on v1.0.11-b3. Release-to-release changes: * Steel floor grating improvments. * Minor model box fixes. * Standalone recipes added. * Language updates.",
"1.0.11-b3": "[M] Added missing standalone recipes for pipe valves, passive fluid accumulator, and waste incinerator.",
"1.0.11-b2": "[F] Fixed Floor Grating issue, which could have caused a crash.\n[M] Lang update ru-ru (Shellyoung, PR #47).",
"1.0.11-b1": "[M] Lang update ru-ru (Shellyoung, PR #45).\n[F] Fixed bounding box of the Steel Table.\n[M] Steel Floor Grating: Items fall through.",
"1.0.10": "[R] Release based on v1.0.10-b2. Release-to-release changes: * Steel table added. * Steel floor grating added. * Treated wood side table added. * Exit Sign added. * Recipe fixes.",
"1.0.10-b2": "[A] Steel table added.\n[A] Steel floor grating added.",
"1.0.10-b1": "[A] Treated wood side table added.\n[F] Fixed recipe collision of Metal Rung Ladder (issue #37, thx ProsperCraft for reporting).\n[A] Added Exit Sign (texture design by J. Carver).",
"1.0.9": "[R] Release based on v1.0.9-b3. Release-to-release changes: * Slabs for clinker, concrete, slag bricks. * Slab slices for sheet metals, treated wood, and concretes. * Language updates. * Block hardness adaptions. * 1st/3rd person item model fixes. * Furnace initialisation issue fixed.",
"1.0.9-b3": "[A] Added missing recipes for slabs.\n[A] Added slab slices for IE sheet metals, treated wood, and concretes (stackable \"quater-slabs\").\n[M] Updated 1st/3rd person item model rotations/translations.\n[M] Hardness of valves and furni slightly increased.",
"1.0.9-b2": "[A] Added slabs for Clinker Brick, Slag Brick, Rebar Concrete, and Stained Clinker. Texture variations like the base blocks. Allow fast pick-up (see tooltip help or config).\n[F] Fixed lab/electrical furnace initialisation issue (first item inserted was smelted directly).",
"1.0.9-b1": "[U] Lang file ru_ru updated (PR#31, yaroslav4167).\n[M] Block hardness adaptions (issue #32).",
"1.0.8": "[R] Release based on v1.0.8-b2. Release-to-release changes: * Added factory area sign. * Added stained clinker. * Config opt-out fixes, detailed feature selection possible now. * Recipe adaptions and fixes. * Lang files updated.\n[A] Added stained clinker brick block/stairs. Can be mixed with \"normal\" clinkers.\n[A] Added opt-out option for CTRL-SHIFT tooltips.\n[M] Recipe condition requirements updated, recipes categorized.",
"1.0.8-b2": "[F] Config opt-out fixed (thx IronPiston for the report #30).\n[A] Added opt-out config for detailed including/excluding of features (using registry name wildcard matching).",
"1.0.8-b1": "[A] Added \"Factory area\" sign.\n[M] Electrical furnace recipe changed (hoppers to conveyors).\n[A] Opt-out config options added.\n[F] Lang file fixes for en_us (Angela, PR#29).",
"1.0.7": "[R] Release based on v1.0.7-b2. Release-to-release changes: * Factory dropper added. * Defense system warning sign added. * Warning sign backgrounds adapted. * Standalone recipes added. * Lang files updated.\n[A] Added standalone recipes for signs, factory dropper, and electrical furnace.\n[M] Adapted \"Caution\" sign backgrounds to the yellow defense system warning background.",
"1.0.7-b2": "[A] Added Defense System Warning sign (design by J. Carver).\n[M] Factory dropper non-experimental now. GUI click area tuning. \"Fast drop\" symbol replaced from arrow to dog icon (thx overchoice for that icon).\n[M] Lang files updated.",
"1.0.7-b1": "[M] Factory dropper (config:experimental) button placement fixed, GUI vs external view x/y markers added, internal trigger logic simplified. Thx @overchoice for beta testing!",
"1.0.6": "[R] Release based on v1.0.6-b1. Release-to-release changes: * Fixed FML remapping issue (COULD CAUSE CRASHES). * Small waste incinerator added. * Lang files updated/corrections. * Metal ladder easier to break.\n[A] Added factory dropper (config:experimental).\n[C] Thx to abdurraslan for the detailed issue #25.",
"1.0.6-b1": "[A] Added small waste incinerator (delayed fifo-buffered item disposal).\n[M] Fixed item/block name capitalization (by Voxelo).\n[M] Metal ladders are easier to break/harvest.\n[F] Fixed FML remapping issue by using dedicated IItemHandler instances.",
"1.0.5": "[R] Release based on v1.0.5-b1. Release-to-release changes: * Small electrical passthrough-furnace added. * Passive fluid accumulator added. * Config options added. * Sign plates added. * Minor bug fixes.\n[A] Added sign \"Electrical hazard\"/\"Caution hot wire\".\n[A] Added sign \"Caution dangerous there\" (skull/bones).",
"1.0.5-b1": "[A] Added passive fluid accumulator.\n[A] Added small electrical passthrough-furnace.\n[F] Fixed version check URL.\n[M] Opt-out config options for valves, passive fluid accumulator, and furni.",
"1.0.4": "[R] Release based on v1.0.4-b9. Release-to-release changes: * Crafting table: Quick crafting history re-fab, JEI integration. * Rendering improvements and issue fixes (stairs, ambient occlusion, optifine, etc). * Walls with texture variations. * Thin/thick steel poles with support feet/heads. * Horizontal steel double-T support beams added. * Fluid pipe valves added: Check valve, redstone controlled valve, analog redstone controlled valve. Support pressurized transfer. * Tool tip documentation (CTRL-SHIFT) for stairs added. * Internal code cleanups. * Recipes tuned.\n[E] Added pass-through electrical furnace (experimental, see config).",
"1.0.4-b9": "[F] Inserting fluids with pressurized tag only into IE piping.\n[F] Valve redstone connector rendering does not check for \"can connect redstone\" but only for \"can provide power\".\n[M] Valves are adapted to be detected as pipe by IE.",
"1.0.4-b8": "[F] Fixed stairs rendering without smooth light (thanks rastot9).\n[E] Added passive fluid accumulator (experimental feature, see config).",
"1.0.4-b7": "[F] Fixed recipe loading issue if IE is not installed.\n[M] Valves support IE pressurized fluid transfer.",
"1.0.4-b6": "[A] Added redstone controlled fluid valve.\n[A] Added redstone controlled analog fluid valve.\n[M] Check valve recipe adapted (thanks majijn).",
"1.0.4-b5": "[A] Horizontal steel double-T support beam with pole connections.\n[A] Added fluid pipe check valve (straight, conducts only one way).\n[M] Internal registration block/te handling changed.",
"1.0.4-b4": "[F] Clinker/slag brick wall side cullfacing disabled to prevent texture leaks when connecting to concrete walls.\n[F] Unused treated wood pole texture regions filled (optifine).\n[F] Using mipped cutout format for window multi-layer model (issue #19, thanks rixmswey for reporting and details).\n[M] Recipe tuning, added standalone recipe for all mod blocks.\n[M] In-game CTRL-SHIFT tooltip documentation updated.\n[M] Panzer glass block: Ambient occlusion and light opacity tuned.\n[M] Stairs: Light opacity tuned.\n[A] Tooltip documentation added for mod stairs.\n[E] Horizontal steel double-T support beam (config:experimental).",
"1.0.4-b3": "[A] Added thin (4x4x16) and thick (6x6x16) steel hollow poles.\n[A] Added support head/foot components for thin and thick steel poles.",
"1.0.4-b2": "[A] Added position dependent texture variation to clinker wall, slag brick wall and rebar concrete wall.",
"1.0.4-b1": "[A] Crafting table: JEI integration for recipe placement added.\n[A] Crafting table: History re-fab added, allowing to quickly select and re-craft recent recipes. Selection with arrow buttons, ingredient placement by clicking the result slot. Automatic item distribution on shift-click. Quick-move buttons.\n[F] Crafting table textures modified to prevent optifine glitches on the edges of the legs.",
"1.0.3": "[R] Release based on v1.0.3-b5. Release-to-release changes: * Small laboratory furnace added. * Extensive config options for mod packing and tuning added. * Rendering issues fixes (window bleeding, optifine). * Steel framed window added. * Treated wood pole \"end pieces\" added (two support variants). * Sitting on treated wood stool added including mobs (but not villagers, as these are obviously very upright people). * Lang ru_ru added (github contribution from Yaroslavik). * Creative tab logo changed to mod logo. * Table/crafting table bounding boxes refined. * Standalone \"escape\" recipes added if IE is not installed.",
"1.0.3-b5": "[F] Fixed typo in en-en lang file.\n[F] Fixed IE concrete texture missing bailout in log if IE is not installed.\n[F] Using forge multi-layer models for windows to circumvent glitches.\n[M] Changed creative tab logo to the mod logo.\n[A] Added alternative recipes for crafting table and furnace if main IE ingredients are missing (for \"stand-alone\" mod usage).",
"1.0.3-b4": "[A] Lab furnace supports electrical speedup when a IE external is placed in one of the two auxiliary slots.\n[F] Fixed window rendering issue (issue #15, thanks to ILLOMIURGE).\n[M] Updated ru_ru lang file (Yaroslavik).",
"1.0.3-b3": "[A] Added sitting on treated wood stool, Zombies included.\n[A] Added steel framed window.\n[A] Added treated wood pole support head/foot and heavy duty support.\n[A] Added language Russian language support, thanks to yaroslav4167.\n[A] Added config for furnace smelting speed (percent of vanilla furnace).\n[A] Added config for furnace fuel efficiency (in percent, ref is vanilla).\n[F] Treated pole model changed to circumvent potential texture bleeding.\n[M] Treated wood table bounding box aligned with the legs.\n[M] Treated wood crafting table bounding box aligned with the legs.\n[M] Treated wood window can be vertically placed for rooflights.",
"1.0.3-b2": "[A] Added config options for selective feature opt-outs (soft opt-out).\n[A] Added config skip registration of opt-out features (hard opt-out).\n[A] Added config to disable all internal recipes (for packs).\n[A] Added JEI API adapter for soft opt-outs.\n[A] Added lab furnace recipe override config to smelt ores to nuggets that would normally be smelted into ingots. Can be changed on-the-fly.",
"1.0.3-b1": "[A] Added small laboratory furnace.\n[M] Panzer glass opacity/light level set explicitly 0.",
"1.0.2": "[R] Release based on v1.0.2-b3 * Fixes: Spawning. * Crafting table: Shift-click. * Ladders: Faster climbing/descending. * Concrete: Rebar tiles, tile stairs. * Treated wood: window, windowsill. * Slag brick: wall. * Panzer glass: added. * Recipes: Adaptions, added decompositions.",
"1.0.2-b3": "[A] Added slag brick wall.\n[A] Added wall decomposition recipes.\n[A] Added treated wood window.\n[M] Climbing/descending mod ladders is faster when looking up or down and not sneaking.\n[M] Panzer glass material definition changed.\n[M] Explicitly preventing spawning in and on \"non-full\" blocks of the mod.",
"1.0.2-b2": "[A] Added rebar concrete tile stairs.\n[A] Added treated wood window sill.\n[A] Added decomposition recipes for stairs and tiles.\n[M] Changed stair recipe yield quantity from 9 to 6.",
"1.0.2-b1": "[A] Added rebar concrete tile.\n[A] Added panzer glass (explosion-resistant reinforced glass).\n[M] Treated wood crafting table supports shift-click to transfer stacks between player inventory and crafting table storage (thanks majijn for the hint).",
"1.0.1": "[R] Release based on v1.0.1-b4 * Treated wood crafting table * Clinker brick wall * Treated wood stool * Inset spot light * Recipe fixes * Logo updated",
"1.0.1-b4": "[M] Crafting table keeps inventory and has eight storage slots.\n[M] Adapted inset light strength and harvest tool.\n[M] Crafting table recipe adapted.",
"1.0.1-b3": "[A] Added inset light (glowstone-metal, light level like torch, can be used as floor/ceiling/wall light).\n[M] Crafting table model updated (issue #7, thanks majijn).\n[M] Logo image updated.",
"1.0.1-b2": "[A] Added treated wood crafting table.\n[A] Added treated wood stool.\n[F] Fixed ladder bounding boxes to allow climbing connected trap doors (issue #6, thanks to Forgilageord).\n[M] Improved wall-block connections (wall elements only connect to other walls or gates, as well as to solid blocks if these blocks are in a straight line with at least two wall elements).\n[M] Decor walls are defined \"solid\" on top, so that e.g. torches and redstone tracks can be placed on them.",
"1.0.1-b1": "[F] Fixed missing condition for ie:stone_deco in recipe constants.\n[A] Added clinker brick wall.",
"1.0.0": "[R] Release based on v1.0.0-b4",
"1.0.0-b4": "[F] Fixed vanished recipe for the rebar concrete wall.\n[A] Concrete wall, material: IE concrete.",
"1.0.0-b3": "[A] Textures of rebar concrete and treated wood table improved.\n[A] Added rebar concrete wall.",
"1.0.0-b2": "[A] Added rebar concrete (steel reinforced, expensive, creeper-proof).",
"1.0.0-b1": "[A] Initial structure.\n[A] Added clinker bricks and clinker brick stairs.\n[A] Added slag bricks and slag brick stairs.\n[A] Added metal rung ladder.\n[A] Added staggered metal steps ladder.\n[A] Added treated wood ladder.\n[A] Added treated wood pole.\n[A] Added treated wood table."
},
"promos": {
"1.12.2-recommended": "1.1.1",
"1.12.2-latest": "1.1.1"
}
}

View file

@ -1,546 +0,0 @@
## Engineer's Decor (MC1.12.2)
Mod sources for Minecraft version 1.12.2.
- Description, credits, and features: Please see the readme in the repository root.
- Compiled mod distribution channel is curseforge: https://www.curseforge.com/minecraft/mc-mods/engineers-decor/files.
----
## Version history
~ v1.1.2-b1 [F]
- v1.1.1 [R] Maintenance release.
[F] Fixed Snow laying on Steel Mesh Fence (issue #107, thx TheTinyPebble).
- v1.1.1-b1 [F] Fixed java related startup problem (issue #103, thx madmax3004, erebus42,
StormbringerGTX, teagan75).
-------------------------------------------------------------------
- v1.1.0 [R] Maintenance Release build v1.1.0. Changes:
* Compatibility fixes.
* E-Furnace speed selection bug fixed.
* Block Placer improvements.
-------------------------------------------------------------------
~ v1.1.0-b3 [/] Version skipped for 1.12.2.
- v1.1.0-b2 [F] Block Placer defers placements if collidable entities are in the way (issue #98, thx DrakoAlcarus).
[F] Added Block verification during TE ticking in case devices are moved (issue #101, thx D0CTOR-ZED).
- v1.1.0-b1 [F] Fixed Electrical Furnace speed sanitizing bug (issue #97, thx therobotmenace).
[M] Changed Labeled Crate Nesting to circumvent server crashing
in combination with the Sponge mod.
-------------------------------------------------------------------
- v1.0.20 [R] Release based on v1.0.20-b6. Release-to-release changes:
* Manual back ported.
* Steel Mesh Fence Gate back ported.
* E-Furnace speed selection switch back ported.
* Labeled Crate back ported.
* Minor bug fixes, compatibility changes.
-------------------------------------------------------------------
- v1.0.20-b6 [F] Implemented compat related to issue #91.
- v1.0.20-b5 [A] Back-ported Patchouli based Manual (you need to install Vazkii_'s Patchouli, too).
[A] Back-ported Steel Mesh Fence Gate.
[M] Minor back-porting compatibility refractoring.
- v1.0.20-b4 [F] Fixed TE registration bug for Crate registry-optout (issue #91, thx tyon2006).
- v1.0.20-b3 [/] Version skipped for 1.12.2.
- v1.0.20-b2 [A] Backported Electrical Furnace GUI speed selection switch.
[A] Backported Labeled Crate (storage crate with built-in item frame).
- v1.0.20-b1 [/] Version skipped for 1.12.2.
-------------------------------------------------------------------
- v1.0.19 [R] Release based on v1.0.19-b4. Release-to-release changes:
* Transfer fixes for Tree Cutter / Block Breaker, and Factory hopper.
* Cleanups, feature backports
* Visual fixes and improvements
-------------------------------------------------------------------
[A] Backport of status display for Tree Cutter, Block Breaker and Solar Panel.
- v1.0.19-b4 [A] Creative tab opt-out visibility handling added (issue #90, thx pimalel233).
- v1.0.19-b3 [A] Factory Hopper: Added bottom item handler (CR#227).
- v1.0.19-b2 [F] Fixed Floor Grating item pass-through jitters (thx Cid).
[M] Removed obsolete recipe collision testing recipes.
- v1.0.19-b1 [F] Fixed Tree Cutter / Block Breaker not accepting small energy transfers (thx WindFox, issue #82).
-------------------------------------------------------------------
- v1.0.18 [R] Release based on v1.0.18-b2. Release-to-release changes:
* Tree cutter config fixes.
* Treated Wood Crafting Table mouse tweaks.
* Lang updates.
-------------------------------------------------------------------
[M] Lang update ru_ru (PR#77, thanks Smollet777).
- v1.0.18-b2 [A] Added Treated Wood Crafting table tweaks (ctrl-shift moves all same stacks from the
inventory, mouse wheel over crafting slot increases/decreases crafting grid stacks).
[F] EN Lang file fixed (issue #76, thx Riverstar907).
[F] Fixed Tree Cutter not respecting power-required config (thx federsavo, issue #77).
- v1.0.18-b1 [M] Lang ru_ru updated (Smollet777).
-------------------------------------------------------------------
- v1.0.17 [R] Release based on v1.0.17-b3. Release-to-release changes:
* Milking machine added.
* Reverse recipes for slab slices added.
* Texture and model improvements.
* Lang file updates.
* Minor bug fixes.
* Config options added.
-------------------------------------------------------------------
[M] Updated zh_cn lang file (scikirbypoke).
[A] Added opt-out config for the Small Tree Cutter.
- v1.0.17-b3 [F] Fixed Small Block Breaker facings to the horizontal range (issue #70, thx JimMiningWorm).
- v1.0.17-b2 [A] Reverse recipes for slabs and slab slices added.
[M] Inset Floor Edge Light slightly thinner, looks better.
- v1.0.17-b1 [A] Added Milking Machine.
[M] Window placement improved.
[M] Made Pipe Valve textures slightly darker to fit IE pipes better when shaded.
-------------------------------------------------------------------
- v1.0.16 [R] Release based on v1.0.16-b3. Release-to-release changes:
* Added Gas Concrete blocks/walls/stairs/slabs/slab slices.
* Added Fluid Collection Funnel
* Crafting yield for Clinker/Slag bricks increased.
* Block Placer improvements (cocoa planting) and fixes.
* Block breaker compat improvements and fixes.
* Recipe compat auto detection fixes.
* Feature opt-out and tweak config options for mod packs improved.
-------------------------------------------------------------------
- v1.0.16-b3 [M] Increased slag brick recipe yield to 8.
[A] Small Block Placer can plant Cocoa.
[F] Fixed Small Block Placer seed detection issue (issue #64, thx Federsavo).
[F] Fixed incorrectly enabled alternative recipes for fluid accumulator and check valve
when IE is installed.
[M] Slightly nerfed the Small Solar Panel default peak power output (does not affect
existing configurations).
- v1.0.16-b2 [A] Added Gas Concrete (including slab, wall, stairs, and slab slice).
[A] Added explicit RF-power-required option for Small Block Breaker and Small Tree Cutter (issue #63).
[M] Increased clinker brick recipe yield to 8 for the master builders needs.
[F] Fixed item-on-ground display glitch (issue #61, thx Federsavo for the hint).
[F] Fixed sign bounding boxes (issue #62, thx angela/themartin).
- v1.0.16-b1 [A] Added Fluid Collection Funnel.
[A] Added config opt-outs for Breaker, Placer, Fluid Funnel, Mineral Smelter.
[A] Added configs tweaks for Small Block Breaker and Small Tree Cutter (cffr#185).
[F] Fixed Block Placer discarding item metadata/variants while placing (issue #60).
[F] Fixed Block Breaker duping empty shulker boxes, model updated.
-------------------------------------------------------------------
- v1.0.15 [R] Release based on v1.0.15-b2. Release-to-release changes:
* Added Small Block Breaker
* Small Tree Cutter fixes and compatability improved.
* Crafting table compat fixes.
-------------------------------------------------------------------
[M] Small Tree Cutter log detection bug fixed (issue #59).
[M] Small Tree Cutter supports Menril chopping (issue #54).
- v1.0.15-b2 [A] Added Small Block Breaker
[M] Crafting Table: Allowing NBT "Damage" mismatch only
items that are declared damagable (issue #56).
[M] Tree Cutter: Loosened the strict mod namespace
requirement for Dynamic Trees log detection (issue #52)
to enable checking DT compat mod log blocks.
- v1.0.15-b1 [A] Added Floor Edge Light.
[A] Added Factory Block Placer and Planter.
-------------------------------------------------------------------
- v1.0.14 [R] Release based on v1.0.14-b1. Release-to-release changes:
* Factory Hopper added.
* Small Waste Incinerator improved.
* Lang updates.
* Recipe fixes.
-------------------------------------------------------------------
- v1.0.14-b1 [A] Factory Hopper added (configurable hopper and item collector).
[M] Small Waste Incinerator Fifo shifting improved.
[M] Lang file zh_cn updated (scikirbypoke, PR#53).
[F] Fixed conditional recipe constant for redstone pipe valve (thx @albert_ac).
-------------------------------------------------------------------
- v1.0.13 [R] Release based on v1.0.13-b2. Release-to-release changes:
* Small Tree Cutter device added.
* Small Solar Panel added.
* Steel Mesh Fence added.
* Broad Window Sill added.
-------------------------------------------------------------------
- v1.0.13-b2 [A] Added Steel Mesh Fence.
[A] Added Broad Window Sill.
[A] Small Tree Cutter can chop Dynamic Trees,
chops at tree trunk radius 7 or higher.
- v1.0.13-b1 [A] Added Small Solar Panel.
[A] Added Small Tree Cutter.
-------------------------------------------------------------------
- v1.0.12 [R] Release based on v1.0.12-b2. Release-to-release changes:
* Crafting table: Recipe collision resolver added. Items are
rendered on the table surface.
* Small Mineral Smelter released.
* Factory Dropper: Continuous dropping mode added.
* Block opacity fixes, window model fixes.
* Lang file updates.
-------------------------------------------------------------------
- v1.0.12-b2 [A] Crafting Table: Added recipe collision resolver,
also applies to crafting history refabrication.
[A] Crafting Table: Added rendering of placed items
on the top surface of the table.
[M] Lang files updated.
- v1.0.12-b1 [A] Mineal Smelter non-experimental now.
[M] Window submodels stripped (reopened issue #19, thx overchoice).
[M] Opaque full block light opacity fixed (issue #50, thx Illomiurge).
[M] Factory Dropper: Added pulse/continuous mode in GUI (issue #51,
thx Aristine for the CR).
-------------------------------------------------------------------
- v1.0.11 [R] Release based on v1.0.11-b3. Release-to-release changes:
* Steel floor grating improvments.
* Minor model box fixes.
* Standalone recipes added.
* Language updates.
-------------------------------------------------------------------
- v1.0.11-b3 [M] Added missing standalone recipes for pipe valves, passive
fluid accumulator, and waste incinerator.
- v1.0.11-b2 [F] Fixed Floor Grating issue, which could have caused a crash.
[M] Lang update ru-ru (Shellyoung, PR #47).
- v1.0.11-b1 [M] Lang update ru-ru (Shellyoung, PR #45).
[F] Fixed bounding box of the Steel Table.
[M] Steel Floor Grating: Items fall through.
-------------------------------------------------------------------
- v1.0.10 [R] Release based on v1.0.10-b2. Release-to-release changes:
* Steel table added.
* Steel floor grating added.
* Treated wood side table added.
* Exit Sign added.
* Recipe fixes.
-------------------------------------------------------------------
- v1.0.10-b2 [A] Steel table added.
[A] Steel floor grating added.
- v1.0.10-b1 [A] Treated wood side table added.
[F] Fixed recipe collision of Metal Rung Ladder (issue #37,
thx ProsperCraft for reporting).
[A] Added Exit Sign (texture design by J. Carver).
-------------------------------------------------------------------
- v1.0.9 [R] Release based on v1.0.9-b3. Release-to-release changes:
* Slabs for clinker, concrete, slag bricks.
* Slab slices for sheet metals, treated wood, and concretes.
* Language updates.
* Block hardness adaptions.
* 1st/3rd person item model fixes.
* Furnace initialisation issue fixed.
-------------------------------------------------------------------
- v1.0.9-b3 [A] Added missing recipes for slabs.
[A] Added slab slices for IE sheet metals, treated wood,
and concretes (stackable "quater-slabs").
[M] Updated 1st/3rd person item model rotations/translations.
[M] Hardness of valves and furni slightly increased.
- v1.0.9-b2 [A] Added slabs for Clinker Brick, Slag Brick, Rebar Concrete,
and Stained Clinker. Texture variations like the base blocks.
Allow fast pick-up (see tooltip help or config).
[F] Fixed lab/electrical furnace initialisation issue (first item
inserted was smelted directly).
- v1.0.9-b1 [U] Lang file ru_ru updated (PR#31, yaroslav4167).
[M] Block hardness adaptions (issue #32).
-------------------------------------------------------------------
- v1.0.8 [R] Release based on v1.0.8-b2. Release-to-release changes:
* Added factory area sign.
* Added stained clinker.
* Config opt-out fixes, detailed feature selection possible now.
* Recipe adaptions and fixes.
* Lang files updated.
-------------------------------------------------------------------
[A] Added stained clinker brick block/stairs. Can be mixed with
"normal" clinkers.
[A] Added opt-out option for CTRL-SHIFT tooltips.
[M] Recipe condition requirements updated, recipes categorized.
- v1.0.8-b2 [F] Config opt-out fixed (thx IronPiston for the report #30).
[A] Added opt-out config for detailed including/excluding
of features (using registry name wildcard matching).
- v1.0.8-b1 [A] Added "Factory area" sign.
[M] Electrical furnace recipe changed (hoppers to conveyors).
[A] Opt-out config options added.
[F] Lang file fixes for en_us (Angela, PR#29).
-------------------------------------------------------------------
- v1.0.7 [R] Release based on v1.0.7-b2. Release-to-release changes:
* Factory dropper added.
* Defense system warning sign added.
* Warning sign backgrounds adapted.
* Standalone recipes added.
* Lang files updated.
-------------------------------------------------------------------
[A] Added standalone recipes for signs, factory dropper, and
electrical furnace.
[M] Adapted "Caution" sign backgrounds to the yellow defense
system warning background.
- v1.0.7-b2 [A] Added Defense System Warning sign (design by J. Carver).
[M] Factory dropper non-experimental now. GUI click area tuning.
"Fast drop" symbol replaced from arrow to dog icon (thx
overchoice for that icon).
[M] Lang files updated.
- v1.0.7-b1 [M] Factory dropper (config:experimental) button placement fixed,
GUI vs external view x/y markers added, internal trigger logic
simplified. Thx @overchoice for beta testing!
-------------------------------------------------------------------
- v1.0.6 [R] Release based on v1.0.6-b1. Release-to-release changes:
* Fixed FML remapping issue (COULD CAUSE CRASHES).
* Small waste incinerator added.
* Lang files updated/corrections.
* Metal ladder easier to break.
-------------------------------------------------------------------
[A] Added factory dropper (config:experimental).
[C] Thx to abdurraslan for the detailed issue #25.
- v1.0.6-b1 [A] Added small waste incinerator (delayed fifo-buffered item disposal).
[M] Fixed item/block name capitalization (by Voxelo).
[M] Metal ladders are easier to break/harvest.
[F] Fixed FML remapping issue by using dedicated IItemHandler instances.
-------------------------------------------------------------------
- v1.0.5 [R] Release based on v1.0.5-b1. Release-to-release changes:
* Small electrical passthrough-furnace added.
* Passive fluid accumulator added.
* Config options added.
* Sign plates added.
* Minor bug fixes.
-------------------------------------------------------------------
[A] Added sign "Electrical hazard"/"Caution hot wire".
[A] Added sign "Caution dangerous there" (skull/bones).
- v1.0.5-b1 [A] Added passive fluid accumulator.
[A] Added small electrical passthrough-furnace.
[F] Fixed version check URL.
[M] Opt-out config options for valves, passive fluid accumulator,
and furni.
-------------------------------------------------------------------
- v1.0.4 [R] Release based on v1.0.4-b9. Release-to-release changes:
* Crafting table: Quick crafting history re-fab, JEI integration.
* Rendering improvements and issue fixes (stairs, ambient occlusion,
optifine, etc).
* Walls with texture variations.
* Thin/thick steel poles with support feet/heads.
* Horizontal steel double-T support beams added.
* Fluid pipe valves added: Check valve, redstone controlled valve,
analog redstone controlled valve. Support pressurized transfer.
* Tool tip documentation (CTRL-SHIFT) for stairs added.
* Internal code cleanups.
* Recipes tuned.
-------------------------------------------------------------------
[E] Added pass-through electrical furnace (experimental, see config).
- v1.0.4-b9 [F] Inserting fluids with pressurized tag only into IE piping.
[F] Valve redstone connector rendering does not check for
"can connect redstone" but only for "can provide power".
[M] Valves are adapted to be detected as pipe by IE.
- v1.0.4-b8 [F] Fixed stairs rendering without smooth light (thanks rastot9).
[E] Added passive fluid accumulator (experimental feature, see config).
- v1.0.4-b7 [F] Fixed recipe loading issue if IE is not installed.
[M] Valves support IE pressurized fluid transfer.
- v1.0.4-b6 [A] Added redstone controlled fluid valve.
[A] Added redstone controlled analog fluid valve.
[M] Check valve recipe adapted (thanks majijn).
- v1.0.4-b5 [A] Horizontal steel double-T support beam with pole connections.
[A] Added fluid pipe check valve (straight, conducts only one way).
[M] Internal registration block/te handling changed.
- v1.0.4-b4 [F] Clinker/slag brick wall side cullfacing disabled to prevent
texture leaks when connecting to concrete walls.
[F] Unused treated wood pole texture regions filled (optifine).
[F] Using mipped cutout format for window multi-layer model
(issue #19, thanks rixmswey for reporting and details).
[M] Recipe tuning, added standalone recipe for all mod blocks.
[M] In-game CTRL-SHIFT tooltip documentation updated.
[M] Panzer glass block: Ambient occlusion and light opacity tuned.
[M] Stairs: Light opacity tuned.
[A] Tooltip documentation added for mod stairs.
[E] Horizontal steel double-T support beam (config:experimental).
- v1.0.4-b3 [A] Added thin (4x4x16) and thick (6x6x16) steel hollow poles.
[A] Added support head/foot components for thin and thick steel poles.
- v1.0.4-b2 [A] Added position dependent texture variation to clinker wall,
slag brick wall and rebar concrete wall.
- v1.0.4-b1 [A] Crafting table: JEI integration for recipe placement added.
[A] Crafting table: History re-fab added, allowing to quickly select
and re-craft recent recipes. Selection with arrow buttons,
ingredient placement by clicking the result slot. Automatic
item distribution on shift-click. Quick-move buttons.
[F] Crafting table textures modified to prevent optifine glitches
on the edges of the legs.
-------------------------------------------------------------------
- v1.0.3 [R] Release based on v1.0.3-b5. Release-to-release changes:
* Small laboratory furnace added.
* Extensive config options for mod packing and tuning added.
* Rendering issues fixes (window bleeding, optifine).
* Steel framed window added.
* Treated wood pole "end pieces" added (two support variants).
* Sitting on treated wood stool added including mobs (but not
villagers, as these are obviously very upright people).
* Lang ru_ru added (github contribution from Yaroslavik).
* Creative tab logo changed to mod logo.
* Table/crafting table bounding boxes refined.
* Standalone "escape" recipes added if IE is not installed.
-------------------------------------------------------------------
- v1.0.3-b5 [F] Fixed typo in en-en lang file.
[F] Fixed IE concrete texture missing bailout in log if IE is not installed.
[F] Using forge multi-layer models for windows to circumvent glitches.
[M] Changed creative tab logo to the mod logo.
[A] Added alternative recipes for crafting table and furnace if main
IE ingredients are missing (for "stand-alone" mod usage).
- v1.0.3-b4 [A] Lab furnace supports electrical speedup when a IE external
is placed in one of the two auxiliary slots.
[F] Fixed window rendering issue (issue #15, thanks to ILLOMIURGE).
[M] Updated ru_ru lang file (Yaroslavik).
- v1.0.3-b3 [A] Added sitting on treated wood stool, Zombies included.
[A] Added steel framed window.
[A] Added treated wood pole support head/foot and heavy duty support.
[A] Added language Russian language support, thanks to yaroslav4167.
[A] Added config for furnace smelting speed (percent of vanilla furnace).
[A] Added config for furnace fuel efficiency (in percent, ref is vanilla).
[F] Treated pole model changed to circumvent potential texture bleeding.
[M] Treated wood table bounding box aligned with the legs.
[M] Treated wood crafting table bounding box aligned with the legs.
[M] Treated wood window can be vertically placed for rooflights.
- v1.0.3-b2 [A] Added config options for selective feature opt-outs (soft opt-out).
[A] Added config skip registration of opt-out features (hard opt-out).
[A] Added config to disable all internal recipes (for packs).
[A] Added JEI API adapter for soft opt-outs.
[A] Added lab furnace recipe override config to smelt ores to nuggets
that would normally be smelted into ingots. Can be changed on-the-fly.
- v1.0.3-b1 [A] Added small laboratory furnace.
[M] Panzer glass opacity/light level set explicitly 0.
-------------------------------------------------------------------
- v1.0.2 [R] Release based on v1.0.2-b3
* Fixes: Spawning.
* Crafting table: Shift-click.
* Ladders: Faster climbing/descending.
* Concrete: Rebar tiles, tile stairs.
* Treated wood: window, windowsill.
* Slag brick: wall.
* Panzer glass: added.
* Recipes: Adaptions, added decompositions.
-------------------------------------------------------------------
- v1.0.2-b3 [A] Added slag brick wall.
[A] Added wall decomposition recipes.
[A] Added treated wood window.
[M] Climbing/descending mod ladders is faster when
looking up or down and not sneaking.
[M] Panzer glass material definition changed.
[M] Explicitly preventing spawning in and on "non-full"
blocks of the mod.
- v1.0.2-b2 [A] Added rebar concrete tile stairs.
[A] Added treated wood window sill.
[A] Added decomposition recipes for stairs and tiles.
[M] Changed stair recipe yield quantity from 9 to 6.
- v1.0.2-b1 [A] Added rebar concrete tile.
[A] Added panzer glass (explosion-resistant reinforced glass).
[M] Treated wood crafting table supports shift-click to transfer
stacks between player inventory and crafting table storage
(thanks majijn for the hint).
-------------------------------------------------------------------
- v1.0.1 [R] Release based on v1.0.1-b4
* Treated wood crafting table
* Clinker brick wall
* Treated wood stool
* Inset spot light
* Recipe fixes
* Logo updated
-------------------------------------------------------------------
- v1.0.1-b4 [M] Crafting table keeps inventory and has eight storage slots.
[M] Adapted inset light strength and harvest tool.
[M] Crafting table recipe adapted.
- v1.0.1-b3 [A] Added inset light (glowstone-metal, light level like torch,
can be used as floor/ceiling/wall light).
[M] Crafting table model updated (issue #7, thanks majijn).
[M] Logo image updated.
- v1.0.1-b2 [A] Added treated wood crafting table.
[A] Added treated wood stool.
[F] Fixed ladder bounding boxes to allow climbing connected trap doors
(issue #6, thanks to Forgilageord).
[M] Improved wall-block connections (wall elements only connect to other
walls or gates, as well as to solid blocks if these blocks are in
a straight line with at least two wall elements).
[M] Decor walls are defined "solid" on top, so that e.g. torches and
redstone tracks can be placed on them.
- v1.0.1-b1 [F] Fixed missing condition for ie:stone_deco in recipe constants.
[A] Added clinker brick wall.
-------------------------------------------------------------------
- v1.0.0 [R] Release based on v1.0.0-b4
-------------------------------------------------------------------
- v1.0.0-b4 [F] Fixed vanished recipe for the rebar concrete wall.
[A] Concrete wall, material: IE concrete.
- v1.0.0-b3 [A] Textures of rebar concrete and treated wood table improved.
[A] Added rebar concrete wall.
- v1.0.0-b2 [A] Added rebar concrete (steel reinforced, expensive, creeper-proof).
- v1.0.0-b1 [A] Initial structure.
[A] Added clinker bricks and clinker brick stairs.
[A] Added slag bricks and slag brick stairs.
[A] Added metal rung ladder.
[A] Added staggered metal steps ladder.
[A] Added treated wood ladder.
[A] Added treated wood pole.
[A] Added treated wood table.
----

View file

@ -1,18 +0,0 @@
/*
* BluSunrize
* Copyright (c) 2017
*
* This code is licensed under "Blu's License of Common Sense"
* Details can be found in the license file in the root folder of this project
*/
package blusunrize.immersiveengineering.api.fluid;
import net.minecraft.util.EnumFacing;
public interface IFluidPipe
{
boolean canOutputPressurized(boolean consumePower);
boolean hasOutputConnection(EnumFacing side);
}

View file

@ -1,747 +0,0 @@
/*
* @file ModBlocks.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2018 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Definition and initialisation of blocks of this
* module, along with their tile entities if applicable.
*
* Note: Straight forward definition of different blocks/entities
* to make recipes, models and texture definitions easier.
*/
package wile.engineersdecor;
import wile.engineersdecor.blocks.*;
import wile.engineersdecor.detail.ModAuxiliaries;
import wile.engineersdecor.detail.ModConfig;
import wile.engineersdecor.detail.ModTesrs;
import wile.engineersdecor.items.ItemDecor;
import net.minecraft.block.Block;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
import net.minecraft.item.Item;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.ModelLoader;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.fml.client.registry.ClientRegistry;
import net.minecraftforge.fml.common.registry.GameRegistry;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import javax.annotation.Nonnull;
@SuppressWarnings("unused")
public class ModContent
{
//--------------------------------------------------------------------------------------------------------------------
//-- Blocks
//--------------------------------------------------------------------------------------------------------------------
public static final BlockDecorFull CLINKER_BRICK_BLOCK = new BlockDecorFull("clinker_brick_block", 0, Material.ROCK, 2f, 15f, SoundType.STONE);
public static final BlockDecorStairs CLINKER_BRICK_STAIRS = new BlockDecorStairs("clinker_brick_stairs", CLINKER_BRICK_BLOCK.getDefaultState());
public static final BlockDecorWall CLINKER_BRICK_WALL = new BlockDecorWall("clinker_brick_wall", BlockDecor.CFG_DEFAULT, Material.ROCK, 2f, 20f, SoundType.STONE);
public static final BlockDecorSlab CLINKER_BRICK_SLAB = new BlockDecorSlab("clinker_brick_slab", BlockDecor.CFG_DEFAULT, Material.ROCK, 2f, 20f, SoundType.STONE);
public static final BlockDecorFull CLINKER_BRICK_STAINED_BLOCK = new BlockDecorFull("clinker_brick_stained_block", 0, Material.ROCK, 2f, 15f, SoundType.STONE);
public static final BlockDecorStairs CLINKER_BRICK_STAINED_STAIRS = new BlockDecorStairs("clinker_brick_stained_stairs", CLINKER_BRICK_STAINED_BLOCK.getDefaultState());
public static final BlockDecorSlab CLINKER_BRICK_STAINED_SLAB = new BlockDecorSlab("clinker_brick_stained_slab", BlockDecor.CFG_DEFAULT, Material.ROCK, 2f, 20f, SoundType.STONE);
public static final BlockDecorFull SLAG_BRICK_BLOCK = new BlockDecorFull("slag_brick_block", 0, Material.ROCK, 2f, 15f, SoundType.STONE);
public static final BlockDecorStairs SLAG_BRICK_STAIRS = new BlockDecorStairs("slag_brick_stairs", SLAG_BRICK_BLOCK.getDefaultState());
public static final BlockDecorWall SLAG_BRICK_WALL = new BlockDecorWall("slag_brick_wall", BlockDecor.CFG_DEFAULT, Material.ROCK, 2f, 15f, SoundType.STONE);
public static final BlockDecorSlab SLAG_BRICK_SLAB = new BlockDecorSlab("slag_brick_slab", BlockDecor.CFG_DEFAULT, Material.ROCK, 2f, 15f, SoundType.STONE);
public static final BlockDecorFull REBAR_CONCRETE_BLOCK = new BlockDecorFull("rebar_concrete", 0, Material.ROCK, 5f, 2000f, SoundType.STONE);
public static final BlockDecorStairs REBAR_CONCRETE_STAIRS = new BlockDecorStairs("rebar_concrete_stairs", REBAR_CONCRETE_BLOCK.getDefaultState());
public static final BlockDecorWall REBAR_CONCRETE_WALL = new BlockDecorWall("rebar_concrete_wall", BlockDecor.CFG_DEFAULT, Material.ROCK, 5f, 2000f, SoundType.STONE);
public static final BlockDecorSlab REBAR_CONCRETE_SLAB = new BlockDecorSlab("rebar_concrete_slab", BlockDecor.CFG_DEFAULT, Material.ROCK, 5f, 2000f, SoundType.STONE);
public static final BlockDecorFull REBAR_CONCRETE_TILE = new BlockDecorFull("rebar_concrete_tile", 0, Material.ROCK, 5f, 2000f, SoundType.STONE);
public static final BlockDecorStairs REBAR_CONCRETE_TILE_STAIRS = new BlockDecorStairs("rebar_concrete_tile_stairs", REBAR_CONCRETE_TILE.getDefaultState());
public static final BlockDecorSlab REBAR_CONCRETE_TILE_SLAB = new BlockDecorSlab("rebar_concrete_tile_slab", BlockDecor.CFG_DEFAULT, Material.ROCK, 5f, 2000f, SoundType.STONE);
public static final BlockDecorWall CONCRETE_WALL = new BlockDecorWall("concrete_wall", BlockDecor.CFG_DEFAULT, Material.ROCK, 5f, 20f, SoundType.STONE);
public static final BlockDecorFull GAS_CONCRETE_BLOCK = new BlockDecorFull("gas_concrete", 0, Material.ROCK, 1.5f, 10f, SoundType.STONE);
public static final BlockDecorStairs GAS_CONCRETE_STAIRS = new BlockDecorStairs("gas_concrete_stairs", REBAR_CONCRETE_BLOCK.getDefaultState());
public static final BlockDecorWall GAS_CONCRETE_WALL = new BlockDecorWall("gas_concrete_wall", BlockDecor.CFG_DEFAULT, Material.ROCK, 1.5f, 10f, SoundType.STONE);
public static final BlockDecorSlab GAS_CONCRETE_SLAB = new BlockDecorSlab("gas_concrete_slab", BlockDecor.CFG_DEFAULT, Material.ROCK, 1.5f, 10f, SoundType.STONE);
public static final BlockDecorLadder METAL_RUNG_LADDER = new BlockDecorLadder("metal_rung_ladder", 0, Material.IRON, 0.5f, 20f, SoundType.METAL);
public static final BlockDecorLadder METAL_RUNG_STEPS = new BlockDecorLadder("metal_rung_steps", 0, Material.IRON, 0.5f, 20f, SoundType.METAL);
public static final BlockDecorLadder TREATED_WOOD_LADDER = new BlockDecorLadder("treated_wood_ladder", 0, Material.WOOD, 0.5f, 10f, SoundType.WOOD);
public static final BlockDecorGlassBlock PANZERGLASS_BLOCK = new BlockDecorGlassBlock("panzerglass_block", 0, Material.GLASS, 1f, 2000f, SoundType.GLASS);
public static final BlockDecorSlab PANZERGLASS_SLAB = new BlockDecorSlab("panzerglass_slab", BlockDecor.CFG_TRANSLUCENT, Material.GLASS, 1f, 2000f, SoundType.GLASS);
public static final BlockDecorFull TREATED_WOOD_FLOOR = new BlockDecorFull("treated_wood_floor", 0, Material.WOOD, 0.5f, 10f, SoundType.WOOD);
//--------------------------------------------------------------------------------------------------------------------
public static final BlockDecorCraftingTable TREATED_WOOD_CRAFTING_TABLE = new BlockDecorCraftingTable(
"treated_wood_crafting_table",
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HORIZIONTAL|BlockDecor.CFG_LOOK_PLACEMENT|BlockDecor.CFG_OPPOSITE_PLACEMENT,
Material.WOOD, 1.0f, 15f, SoundType.WOOD,
ModAuxiliaries.getPixeledAABB(1,0,1, 15,15.9,15)
);
public static final BlockDecorFurnace SMALL_LAB_FURNACE = new BlockDecorFurnace(
"small_lab_furnace",
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HORIZIONTAL|BlockDecor.CFG_LOOK_PLACEMENT|BlockDecor.CFG_OPPOSITE_PLACEMENT|
BlockDecor.CFG_ELECTRICAL,
Material.IRON, 0.5f, 15f, SoundType.METAL,
ModAuxiliaries.getPixeledAABB(1,0,1, 15,15,16)
);
public static final BlockDecorFurnaceElectrical SMALL_ELECTRICAL_FURNACE = new BlockDecorFurnaceElectrical(
"small_electrical_furnace",
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HORIZIONTAL|BlockDecor.CFG_LOOK_PLACEMENT|BlockDecor.CFG_ELECTRICAL,
Material.IRON, 0.5f, 15f, SoundType.METAL,
ModAuxiliaries.getPixeledAABB(0,0,0, 16,16,16)
);
public static final BlockDecorDropper FACTORY_DROPPER = new BlockDecorDropper(
"factory_dropper",
BlockDecor.CFG_LOOK_PLACEMENT|BlockDecor.CFG_REDSTONE_CONTROLLED,
Material.IRON, 1f, 15f, SoundType.METAL,
ModAuxiliaries.getPixeledAABB(0,0,0, 16,16,15)
);
public static final BlockDecorHopper FACTORY_HOPPER = new BlockDecorHopper(
"factory_hopper",
BlockDecor.CFG_FACING_PLACEMENT|BlockDecor.CFG_OPPOSITE_PLACEMENT|BlockDecor.CFG_REDSTONE_CONTROLLED,
Material.IRON, 1f, 15f, SoundType.METAL,
ModAuxiliaries.getPixeledAABB(2,2,2, 14,14,14)
);
public static final BlockDecorPlacer FACTORY_PLACER = new BlockDecorPlacer(
"factory_placer",
BlockDecor.CFG_LOOK_PLACEMENT|BlockDecor.CFG_FLIP_PLACEMENT_SHIFTCLICK|BlockDecor.CFG_REDSTONE_CONTROLLED,
Material.IRON, 1f, 15f, SoundType.METAL,
ModAuxiliaries.getPixeledAABB(2,2,2, 14,14,14)
);
public static final BlockDecorWasteIncinerator SMALL_WASTE_INCINERATOR = new BlockDecorWasteIncinerator(
"small_waste_incinerator",
BlockDecor.CFG_DEFAULT|BlockDecor.CFG_ELECTRICAL,
Material.IRON, 1f, 15f, SoundType.METAL,
ModAuxiliaries.getPixeledAABB(0,0,0, 16,16,16)
);
public static final BlockDecorMineralSmelter SMALL_MINERAL_SMELTER = new BlockDecorMineralSmelter(
"small_mineral_smelter",
BlockDecor.CFG_LOOK_PLACEMENT,
Material.IRON, 1f, 15f, SoundType.METAL,
ModAuxiliaries.getPixeledAABB(1.1,0,1.1, 14.9,16,14.9)
);
public static final BlockDecorMilker SMALL_MILKING_MACHINE = new BlockDecorMilker(
"small_milking_machine",
BlockDecor.CFG_LOOK_PLACEMENT|BlockDecor.CFG_HORIZIONTAL|BlockDecor.CFG_CUTOUT|BlockDecor.CFG_ELECTRICAL,
Material.IRON, 1f, 15f, SoundType.METAL,
ModAuxiliaries.getPixeledAABB(0,0,0, 16,16,13)
);
public static final BlockDecorSolarPanel SMALL_SOLAR_PANEL = new BlockDecorSolarPanel(
"small_solar_panel",
BlockDecor.CFG_LOOK_PLACEMENT,
Material.IRON, 1f, 15f, SoundType.METAL,
ModAuxiliaries.getPixeledAABB(0,0,0, 16,11.5,16)
);
public static final BlockDecorTreeCutter SMALL_TREE_CUTTER = new BlockDecorTreeCutter(
"small_tree_cutter",
BlockDecor.CFG_HORIZIONTAL|BlockDecor.CFG_LOOK_PLACEMENT|BlockDecor.CFG_FLIP_PLACEMENT_SHIFTCLICK,
Material.IRON, 1f, 15f, SoundType.METAL,
ModAuxiliaries.getPixeledAABB(0,0,0, 16,8,16)
);
public static final BlockDecorBreaker SMALL_BLOCK_BREAKER = new BlockDecorBreaker(
"small_block_breaker",
BlockDecor.CFG_HORIZIONTAL|BlockDecor.CFG_LOOK_PLACEMENT|BlockDecor.CFG_FLIP_PLACEMENT_SHIFTCLICK,
Material.IRON, 1f, 15f, SoundType.METAL,
ModAuxiliaries.getPixeledAABB(0,0,0, 16,12,16)
);
//--------------------------------------------------------------------------------------------------------------------
public static final BlockDecorPipeValve STRAIGHT_CHECK_VALVE = new BlockDecorPipeValve(
"straight_pipe_valve",
BlockDecor.CFG_FACING_PLACEMENT|BlockDecor.CFG_OPPOSITE_PLACEMENT|BlockDecor.CFG_FLIP_PLACEMENT_SHIFTCLICK|
BlockDecor.CFG_CUTOUT,
Material.IRON, 0.7f, 15f, SoundType.METAL,
ModAuxiliaries.getPixeledAABB(4,4,0, 12,12,16)
);
public static final BlockDecorPipeValve STRAIGHT_REDSTONE_VALVE = new BlockDecorPipeValve(
"straight_pipe_valve_redstone",
BlockDecor.CFG_FACING_PLACEMENT|BlockDecor.CFG_OPPOSITE_PLACEMENT|BlockDecor.CFG_FLIP_PLACEMENT_SHIFTCLICK|
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_REDSTONE_CONTROLLED,
Material.IRON, 0.7f, 15f, SoundType.METAL,
ModAuxiliaries.getPixeledAABB(4,4,0, 12,12,16)
);
public static final BlockDecorPipeValve STRAIGHT_REDSTONE_ANALOG_VALVE = new BlockDecorPipeValve(
"straight_pipe_valve_redstone_analog",
BlockDecor.CFG_FACING_PLACEMENT|BlockDecor.CFG_OPPOSITE_PLACEMENT|BlockDecor.CFG_FLIP_PLACEMENT_SHIFTCLICK|
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_REDSTONE_CONTROLLED|BlockDecor.CFG_ANALOG,
Material.IRON, 0.7f, 15f, SoundType.METAL,
ModAuxiliaries.getPixeledAABB(4,4,0, 12,12,16)
);
public static final BlockDecorPassiveFluidAccumulator PASSIVE_FLUID_ACCUMULATOR = new BlockDecorPassiveFluidAccumulator(
"passive_fluid_accumulator",
BlockDecor.CFG_FACING_PLACEMENT|BlockDecor.CFG_OPPOSITE_PLACEMENT|BlockDecor.CFG_FLIP_PLACEMENT_SHIFTCLICK|
BlockDecor.CFG_CUTOUT,
Material.IRON, 0.7f, 15f, SoundType.METAL,
ModAuxiliaries.getPixeledAABB(0,0,0, 16,16,16)
);
public static final BlockDecorFluidFunnel SMALL_FLUID_FUNNEL = new BlockDecorFluidFunnel(
"small_fluid_funnel",
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_ELECTRICAL|BlockDecor.CFG_REDSTONE_CONTROLLED,
Material.IRON, 1f, 15f, SoundType.METAL,
ModAuxiliaries.getPixeledAABB(0,0,0, 16,16,16)
);
public static final BlockDecorLabeledCrate LABELED_CRATE = new BlockDecorLabeledCrate(
"labeled_crate",
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HORIZIONTAL|BlockDecor.CFG_LOOK_PLACEMENT|BlockDecor.CFG_OPPOSITE_PLACEMENT,
Material.WOOD, 0.5f, 128f, SoundType.METAL,
ModAuxiliaries.getPixeledAABB(0,0,0, 16,16,16)
);
//--------------------------------------------------------------------------------------------------------------------
public static final BlockDecorStraightPole TREATED_WOOD_POLE = new BlockDecorStraightPole(
"treated_wood_pole",
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_FACING_PLACEMENT,
Material.WOOD, 1.0f, 10f, SoundType.WOOD,
ModAuxiliaries.getPixeledAABB(5.8,5.8,0, 10.2,10.2,16)
);
public static final BlockDecorStraightPole TREATED_WOOD_POLE_HEAD = new BlockDecorStraightPole(
"treated_wood_pole_head",
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_FACING_PLACEMENT|BlockDecor.CFG_FLIP_PLACEMENT_IF_SAME,
Material.WOOD, 1.0f, 10f, SoundType.WOOD,
ModAuxiliaries.getPixeledAABB(5.8,5.8,0, 10.2,10.2,16)
);
public static final BlockDecorStraightPole TREATED_WOOD_POLE_SUPPORT = new BlockDecorStraightPole(
"treated_wood_pole_support",
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_FACING_PLACEMENT|BlockDecor.CFG_FLIP_PLACEMENT_IF_SAME,
Material.WOOD, 1.0f, 10f, SoundType.WOOD,
ModAuxiliaries.getPixeledAABB(5.8,5.8,0, 10.2,10.2,16)
);
public static final BlockDecorStraightPole THIN_STEEL_POLE = new BlockDecorStraightPole(
"thin_steel_pole",
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_FACING_PLACEMENT,
Material.IRON, 2.0f, 15f, SoundType.METAL,
ModAuxiliaries.getPixeledAABB(6,6,0, 10,10,16)
);
public static final BlockDecorStraightPole THIN_STEEL_POLE_HEAD = new BlockDecorStraightPole(
"thin_steel_pole_head",
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_FACING_PLACEMENT|BlockDecor.CFG_FLIP_PLACEMENT_IF_SAME,
Material.IRON, 2.0f, 15f, SoundType.METAL,
ModAuxiliaries.getPixeledAABB(6,6,0, 10,10,16)
);
public static final BlockDecorStraightPole THICK_STEEL_POLE = new BlockDecorStraightPole(
"thick_steel_pole",
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_FACING_PLACEMENT,
Material.IRON, 2.0f, 15f, SoundType.METAL,
ModAuxiliaries.getPixeledAABB(5,5,0, 11,11,16)
);
public static final BlockDecorStraightPole THICK_STEEL_POLE_HEAD = new BlockDecorStraightPole(
"thick_steel_pole_head",
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_FACING_PLACEMENT|BlockDecor.CFG_FLIP_PLACEMENT_IF_SAME,
Material.IRON, 2.0f, 15f, SoundType.METAL,
ModAuxiliaries.getPixeledAABB(5,5,0, 11,11,16)
);
public static final BlockDecorHorizontalSupport STEEL_DOUBLE_T_SUPPORT = new BlockDecorHorizontalSupport(
"steel_double_t_support",
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HORIZIONTAL|BlockDecor.CFG_LOOK_PLACEMENT,
Material.IRON, 2.0f, 15f, SoundType.METAL,
ModAuxiliaries.getPixeledAABB(5,11,0, 11,16,16)
);
//--------------------------------------------------------------------------------------------------------------------
public static final BlockDecorFence STEEL_MESH_FENCE = new BlockDecorFence(
"steel_mesh_fence",
BlockDecor.CFG_CUTOUT, Material.IRON, 2f, 15f, SoundType.METAL
);
public static final BlockDecorDoubleGate STEEL_MESH_FENCE_GATE = new BlockDecorDoubleGate(
"steel_mesh_fence_gate",
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_LOOK_PLACEMENT,
Material.IRON, 2f, 15f, SoundType.METAL,
ModAuxiliaries.getPixeledAABB(0,0,6.5, 16,16,9.5)
);
//--------------------------------------------------------------------------------------------------------------------
public static final BlockDecor TREATED_WOOD_TABLE = new BlockDecor(
"treated_wood_table",
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HORIZIONTAL|BlockDecor.CFG_LOOK_PLACEMENT,
Material.WOOD, 1.0f, 15f, SoundType.WOOD,
ModAuxiliaries.getPixeledAABB(1,0,1, 15,15.9,15)
);
public static final BlockDecorChair TREATED_WOOD_STOOL = new BlockDecorChair(
"treated_wood_stool",
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HORIZIONTAL|BlockDecor.CFG_LOOK_PLACEMENT,
Material.WOOD, 1.0f, 15f, SoundType.WOOD,
ModAuxiliaries.getPixeledAABB(4.1,0,4.1, 11.8,8.8,11.8)
);
public static final BlockDecor TREATED_WOOD_SIDE_TABLE = new BlockDecor(
"treated_wood_side_table",
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HORIZIONTAL|BlockDecor.CFG_LOOK_PLACEMENT,
Material.WOOD, 1.0f, 15f, SoundType.WOOD,
ModAuxiliaries.getPixeledAABB(2,0,2, 14,15.9,14)
);
public static final BlockDecorWindowSill TREATED_WOOD_WINDOWSILL = new BlockDecorWindowSill(
"treated_wood_windowsill",
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HORIZIONTAL|BlockDecor.CFG_FACING_PLACEMENT,
Material.WOOD, 1.0f, 10f, SoundType.WOOD,
ModAuxiliaries.getPixeledAABB(0.5,15,10.5, 15.5,16,16)
);
public static final BlockDecorWindowSill TREATED_WOOD_BROAD_WINDOWSILL = new BlockDecorWindowSill(
"treated_wood_broad_windowsill",
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HORIZIONTAL|BlockDecor.CFG_FACING_PLACEMENT,
Material.WOOD, 1.0f, 10f, SoundType.WOOD,
ModAuxiliaries.getPixeledAABB(0,14.5,4, 16,16,16)
);
public static final BlockDecorDirected INSET_LIGHT_IRON = new BlockDecorDirected(
"iron_inset_light",
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_OPPOSITE_PLACEMENT|(15<<BlockDecor.CFG_LIGHT_VALUE_SHIFT),
Material.IRON, 0.5f, 15f, SoundType.METAL,
ModAuxiliaries.getPixeledAABB(5.2,5.2,15.7, 10.8,10.8,16.0)
);
public static final BlockDecorDirected FLOOR_EDGE_LIGHT_IRON = new BlockDecorDirected(
"iron_floor_edge_light",
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_LOOK_PLACEMENT|BlockDecor.CFG_HORIZIONTAL|(15<<BlockDecor.CFG_LIGHT_VALUE_SHIFT),
Material.IRON, 0.5f, 15f, SoundType.METAL,
ModAuxiliaries.getPixeledAABB(5,0,0, 11,2,1)
);
public static final BlockDecor STEEL_TABLE = new BlockDecor(
"steel_table",
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HORIZIONTAL|BlockDecor.CFG_LOOK_PLACEMENT,
Material.IRON, 1.0f, 15f, SoundType.METAL,
ModAuxiliaries.getPixeledAABB(0,0,0, 16,16,16)
);
public static final BlockDecorFloorGrating STEEL_FLOOR_GRATING = new BlockDecorFloorGrating(
"steel_floor_grating",
BlockDecor.CFG_CUTOUT,
Material.IRON, 1.0f, 15f, SoundType.METAL,
ModAuxiliaries.getPixeledAABB(0,14,0, 16,15.9,16)
);
//--------------------------------------------------------------------------------------------------------------------
public static final BlockDecorWindow TREATED_WOOD_WINDOW = new BlockDecorWindow(
"treated_wood_window",
BlockDecor.CFG_TRANSLUCENT|BlockDecor.CFG_LOOK_PLACEMENT,
Material.WOOD, 0.5f, 10f, SoundType.GLASS,
ModAuxiliaries.getPixeledAABB(0,0,7, 16,16,9)
);
public static final BlockDecorWindow STEEL_FRAMED_WINDOW = new BlockDecorWindow(
"steel_framed_window",
BlockDecor.CFG_TRANSLUCENT|BlockDecor.CFG_LOOK_PLACEMENT,
Material.IRON, 0.5f, 15f, SoundType.GLASS,
ModAuxiliaries.getPixeledAABB(0,0,7.5, 16,16,8.5)
);
//--------------------------------------------------------------------------------------------------------------------
public static final BlockDecorDirected SIGN_MODLOGO = new BlockDecorDirected(
"sign_decor",
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HORIZIONTAL|BlockDecor.CFG_OPPOSITE_PLACEMENT|(1<<BlockDecor.CFG_LIGHT_VALUE_SHIFT),
Material.WOOD, 0.1f, 1000f, SoundType.WOOD,
ModAuxiliaries.getPixeledAABB(0,0,0, 16,16,0.5)
);
public static final BlockDecorDirected SIGN_HOTWIRE = new BlockDecorDirected(
"sign_hotwire",
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HORIZIONTAL|BlockDecor.CFG_OPPOSITE_PLACEMENT|(1<<BlockDecor.CFG_LIGHT_VALUE_SHIFT),
Material.WOOD, 0.1f, 1f, SoundType.WOOD,
ModAuxiliaries.getPixeledAABB(2,2,0, 14,14,0.5)
);
public static final BlockDecorDirected SIGN_MINDSTEP = new BlockDecorDirected(
"sign_mindstep",
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HORIZIONTAL|BlockDecor.CFG_OPPOSITE_PLACEMENT|(1<<BlockDecor.CFG_LIGHT_VALUE_SHIFT),
Material.WOOD, 0.1f, 1f, SoundType.WOOD,
ModAuxiliaries.getPixeledAABB(0,0,0, 16,16,0.5)
);
public static final BlockDecorDirected SIGN_DANGER = new BlockDecorDirected(
"sign_danger",
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HORIZIONTAL|BlockDecor.CFG_OPPOSITE_PLACEMENT|(1<<BlockDecor.CFG_LIGHT_VALUE_SHIFT),
Material.WOOD, 0.1f, 1f, SoundType.WOOD,
ModAuxiliaries.getPixeledAABB(2,2,0, 14,14,0.5)
);
public static final BlockDecorDirected SIGN_DEFENSE = new BlockDecorDirected(
"sign_defense",
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HORIZIONTAL|BlockDecor.CFG_OPPOSITE_PLACEMENT|(1<<BlockDecor.CFG_LIGHT_VALUE_SHIFT),
Material.WOOD, 0.1f, 1f, SoundType.WOOD,
ModAuxiliaries.getPixeledAABB(0,0,0, 16,16,0.5)
);
public static final BlockDecorDirected SIGN_FACTORY_AREA = new BlockDecorDirected(
"sign_factoryarea",
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HORIZIONTAL|BlockDecor.CFG_OPPOSITE_PLACEMENT,
Material.WOOD, 0.1f, 1f, SoundType.WOOD,
ModAuxiliaries.getPixeledAABB(1,1,0, 15,15,0.5)
);
public static final BlockDecorDirected SIGN_EXIT = new BlockDecorDirected(
"sign_exit",
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HORIZIONTAL|BlockDecor.CFG_OPPOSITE_PLACEMENT,
Material.WOOD, 0.1f, 1f, SoundType.WOOD,
ModAuxiliaries.getPixeledAABB(3,7,0, 13,13,0.5)
);
//--------------------------------------------------------------------------------------------------------------------
public static final BlockDecorHalfSlab HALFSLAB_REBARCONCRETE = new BlockDecorHalfSlab(
"halfslab_rebar_concrete",
BlockDecor.CFG_CUTOUT,
Material.ROCK, 2f, 2000f, SoundType.STONE
);
public static final BlockDecorHalfSlab HALFSLAB_CONCRETE = new BlockDecorHalfSlab(
"halfslab_concrete",
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HARD_IE_DEPENDENT,
Material.ROCK, 1.0f, 10f, SoundType.STONE
);
public static final BlockDecorHalfSlab HALFSLAB_GAS_CONCRETE = new BlockDecorHalfSlab(
"halfslab_gas_concrete",
BlockDecor.CFG_CUTOUT,
Material.ROCK, 1.5f, 10f, SoundType.STONE
);
public static final BlockDecorHalfSlab HALFSLAB_TREATEDWOOD = new BlockDecorHalfSlab(
"halfslab_treated_wood",
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HARD_IE_DEPENDENT,
Material.WOOD, 0.6f, 4f, SoundType.WOOD
);
public static final BlockDecorHalfSlab HALFSLAB_SHEETMETALIRON = new BlockDecorHalfSlab(
"halfslab_sheetmetal_iron",
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HARD_IE_DEPENDENT,
Material.IRON, 0.8f, 10f, SoundType.METAL
);
public static final BlockDecorHalfSlab HALFSLAB_SHEETMETALSTEEL = new BlockDecorHalfSlab(
"halfslab_sheetmetal_steel",
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HARD_IE_DEPENDENT,
Material.IRON, 0.8f, 10f, SoundType.METAL
);
public static final BlockDecorHalfSlab HALFSLAB_SHEETMETALCOPPER = new BlockDecorHalfSlab(
"halfslab_sheetmetal_copper",
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HARD_IE_DEPENDENT,
Material.IRON, 0.8f, 10f, SoundType.METAL
);
public static final BlockDecorHalfSlab HALFSLAB_SHEETMETALGOLD = new BlockDecorHalfSlab(
"halfslab_sheetmetal_gold",
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HARD_IE_DEPENDENT,
Material.IRON, 0.6f, 10f, SoundType.METAL
);
public static final BlockDecorHalfSlab HALFSLAB_SHEETMETALALUMINIUM = new BlockDecorHalfSlab(
"halfslab_sheetmetal_aluminum",
BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HARD_IE_DEPENDENT,
Material.IRON, 0.6f, 10f, SoundType.METAL
);
//--------------------------------------------------------------------------------------------------------------------
public static final BlockDecorTest TEST_BLOCK = new BlockDecorTest(
"testblock",
BlockDecor.CFG_LOOK_PLACEMENT|BlockDecor.CFG_FLIP_PLACEMENT_SHIFTCLICK,
Material.IRON, 0.1f, 9000f, SoundType.METAL,
ModAuxiliaries.getPixeledAABB(0,0,0, 16,16,16)
);
//--------------------------------------------------------------------------------------------------------------------
//-- Tile entities
//--------------------------------------------------------------------------------------------------------------------
private static class TileEntityRegistrationData
{
public final Class<? extends TileEntity> clazz;
public final ResourceLocation key;
public final Block[] blocks;
public TileEntityRegistrationData(Class<? extends TileEntity> c, String k, Block... b)
{ clazz=c; key = new ResourceLocation(ModEngineersDecor.MODID, k); blocks=b; }
}
private static final TileEntityRegistrationData TREATED_WOOD_CRAFTING_TABLE_TEI = new TileEntityRegistrationData(
BlockDecorCraftingTable.BTileEntity.class, "te_crafting_table", TREATED_WOOD_CRAFTING_TABLE
);
private static final TileEntityRegistrationData LABELED_CRATE_TEI = new TileEntityRegistrationData(
BlockDecorLabeledCrate.LabeledCrateTileEntity.class, "te_labeled_crate", LABELED_CRATE
);
private static final TileEntityRegistrationData SMALL_LAB_FURNACE_TEI = new TileEntityRegistrationData(
BlockDecorFurnace.BTileEntity.class, "te_small_lab_furnace", SMALL_ELECTRICAL_FURNACE
);
private static final TileEntityRegistrationData SMALL_ELECTRICAL_FURNACE_TEI = new TileEntityRegistrationData(
BlockDecorFurnaceElectrical.BTileEntity.class, "te_electrical_lab_furnace", SMALL_ELECTRICAL_FURNACE
);
private static final TileEntityRegistrationData STRAIGHT_PIPE_VALVE_TEI = new TileEntityRegistrationData(
BlockDecorPipeValve.BTileEntity.class, "te_pipe_valve", STRAIGHT_CHECK_VALVE,STRAIGHT_REDSTONE_ANALOG_VALVE,STRAIGHT_REDSTONE_VALVE
);
private static final TileEntityRegistrationData PASSIVE_FLUID_ACCUMULATOR_TEI = new TileEntityRegistrationData(
BlockDecorPassiveFluidAccumulator.BTileEntity.class, "te_passive_fluid_accumulator", PASSIVE_FLUID_ACCUMULATOR
);
private static final TileEntityRegistrationData SMALL_FLUID_FUNNEL_TEI = new TileEntityRegistrationData(
BlockDecorFluidFunnel.BTileEntity.class, "te_small_fluid_funnel", SMALL_FLUID_FUNNEL
);
private static final TileEntityRegistrationData WASTE_INCINERATOR_TEI = new TileEntityRegistrationData(
BlockDecorWasteIncinerator.BTileEntity.class, "te_small_waste_incinerator", SMALL_WASTE_INCINERATOR
);
private static final TileEntityRegistrationData FACTORY_DROPPER_TEI = new TileEntityRegistrationData(
BlockDecorDropper.BTileEntity.class, "te_factory_dropper", FACTORY_DROPPER
);
private static final TileEntityRegistrationData FACTORY_HOPPER_TEI = new TileEntityRegistrationData(
BlockDecorHopper.BTileEntity.class, "te_factory_hopper", FACTORY_HOPPER
);
private static final TileEntityRegistrationData FACTORY_PLACER_TEI = new TileEntityRegistrationData(
BlockDecorPlacer.BTileEntity.class, "te_factory_placer", FACTORY_PLACER
);
private static final TileEntityRegistrationData SMALL_MINERAL_SMELTER_TEI = new TileEntityRegistrationData(
BlockDecorMineralSmelter.BTileEntity.class, "te_small_mineral_smelter", SMALL_MINERAL_SMELTER
);
private static final TileEntityRegistrationData SMALL_MILKING_MACHINE_TEI = new TileEntityRegistrationData(
BlockDecorMilker.BTileEntity.class, "te_small_milking_machine", SMALL_MILKING_MACHINE
);
private static final TileEntityRegistrationData SMALL_SOLAR_PANEL_TEI = new TileEntityRegistrationData(
BlockDecorSolarPanel.BTileEntity.class, "te_small_solar_panel", SMALL_SOLAR_PANEL
);
private static final TileEntityRegistrationData SMALL_TREE_CUTTER_TEI = new TileEntityRegistrationData(
BlockDecorTreeCutter.BTileEntity.class, "te_small_tree_cutter", SMALL_TREE_CUTTER
);
private static final TileEntityRegistrationData SMALL_BLOCK_BREAKER_TEI = new TileEntityRegistrationData(
BlockDecorBreaker.BTileEntity.class, "te_small_block_breaker", SMALL_BLOCK_BREAKER
);
private static final TileEntityRegistrationData TEST_BLOCK_TEI = new TileEntityRegistrationData(
BlockDecorTest.BTileEntity.class, "te_testblock", TEST_BLOCK
);
//--------------------------------------------------------------------------------------------------------------------
//-- Block registration list
//--------------------------------------------------------------------------------------------------------------------
private static final Object content[] = {
TREATED_WOOD_CRAFTING_TABLE, TREATED_WOOD_CRAFTING_TABLE_TEI,
LABELED_CRATE, LABELED_CRATE_TEI,
SMALL_LAB_FURNACE, SMALL_LAB_FURNACE_TEI,
SMALL_ELECTRICAL_FURNACE, SMALL_ELECTRICAL_FURNACE_TEI,
FACTORY_HOPPER,FACTORY_HOPPER_TEI,
FACTORY_DROPPER, FACTORY_DROPPER_TEI,
FACTORY_PLACER, FACTORY_PLACER_TEI,
SMALL_BLOCK_BREAKER,SMALL_BLOCK_BREAKER_TEI,
SMALL_TREE_CUTTER,SMALL_TREE_CUTTER_TEI,
SMALL_WASTE_INCINERATOR, WASTE_INCINERATOR_TEI,
SMALL_SOLAR_PANEL,SMALL_SOLAR_PANEL_TEI,
SMALL_MINERAL_SMELTER, SMALL_MINERAL_SMELTER_TEI,
STRAIGHT_CHECK_VALVE, STRAIGHT_REDSTONE_VALVE, STRAIGHT_REDSTONE_ANALOG_VALVE, STRAIGHT_PIPE_VALVE_TEI,
SMALL_FLUID_FUNNEL,SMALL_FLUID_FUNNEL_TEI,
PASSIVE_FLUID_ACCUMULATOR, PASSIVE_FLUID_ACCUMULATOR_TEI,
SMALL_MILKING_MACHINE,SMALL_MILKING_MACHINE_TEI,
CLINKER_BRICK_BLOCK,
CLINKER_BRICK_SLAB,
CLINKER_BRICK_STAIRS,
CLINKER_BRICK_WALL,
CLINKER_BRICK_STAINED_BLOCK,
CLINKER_BRICK_STAINED_SLAB,
CLINKER_BRICK_STAINED_STAIRS,
SLAG_BRICK_BLOCK,
SLAG_BRICK_SLAB,
SLAG_BRICK_STAIRS,
SLAG_BRICK_WALL,
REBAR_CONCRETE_BLOCK,
REBAR_CONCRETE_SLAB,
REBAR_CONCRETE_STAIRS,
REBAR_CONCRETE_WALL,
REBAR_CONCRETE_TILE,
REBAR_CONCRETE_TILE_SLAB,
REBAR_CONCRETE_TILE_STAIRS,
GAS_CONCRETE_BLOCK,
GAS_CONCRETE_SLAB,
GAS_CONCRETE_STAIRS,
GAS_CONCRETE_WALL,
CONCRETE_WALL,
PANZERGLASS_BLOCK,
METAL_RUNG_LADDER,
METAL_RUNG_STEPS,
TREATED_WOOD_LADDER,
TREATED_WOOD_POLE,
TREATED_WOOD_TABLE,
STEEL_TABLE,
TREATED_WOOD_STOOL,
TREATED_WOOD_WINDOW,
STEEL_FRAMED_WINDOW,
TREATED_WOOD_WINDOWSILL,
TREATED_WOOD_BROAD_WINDOWSILL,
INSET_LIGHT_IRON,
FLOOR_EDGE_LIGHT_IRON,
TREATED_WOOD_POLE_SUPPORT,
TREATED_WOOD_POLE_HEAD,
THIN_STEEL_POLE,
THICK_STEEL_POLE,
THIN_STEEL_POLE_HEAD,
THICK_STEEL_POLE_HEAD,
STEEL_DOUBLE_T_SUPPORT,
STEEL_FLOOR_GRATING,
STEEL_MESH_FENCE,
STEEL_MESH_FENCE_GATE,
SIGN_HOTWIRE, SIGN_DANGER, SIGN_DEFENSE, SIGN_FACTORY_AREA, SIGN_EXIT, SIGN_MODLOGO,
TREATED_WOOD_SIDE_TABLE,
HALFSLAB_REBARCONCRETE, HALFSLAB_CONCRETE, HALFSLAB_GAS_CONCRETE, HALFSLAB_TREATEDWOOD,
HALFSLAB_SHEETMETALIRON, HALFSLAB_SHEETMETALSTEEL, HALFSLAB_SHEETMETALCOPPER,
HALFSLAB_SHEETMETALGOLD, HALFSLAB_SHEETMETALALUMINIUM,
};
private static final Object dev_content[] = {
SIGN_MINDSTEP, // @todo: somehow make this sign look good.
PANZERGLASS_SLAB, // @todo: check if another class is needed due to is_side_visible
TREATED_WOOD_FLOOR, // @todo: check if textures need improvement
TEST_BLOCK,TEST_BLOCK_TEI,
};
//--------------------------------------------------------------------------------------------------------------------
//-- Items
//--------------------------------------------------------------------------------------------------------------------
private static final Item[] modItems = {
};
private static final ArrayList<Item> registeredItems = new ArrayList<>();
@Nonnull
public static List<Item> getRegisteredItems()
{ return Collections.unmodifiableList(registeredItems); }
public static final void registerItems(RegistryEvent.Register<Item> event)
{
// Config based registry selection
int num_registrations_skipped = 0;
ArrayList<Item> allItems = new ArrayList<>();
Collections.addAll(allItems, modItems);
final boolean woor = ModConfig.isWithoutOptOutRegistration();
for(Item e:allItems) {
if((!woor) || (!ModConfig.isOptedOut(e))) {
registeredItems.add(e);
} else {
++num_registrations_skipped;
}
}
for(Item e:registeredItems) event.getRegistry().register(e);
ModEngineersDecor.logger.info("Registered " + Integer.toString(registeredItems.size()) + " items.");
if(num_registrations_skipped > 0) {
ModEngineersDecor.logger.info("Skipped registration of " + num_registrations_skipped + " items.");
}
}
//--------------------------------------------------------------------------------------------------------------------
//-- Init
//--------------------------------------------------------------------------------------------------------------------
private static ArrayList<Block> registeredBlocks = new ArrayList<>();
private static ArrayList<TileEntityRegistrationData> registeredTileEntityInits = new ArrayList<>();
@Nonnull
public static List<Block> getRegisteredBlocks()
{ return Collections.unmodifiableList(registeredBlocks); }
// Invoked from CommonProxy.registerBlocks()
public static final void registerBlocks(RegistryEvent.Register<Block> event)
{
// Config based registry selection
final boolean ie_installed = ModAuxiliaries.isModLoaded("immersiveengineering");
int num_block_registrations_skipped = 0;
int num_block_registrations_skipped_noie = 0;
final boolean woor = ModConfig.isWithoutOptOutRegistration();
for(Object e:content) {
if(e instanceof Block) {
if((!ie_installed) && ((e instanceof BlockDecor) && ((((BlockDecor)e).config & BlockDecor.CFG_HARD_IE_DEPENDENT)!=0))) {
++num_block_registrations_skipped;
++num_block_registrations_skipped_noie;
continue;
}
if((woor) && (e != SIGN_MODLOGO) && (ModConfig.isOptedOut((Block)e))) {
ModEngineersDecor.logger.info("Registration opt-out: " + ((Block) e).getRegistryName().getPath());
++num_block_registrations_skipped;
continue;
}
registeredBlocks.add((Block) e);
} else if(e instanceof TileEntityRegistrationData) {
if((woor) && Arrays.stream(((TileEntityRegistrationData)e).blocks).allMatch(ModConfig::isOptedOut)) continue;
registeredTileEntityInits.add((TileEntityRegistrationData)e);
}
}
if(ModConfig.zmisc.with_experimental) {
for(Object e:dev_content) {
if(e instanceof Block) {
registeredBlocks.add((Block) e);
} else if(e instanceof TileEntityRegistrationData) {
registeredTileEntityInits.add((TileEntityRegistrationData) e);
}
}
}
for(Block e:registeredBlocks) event.getRegistry().register(e);
ModEngineersDecor.logger.info("Registered " + Integer.toString(registeredBlocks.size()) + " blocks.");
if(num_block_registrations_skipped > 0) ModEngineersDecor.logger.info("Skipped registration of " + num_block_registrations_skipped + " blocks, " + num_block_registrations_skipped_noie + " because IE is not installed.");
for(TileEntityRegistrationData e:registeredTileEntityInits) GameRegistry.registerTileEntity(e.clazz, e.key);
ModEngineersDecor.logger.info("Registered " + Integer.toString(registeredTileEntityInits.size()) + " tile entities.");
}
// Invoked from ClientProxy.registerModels()
@SideOnly(Side.CLIENT)
public static final void initModels()
{
for(Block e:registeredBlocks) {
ModelLoader.setCustomModelResourceLocation(Item.getItemFromBlock(e), 0, new ModelResourceLocation(e.getRegistryName(), "inventory"));
}
for(Item e:registeredItems) {
if(e instanceof ItemDecor) ((ItemDecor)e).initModel();
}
if(!ModConfig.optout.without_tesrs) {
if(!ModConfig.isOptedOut(TREATED_WOOD_CRAFTING_TABLE)) {
ClientRegistry.bindTileEntitySpecialRenderer(BlockDecorCraftingTable.BTileEntity.class, new ModTesrs.TesrDecorCraftingTable());
}
if(!ModConfig.isOptedOut(LABELED_CRATE)) {
ClientRegistry.bindTileEntitySpecialRenderer(BlockDecorLabeledCrate.LabeledCrateTileEntity.class, new ModTesrs.TesrDecorLabeledCrate());
}
if(!ModConfig.isOptedOut(TEST_BLOCK)) {
ClientRegistry.bindTileEntitySpecialRenderer(BlockDecorTest.BTileEntity.class, new ModTesrs.TesrDecorTest());
}
}
}
// Invoked from CommonProxy.registerItems()
public static final void registerItemBlocks(RegistryEvent.Register<Item> event)
{
for(Block e:registeredBlocks) event.getRegistry().register(new ItemDecor(e));
}
}

View file

@ -1,217 +0,0 @@
/*
* @file ModEngineersDecor.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Main mod class.
*/
package wile.engineersdecor;
import wile.engineersdecor.detail.*;
import wile.engineersdecor.blocks.*;
import net.minecraft.world.World;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.client.multiplayer.WorldClient;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.block.Block;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Item;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.network.IGuiHandler;
import net.minecraftforge.fml.common.network.NetworkRegistry;
import net.minecraftforge.fml.common.registry.EntityRegistry;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.SidedProxy;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.event.entity.living.LivingEvent;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.client.event.ModelRegistryEvent;
import net.minecraftforge.fml.relauncher.SideOnly;
import org.apache.logging.log4j.Logger;
import javax.annotation.Nonnull;
@Mod(
modid = ModEngineersDecor.MODID,
name = ModEngineersDecor.MODNAME,
version = ModEngineersDecor.MODVERSION,
dependencies = "required-after:forge@[14.23.5.2768,);before:immersiveengineering",
useMetadata = true,
updateJSON = "https://raw.githubusercontent.com/stfwi/engineers-decor/develop/meta/update.json",
certificateFingerprint = ((ModEngineersDecor.MODFINGERPRINT==("@"+"MOD_SIGNSHA1"+"@")) ? "" : ModEngineersDecor.MODFINGERPRINT)
)
@SuppressWarnings({"unused", "ConstantConditions"})
public class ModEngineersDecor
{
public static final String MODID = "engineersdecor";
public static final String MODNAME = "Engineer's Decor";
public static final String MODVERSION = "@MOD_VERSION@";
public static final String MODMCVERSION = "@MOD_MCVERSION@";
public static final String MODFINGERPRINT = "@MOD_SIGNSHA1@";
public static final String MODBUILDID = "@MOD_BUILDID@";
public static Logger logger;
@Mod.Instance
public static ModEngineersDecor instance;
//--------------------------------------------------------------------------------------------------------------------
// Side handling
//--------------------------------------------------------------------------------------------------------------------
@SidedProxy(clientSide = "wile.engineersdecor.detail.ClientProxy", serverSide = "wile.engineersdecor.detail.ServerProxy")
public static IProxy proxy;
public interface IProxy
{
default void preInit(final FMLPreInitializationEvent e) {}
default void init(final FMLInitializationEvent e) {}
default void postInit(final FMLPostInitializationEvent e) {}
default World getWorlClientSide() { return null; }
default EntityPlayer getPlayerClientSide() { return null; }
}
//--------------------------------------------------------------------------------------------------------------------
// Init
//--------------------------------------------------------------------------------------------------------------------
@Mod.EventHandler
public void preInit(final FMLPreInitializationEvent event)
{
logger = event.getModLog();
logger.info(MODNAME + ": Version " + MODMCVERSION + "-" + MODVERSION + ( (MODBUILDID=="@"+"MOD_BUILDID"+"@") ? "" : (" "+MODBUILDID) ) + ".");
if(MODFINGERPRINT=="@"+"MOD_SIGNSHA1"+"@") {
logger.warn(MODNAME + ": Mod is NOT signed by the author.");
} else {
logger.info(MODNAME + ": Found valid fingerprint " + MODFINGERPRINT + ".");
}
proxy.preInit(event);
MinecraftForge.EVENT_BUS.register(new PlayerEventHandler());
Networking.init();
ModConfig.onPreInit();
}
@Mod.EventHandler
public void init(final FMLInitializationEvent event)
{
proxy.init(event);
NetworkRegistry.INSTANCE.registerGuiHandler(this, new ModEngineersDecor.GuiHandler());
EntityRegistry.registerModEntity(new ResourceLocation(ModEngineersDecor.MODID, "chair_entity"), BlockDecorChair.EntityChair.class,"DecorChair",0,this,80,1,false);
}
@Mod.EventHandler
public void postInit(final FMLPostInitializationEvent event)
{
ModConfig.onPostInit(event);
proxy.postInit(event);
if(RecipeCondModSpecific.num_skipped > 0) logger.info("Excluded " + RecipeCondModSpecific.num_skipped + " recipes due to config opt-out.");
if(ModConfig.zmisc.with_experimental) logger.info("Included experimental features due to mod config.");
ExtItems.onPostInit();
BlockCategories.reload();
TreeCutting.reload();
}
@Mod.EventBusSubscriber
public static final class RegistrationSubscriptions
{
@SubscribeEvent
public static void registerBlocks(final RegistryEvent.Register<Block> event)
{ ModContent.registerBlocks(event); }
@SubscribeEvent
public static void registerItems(final RegistryEvent.Register<Item> event)
{ ModContent.registerItemBlocks(event); ModContent.registerItems(event); }
@SubscribeEvent
public static void registerRecipes(RegistryEvent.Register<IRecipe> event)
{ ModRecipes.registerRecipes(event); }
@SideOnly(Side.CLIENT)
@SubscribeEvent
public static void registerModels(final ModelRegistryEvent event)
{ ModContent.initModels(); }
}
public static final CreativeTabs CREATIVE_TAB_ENGINEERSDECOR = (new CreativeTabs("tabengineersdecor") {
@Override
@SideOnly(Side.CLIENT)
public @Nonnull ItemStack createIcon()
{ return new ItemStack(ModContent.SIGN_MODLOGO); }
});
//--------------------------------------------------------------------------------------------------------------------
// Player interaction/notification
//--------------------------------------------------------------------------------------------------------------------
public static final class GuiHandler implements IGuiHandler
{
public static final int GUIID_CRAFTING_TABLE = 213101;
public static final int GUIID_SMALL_LAB_FURNACE = 213102;
public static final int GUIID_ELECTRICAL_LAB_FURNACE = 213103;
public static final int GUIID_SMALL_WASTE_INCINERATOR = 213104;
public static final int GUIID_FACTORY_DROPPER = 213105;
public static final int GUIID_FACTORY_HOPPER = 213106;
public static final int GUIID_FACTORY_PLACER = 213107;
public static final int GUIID_LABELED_CRATE = 213108;
@Override
public Object getServerGuiElement(final int guiid, final EntityPlayer player, final World world, int x, int y, int z)
{
final BlockPos pos = new BlockPos(x,y,z);
final TileEntity te = world.getTileEntity(pos);
switch(guiid) {
case GUIID_CRAFTING_TABLE: return BlockDecorCraftingTable.getServerGuiElement(player, world, pos, te);
case GUIID_SMALL_LAB_FURNACE: return BlockDecorFurnace.getServerGuiElement(player, world, pos, te);
case GUIID_ELECTRICAL_LAB_FURNACE: return BlockDecorFurnaceElectrical.getServerGuiElement(player, world, pos, te);
case GUIID_SMALL_WASTE_INCINERATOR: return BlockDecorWasteIncinerator.getServerGuiElement(player, world, pos, te);
case GUIID_FACTORY_DROPPER: return BlockDecorDropper.getServerGuiElement(player, world, pos, te);
case GUIID_FACTORY_HOPPER: return BlockDecorHopper.getServerGuiElement(player, world, pos, te);
case GUIID_FACTORY_PLACER: return BlockDecorPlacer.getServerGuiElement(player, world, pos, te);
case GUIID_LABELED_CRATE: return BlockDecorLabeledCrate.getServerGuiElement(player, world, pos, te);
}
return null;
}
@SideOnly(Side.CLIENT)
@Override
public Object getClientGuiElement(final int guiid, final EntityPlayer player, final World world, int x, int y, int z)
{
final BlockPos pos = new BlockPos(x,y,z);
final TileEntity te = (world instanceof WorldClient) ? world.getTileEntity(pos) : null;
switch(guiid) {
case GUIID_CRAFTING_TABLE: return BlockDecorCraftingTable.getClientGuiElement(player, world, pos, te);
case GUIID_SMALL_LAB_FURNACE: return BlockDecorFurnace.getClientGuiElement(player, world, pos, te);
case GUIID_ELECTRICAL_LAB_FURNACE: return BlockDecorFurnaceElectrical.getClientGuiElement(player, world, pos, te);
case GUIID_SMALL_WASTE_INCINERATOR: return BlockDecorWasteIncinerator.getClientGuiElement(player, world, pos, te);
case GUIID_FACTORY_DROPPER: return BlockDecorDropper.getClientGuiElement(player, world, pos, te);
case GUIID_FACTORY_HOPPER: return BlockDecorHopper.getClientGuiElement(player, world, pos, te);
case GUIID_FACTORY_PLACER: return BlockDecorPlacer.getClientGuiElement(player, world, pos, te);
case GUIID_LABELED_CRATE: return BlockDecorLabeledCrate.getClientGuiElement(player, world, pos, te);
}
return null;
}
}
@Mod.EventBusSubscriber
public static class PlayerEventHandler
{
@SubscribeEvent
public void update(final LivingEvent.LivingUpdateEvent event)
{
if(!(event.getEntity() instanceof EntityPlayer)) return;
final EntityPlayer player = (EntityPlayer)event.getEntity();
if(player.world == null) return;
if(player.isOnLadder()) BlockDecorLadder.onPlayerUpdateEvent(player);
}
}
}

View file

@ -1,196 +0,0 @@
/*
* @file BlockDecor.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Common functionality class for decor blocks.
* Mainly needed for:
* - MC block defaults.
* - Tooltip functionality
* - Model initialisation
* - Accumulating "deprecated" warnings from Block where "overriding/implementing is fine".
*/
package wile.engineersdecor.blocks;
import net.minecraft.block.BlockSnow;
import wile.engineersdecor.ModEngineersDecor;
import wile.engineersdecor.detail.ModAuxiliaries;
import net.minecraft.block.SoundType;
import net.minecraft.block.state.BlockFaceShape;
import net.minecraft.block.Block;
import net.minecraft.block.material.EnumPushReaction;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.state.IBlockState;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraft.item.ItemStack;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.*;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.entity.Entity;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
public class BlockDecor extends Block
{
// The config combines some aspects of blocks, allowing to define different behaviour at construction time, without excessive polymorphy.
// It's an old school flag set as it is used internally only and shall not have as littlt impact on performance as possible.
public final long config;
public static final long CFG_DEFAULT = 0x0000000000000000L; // no special config
public static final long CFG_CUTOUT = 0x0000000000000001L; // cutout rendering
public static final long CFG_HORIZIONTAL = 0x0000000000000002L; // horizontal block, affects bounding box calculation at construction time and placement
public static final long CFG_LOOK_PLACEMENT = 0x0000000000000004L; // placed in direction the player is looking when placing.
public static final long CFG_FACING_PLACEMENT = 0x0000000000000008L; // placed on the facing the player has clicked.
public static final long CFG_OPPOSITE_PLACEMENT = 0x0000000000000010L; // placed placed in the opposite direction of the face the player clicked.
public static final long CFG_FLIP_PLACEMENT_IF_SAME = 0x0000000000000020L; // placement direction flipped if an instance of the same class was clicked
public static final long CFG_FLIP_PLACEMENT_SHIFTCLICK = 0x0000000000000040L; // placement direction flipped if player is sneaking
public static final long CFG_TRANSLUCENT = 0x0000000000000080L; // indicates a block/pane is glass like (transparent, etc)
public static final long CFG_LIGHT_VALUE_MASK = 0x0000000000000f00L; // fixed value for getLightValue()
public static final long CFG_LIGHT_VALUE_SHIFT = 8L;
public static final long CFG_ELECTRICAL = 0x0000000000010000L; // Denotes if a component is mainly flux driven.
public static final long CFG_REDSTONE_CONTROLLED = 0x0000000000020000L; // Denotes if a component has somehow a redstone control input
public static final long CFG_ANALOG = 0x0000000000040000L; // Denotes if a component has analog behaviour
public static final long CFG_HARD_IE_DEPENDENT = 0x8000000000000000L; // Defines that this block abolutely needs IE to be installed.
protected final AxisAlignedBB[] aabb;
public BlockDecor(@Nonnull String registryName, long config, @Nullable Material material, float hardness, float resistance, @Nullable SoundType sound)
{ this(registryName, config, material, hardness, resistance, sound, (new AxisAlignedBB[]{FULL_BLOCK_AABB})); }
public BlockDecor(@Nonnull String registryName, long config, @Nullable Material material, float hardness, float resistance, @Nullable SoundType sound, @Nullable AxisAlignedBB boundingbox)
{ this(registryName, config, material, hardness, resistance, sound, (boundingbox==null) ? (new AxisAlignedBB[]{FULL_BLOCK_AABB}) : (new AxisAlignedBB[]{boundingbox})); }
public BlockDecor(@Nonnull String registryName, long config, @Nullable Material material, float hardness, float resistance, @Nullable SoundType sound, @Nonnull AxisAlignedBB[] boundingboxes)
{
super((material!=null) ? (material) : (Material.IRON));
setCreativeTab(ModEngineersDecor.CREATIVE_TAB_ENGINEERSDECOR);
setRegistryName(ModEngineersDecor.MODID, registryName);
setTranslationKey(ModEngineersDecor.MODID + "." + registryName);
setTickRandomly(false);
setHardness((hardness > 0) ? hardness : 5.0f);
setResistance((resistance > 0) ? resistance : 10.0f);
setSoundType((sound==null) ? SoundType.STONE : sound);
if(((config & (CFG_CUTOUT|CFG_TRANSLUCENT))!=0)) setLightOpacity(0);
if((config & CFG_TRANSLUCENT) != 0) this.translucent = true;
this.config = config;
this.aabb = boundingboxes;
}
@Override
@SideOnly(Side.CLIENT)
public void addInformation(ItemStack stack, @Nullable World world, List<String> tooltip, ITooltipFlag flag)
{ ModAuxiliaries.Tooltip.addInformation(stack, world, tooltip, flag, true); }
@Override
@SideOnly(Side.CLIENT)
public BlockRenderLayer getRenderLayer()
{ return ((config & CFG_CUTOUT)!=0) ? (BlockRenderLayer.CUTOUT) : ( ((config & CFG_TRANSLUCENT)!=0) ? (BlockRenderLayer.TRANSLUCENT) : (BlockRenderLayer.SOLID)); }
@Override
@SideOnly(Side.CLIENT)
@SuppressWarnings("deprecation")
public boolean shouldSideBeRendered(IBlockState state, IBlockAccess world, BlockPos pos, EnumFacing side)
{ return true; }
@Override
@SuppressWarnings("deprecation")
public BlockFaceShape getBlockFaceShape(IBlockAccess world, IBlockState state, BlockPos pos, EnumFacing face)
{ return BlockFaceShape.SOLID; }
@Override
@SuppressWarnings("deprecation")
public boolean isFullCube(IBlockState state)
{ return ((config & CFG_CUTOUT)==0); }
@Override
@SuppressWarnings("deprecation")
public boolean isNormalCube(IBlockState state)
{ return ((config & (CFG_CUTOUT|CFG_TRANSLUCENT))==0); }
@Override
@SuppressWarnings("deprecation")
public boolean isOpaqueCube(IBlockState state)
{ return ((config & (CFG_CUTOUT|CFG_TRANSLUCENT))==0); }
@Override
public boolean canSpawnInBlock()
{ return false; }
@Override
public boolean canHarvestBlock(IBlockAccess world, BlockPos pos, EntityPlayer player)
{ return true; }
@Override
@SuppressWarnings("deprecation")
public EnumPushReaction getPushReaction(IBlockState state)
{ return EnumPushReaction.NORMAL; }
@Override
@SuppressWarnings("deprecation")
public IBlockState getStateFromMeta(int meta)
{ return getDefaultState(); }
@Override
public int getMetaFromState(IBlockState state)
{ return 0; }
@Override
protected BlockStateContainer createBlockState()
{ return new BlockStateContainer(this); }
@Override
@SuppressWarnings("deprecation")
public IBlockState getActualState(IBlockState state, IBlockAccess world, BlockPos pos)
{ return state; }
@Override
@SuppressWarnings("deprecation")
public IBlockState withRotation(IBlockState state, Rotation rot)
{ return state; }
@Override
@SuppressWarnings("deprecation")
public IBlockState withMirror(IBlockState state, Mirror mirrorIn)
{ return state; }
@Override
@Nullable
@SuppressWarnings("deprecation")
public AxisAlignedBB getCollisionBoundingBox(IBlockState state, IBlockAccess world, BlockPos pos)
{ return getBoundingBox(state, world, pos); }
@Override
@SuppressWarnings("deprecation")
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos)
{ return aabb[0]; }
@SideOnly(Side.CLIENT)
@SuppressWarnings("deprecation")
public AxisAlignedBB getSelectedBoundingBox(IBlockState state, World world, BlockPos pos)
{ return state.getBoundingBox(world, pos).offset(pos); }
@SuppressWarnings("deprecation")
public void addCollisionBoxToList(IBlockState state, World world, BlockPos pos, AxisAlignedBB entityBox, List<AxisAlignedBB> collidingBoxes, @Nullable Entity entityIn, boolean isActualState)
{
addCollisionBoxToList(pos, entityBox, collidingBoxes, getBoundingBox(state, world, pos));
for(int i=1; i<aabb.length; ++i) addCollisionBoxToList(pos, entityBox, collidingBoxes, aabb[i]);
}
@Override
public boolean hasTileEntity(IBlockState state)
{ return false; }
@Override
@SuppressWarnings("deprecation")
public void neighborChanged(IBlockState state, World world, BlockPos pos, Block blockIn, BlockPos fromPos)
{}
}

View file

@ -1,332 +0,0 @@
/*
* @file BlockDecorBreaker.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Small Block Breaker
*/
package wile.engineersdecor.blocks;
import wile.engineersdecor.ModEngineersDecor;
import wile.engineersdecor.detail.ModAuxiliaries;
import net.minecraft.world.World;
import net.minecraft.block.Block;
import net.minecraft.block.properties.PropertyBool;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.init.Blocks;
import net.minecraft.init.SoundEvents;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.*;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.energy.CapabilityEnergy;
import net.minecraftforge.energy.IEnergyStorage;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.HashSet;
import java.util.Random;
public class BlockDecorBreaker extends BlockDecorDirectedHorizontal
{
//--------------------------------------------------------------------------------------------------------------------
// Config
//--------------------------------------------------------------------------------------------------------------------
public static final int IDLE_TICK_INTERVAL = 40;
public static final int TICK_INTERVAL = 5;
public static final int BOOST_FACTOR = 8;
public static final int DEFAULT_BOOST_ENERGY = 64;
public static final int DEFAULT_BREAKING_RELUCTANCE = 17;
public static final int DEFAULT_MIN_BREAKING_TIME = 15;
public static final int MAX_BREAKING_TIME = 800;
private static int boost_energy_consumption = DEFAULT_BOOST_ENERGY;
private static int energy_max = 10000;
private static int breaking_reluctance = DEFAULT_BREAKING_RELUCTANCE;
private static int min_breaking_time = DEFAULT_MIN_BREAKING_TIME;
private static boolean requires_power = false;
public static void on_config(int boost_energy_per_tick, int breaking_time_per_hardness, int min_breaking_time_ticks, boolean power_required)
{
boost_energy_consumption = TICK_INTERVAL * MathHelper.clamp(boost_energy_per_tick, 16, 512);
energy_max = Math.max(boost_energy_consumption * 10, 10000);
breaking_reluctance = MathHelper.clamp(breaking_time_per_hardness, 5, 50);
min_breaking_time = MathHelper.clamp(min_breaking_time_ticks, 10, 100);
requires_power = power_required;
ModEngineersDecor.logger.info("Config block breaker: Boost energy consumption:" + (boost_energy_consumption/TICK_INTERVAL) + "rf/t, reluctance=" + breaking_reluctance + "t/hrdn, break time offset=" + min_breaking_time + "t");
}
//--------------------------------------------------------------------------------------------------------------------
// Block
//--------------------------------------------------------------------------------------------------------------------
public static final PropertyBool ACTIVE = PropertyBool.create("active");
public BlockDecorBreaker(@Nonnull String registryName, long config, @Nullable Material material, float hardness, float resistance, @Nullable SoundType sound, @Nonnull AxisAlignedBB unrotatedAABB)
{
super(registryName, config, material, hardness, resistance, sound, unrotatedAABB);
setLightOpacity(0);
}
@Override
protected BlockStateContainer createBlockState()
{ return new BlockStateContainer(this, FACING, ACTIVE); }
@Override
public IBlockState getStateFromMeta(int meta)
{ return getDefaultState().withProperty(FACING, EnumFacing.byHorizontalIndex(meta & 0x7)).withProperty(ACTIVE, (meta & 0x8)!=0); }
@Override
public int getMetaFromState(IBlockState state)
{ return (state.getValue(FACING).getHorizontalIndex() & 0x7) | (state.getValue(ACTIVE) ? 8 : 0); }
@Override
public IBlockState getStateForPlacement(World world, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer, EnumHand hand)
{ return super.getStateForPlacement(world, pos, facing, hitX, hitY, hitZ, meta, placer, hand).withProperty(ACTIVE, false); }
@Override
public boolean hasTileEntity(IBlockState state)
{ return true; }
@Override
@Nullable
public TileEntity createTileEntity(World world, IBlockState state)
{ return new BTileEntity(); }
@Override
@SideOnly(Side.CLIENT)
public void randomDisplayTick(IBlockState state, World world, BlockPos pos, Random rnd)
{
if((state.getBlock()!=this) || (!state.getValue(ACTIVE))) return;
final double rv = rnd.nextDouble();
if(rv > 0.8) return;
final double x=0.5+pos.getX(), y=0.5+pos.getY(), z=0.5+pos.getZ();
final double xc=0.52, xr=rnd.nextDouble()*0.4-0.2, yr=(y-0.3+rnd.nextDouble()*0.2);
switch(state.getValue(FACING)) {
case WEST: world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, x-xc, yr, z+xr, 0.0, 0.0, 0.0); break;
case EAST: world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, x+xc, yr, z+xr, 0.0, 0.0, 0.0); break;
case NORTH: world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, x+xr, yr, z-xc, 0.0, 0.0, 0.0); break;
default: world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, x+xr, yr, z+xc, 0.0, 0.0, 0.0); break;
}
}
@Override
public void neighborChanged(IBlockState state, World world, BlockPos pos, Block block, BlockPos neighborPos)
{
if(!(world instanceof World) || (((World) world).isRemote)) return;
TileEntity te = world.getTileEntity(pos);
if(!(te instanceof BTileEntity)) return;
((BTileEntity)te).block_updated();
}
@Override
public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
{
if(world.isRemote) return true;
TileEntity te = world.getTileEntity(pos);
if(!(te instanceof BTileEntity)) return true;
((BTileEntity)te).state_message(player);
return true;
}
//--------------------------------------------------------------------------------------------------------------------
// Tile entity
//--------------------------------------------------------------------------------------------------------------------
public static class BTileEntity extends TileEntity implements ITickable, IEnergyStorage
{
private int tick_timer_;
private int active_timer_;
private int proc_time_elapsed_;
private int time_needed_;
private int energy_;
public BTileEntity()
{}
public void block_updated()
{ if(tick_timer_ > 2) tick_timer_ = 2; }
public void state_message(EntityPlayer player)
{
String soc = Integer.toString(MathHelper.clamp((energy_*100/energy_max),0,100));
String progress = "";
if((proc_time_elapsed_ > 0) && (time_needed_ > 0) && (active_timer_ > 0)) {
progress = " | " + Integer.toString((int)MathHelper.clamp((((double)proc_time_elapsed_) / ((double)time_needed_) * 100), 0, 100)) + "%%";
}
ModAuxiliaries.playerChatMessage(player, soc + "%%/" + energy_max + "RF" + progress);
}
public void readnbt(NBTTagCompound nbt)
{ energy_ = nbt.getInteger("energy"); }
private void writenbt(NBTTagCompound nbt)
{ nbt.setInteger("energy", energy_); }
// TileEntity ------------------------------------------------------------------------------
@Override
public boolean shouldRefresh(World world, BlockPos pos, IBlockState os, IBlockState ns)
{ return (os.getBlock() != ns.getBlock()) || (!(ns.getBlock() instanceof BlockDecorBreaker)); }
@Override
public void readFromNBT(NBTTagCompound nbt)
{ super.readFromNBT(nbt); readnbt(nbt); }
@Override
public NBTTagCompound writeToNBT(NBTTagCompound nbt)
{ super.writeToNBT(nbt); writenbt(nbt); return nbt; }
// IEnergyStorage ----------------------------------------------------------------------------
@Override
public boolean canExtract()
{ return false; }
@Override
public boolean canReceive()
{ return true; }
@Override
public int getMaxEnergyStored()
{ return boost_energy_consumption*2; }
@Override
public int getEnergyStored()
{ return energy_; }
@Override
public int extractEnergy(int maxExtract, boolean simulate)
{ return 0; }
@Override
public int receiveEnergy(int maxReceive, boolean simulate)
{
maxReceive = MathHelper.clamp(maxReceive, 0, Math.max(energy_max-energy_, 0));
if(!simulate) energy_ += maxReceive;
return maxReceive;
}
// Capability export ----------------------------------------------------------------------------
@Override
public boolean hasCapability(Capability<?> cap, EnumFacing facing)
{ return ((cap==CapabilityEnergy.ENERGY)) || super.hasCapability(cap, facing); }
@Override
@SuppressWarnings("unchecked")
@Nullable
public <T> T getCapability(Capability<T> capability, @Nullable EnumFacing facing)
{
if(capability == CapabilityEnergy.ENERGY) {
return (T)this;
} else {
return super.getCapability(capability, facing);
}
}
// ITickable ------------------------------------------------------------------------------------
private static HashSet<Block> blacklist = new HashSet<>();
static {
blacklist.add(Blocks.AIR);
blacklist.add(Blocks.BEDROCK);
blacklist.add(Blocks.FIRE);
blacklist.add(Blocks.END_PORTAL);
blacklist.add(Blocks.END_GATEWAY);
blacklist.add(Blocks.END_PORTAL_FRAME);
}
private static boolean isBreakable(IBlockState state, BlockPos pos, World world)
{
final Block block = state.getBlock();
if(blacklist.contains(block)) return false;
if(state.getMaterial().isLiquid()) return false;
if(block.isAir(state, world, pos)) return false;
float bh = state.getBlockHardness(world, pos);
if((bh<0) || (bh>55)) return false;
return true;
}
private static boolean breakBlock(IBlockState state, BlockPos pos, World world)
{
if(world.isRemote || world.restoringBlockSnapshots) return false; // retry next cycle
final Block block = state.getBlock();
block.dropBlockAsItem(world, pos, state, 0);
world.setBlockToAir(pos);
SoundType stype = state.getBlock().getSoundType(state, world, pos, null);
if(stype != null) world.playSound(null, pos, stype.getPlaceSound(), SoundCategory.BLOCKS, stype.getVolume()*0.6f, stype.getPitch());
return true;
}
@Override
@SuppressWarnings("deprecation")
public void update()
{
if(--tick_timer_ > 0) return;
final IBlockState device_state = world.getBlockState(pos);
if(!(device_state.getBlock() instanceof BlockDecorBreaker)) { tick_timer_ = TICK_INTERVAL; return; }
if(world.isRemote) {
if(!device_state.getValue(ACTIVE)) {
tick_timer_ = TICK_INTERVAL;
} else {
tick_timer_ = 1;
// not sure if is so cool to do this each tick ... may be simplified/removed again.
SoundEvent sound = SoundEvents.BLOCK_WOOD_HIT;
SoundType stype = world.getBlockState(pos.offset(device_state.getValue(FACING))).getBlock().getSoundType();
if((stype == SoundType.CLOTH) || (stype == SoundType.PLANT) || (stype == SoundType.SNOW)) {
sound = SoundEvents.BLOCK_CLOTH_HIT;
} else if((stype == SoundType.GROUND) || (stype == SoundType.SAND)) {
sound = SoundEvents.BLOCK_GRAVEL_HIT;
}
world.playSound(pos.getX(), pos.getY(), pos.getZ(), sound, SoundCategory.BLOCKS, 0.1f, 1.2f, false);
}
} else {
tick_timer_ = TICK_INTERVAL;
final BlockPos target_pos = pos.offset(device_state.getValue(FACING));
final IBlockState target_state = world.getBlockState(target_pos);
if((world.isBlockPowered(pos)) || (!isBreakable(target_state, target_pos, world))) {
if(device_state.getValue(ACTIVE)) world.setBlockState(pos, device_state.withProperty(ACTIVE, false), 1|2);
proc_time_elapsed_ = 0;
tick_timer_ = IDLE_TICK_INTERVAL;
return;
}
time_needed_ = MathHelper.clamp((int)(target_state.getBlockHardness(world, pos) * breaking_reluctance) + min_breaking_time, min_breaking_time, MAX_BREAKING_TIME);
if(energy_ >= boost_energy_consumption) {
energy_ -= boost_energy_consumption;
proc_time_elapsed_ += TICK_INTERVAL * (1+BOOST_FACTOR);
time_needed_ += min_breaking_time * (3*BOOST_FACTOR/5);
active_timer_ = 2;
} else if(!requires_power) {
proc_time_elapsed_ += TICK_INTERVAL;
active_timer_ = 1024;
} else if(active_timer_ > 0) {
--active_timer_;
}
boolean active = (active_timer_ > 0);
if(requires_power && !active) {
proc_time_elapsed_ = Math.max(0, proc_time_elapsed_ - 2*TICK_INTERVAL);
}
if(proc_time_elapsed_ >= time_needed_) {
proc_time_elapsed_ = 0;
breakBlock(target_state, target_pos, world);
active = false;
}
if(device_state.getValue(ACTIVE) != active) {
world.setBlockState(pos, device_state.withProperty(ACTIVE, active), 1|2);
}
}
}
}
}

View file

@ -1,160 +0,0 @@
/*
* @file BlockDecorFull.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Full block characteristics class.
*/
package wile.engineersdecor.blocks;
import wile.engineersdecor.ModEngineersDecor;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.monster.EntityMob;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.*;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Random;
public class BlockDecorChair extends BlockDecorDirected
{
//--------------------------------------------------------------------------------------------------------------------
// Config
//--------------------------------------------------------------------------------------------------------------------
private static boolean sitting_enabled = true;
private static double sitting_probability = 0.1;
private static double standup_probability = 0.01;
public static void on_config(boolean without_sitting, boolean without_mob_sitting, double sitting_probability_percent, double standup_probability_percent)
{
sitting_enabled = (!without_sitting);
sitting_probability = (without_sitting||without_mob_sitting) ? 0.0 : MathHelper.clamp(sitting_probability_percent/100, 0, 0.9);
standup_probability = (without_sitting||without_mob_sitting) ? 1.0 : MathHelper.clamp(standup_probability_percent/100, 1e-6, 1e-2);
ModEngineersDecor.logger.info("Config chairs: " + sitting_enabled + ", sit: " + sitting_probability, ", stand up: " + standup_probability);
}
//--------------------------------------------------------------------------------------------------------------------
// Block
//--------------------------------------------------------------------------------------------------------------------
public BlockDecorChair(@Nonnull String registryName, long config, @Nullable Material material, float hardness, float resistance, @Nullable SoundType sound, @Nonnull AxisAlignedBB unrotatedAABB)
{ super(registryName, config, material, hardness, resistance, sound, unrotatedAABB); setLightOpacity(0); setTickRandomly(true); }
@Override
public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
{ if(sitting_enabled && (!world.isRemote)) { EntityChair.sit(world, player, pos); } return true; }
@Override
public void onEntityCollision(World world, BlockPos pos, IBlockState state, Entity entity)
{ if(sitting_enabled && (Math.random() < sitting_probability) && (entity instanceof EntityMob)) EntityChair.sit(world, (EntityLivingBase)entity, pos); }
@Override
public void updateTick(World world, BlockPos pos, IBlockState state, Random rand)
{
if((!sitting_enabled) || (sitting_probability < 1e-6)) return;
final List<EntityLivingBase> entities = world.getEntitiesWithinAABB(EntityMob.class, new AxisAlignedBB(pos).grow(2,1,2).expand(0,1,0));
if(entities.isEmpty()) return;
int index = rand.nextInt(entities.size());
if((index < 0) || (index >= entities.size())) return;
EntityChair.sit(world, entities.get(index), pos);
}
//--------------------------------------------------------------------------------------------------------------------
// Riding entity for sitting
//--------------------------------------------------------------------------------------------------------------------
public static class EntityChair extends Entity
{
public final double x_offset = 0.5d;
public final double y_offset = 0.4d;
public final double z_offset = 0.5d;
private int t_tick = 0;
private int t_sit = 0;
public BlockPos chair_pos = new BlockPos(0,0,0);
public EntityChair(World world)
{ super(world); preventEntitySpawning=true; noClip=true; setSize(2e-3f, 2e-3f); }
public EntityChair(World world, BlockPos pos)
{
this(world);
setPosition(pos.getX()+x_offset,pos.getY()+y_offset,pos.getZ()+z_offset);
chair_pos = pos;
t_sit = 5;
}
public static boolean accepts_mob(EntityLivingBase entity)
{
if(!(entity instanceof net.minecraft.entity.monster.EntityMob)) return false;
if((entity.height > 2.5) || (entity.width > 2.0)) return false;
if(entity instanceof net.minecraft.entity.monster.EntityZombie) return true;
if(entity instanceof net.minecraft.entity.monster.EntityZombieVillager) return true;
if(entity instanceof net.minecraft.entity.monster.EntityPigZombie) return true;
if(entity instanceof net.minecraft.entity.monster.EntityHusk) return true;
if(entity instanceof net.minecraft.entity.monster.EntityStray) return true;
if(entity instanceof net.minecraft.entity.monster.EntitySkeleton) return true;
if(entity instanceof net.minecraft.entity.monster.EntityWitherSkeleton) return true;
return false;
}
public static void sit(World world, EntityLivingBase sitter, BlockPos pos)
{
if(!sitting_enabled) return;
if((world==null) || (world.isRemote) || (sitter==null) || (pos==null)) return;
if((!(sitter instanceof EntityPlayer)) && (!accepts_mob(sitter))) return;
if(!world.getEntitiesWithinAABB(EntityChair.class, new AxisAlignedBB(pos)).isEmpty()) return;
if(sitter.isBeingRidden() || (sitter.isDead) || (sitter.isRiding())) return;
if((!world.isAirBlock(pos.up())) || (!world.isAirBlock(pos.up(2)))) return;
EntityChair chair = new EntityChair(world, pos);
if(world.spawnEntity(chair)) sitter.startRiding(chair);
}
@Override
protected void entityInit()
{}
@Override
protected void writeEntityToNBT(NBTTagCompound compound)
{}
@Override
protected void readEntityFromNBT(NBTTagCompound compound)
{}
@Override
public double getMountedYOffset()
{ return 0.0; }
@Override
public void onUpdate()
{
if((world.isRemote) || (--t_tick > 0)) return;
t_tick = 20;
if(--t_sit > 0) return;
Entity sitter = getPassengers().isEmpty() ? null : getPassengers().get(0);
if((sitter==null) || (sitter.isDead)) { setDead(); return; }
boolean abort = !sitting_enabled;
final IBlockState state = world.getBlockState(chair_pos);
if((state==null) || (!(state.getBlock() instanceof BlockDecorChair))) abort = true;
if(!world.isAirBlock(chair_pos.up())) abort = true;
if((!(sitter instanceof EntityPlayer)) && (Math.random() < standup_probability)) abort = true;
if(abort) {
for(Entity e:getPassengers()) e.dismountRidingEntity();
setDead();
}
}
}
}

View file

@ -1,133 +0,0 @@
/*
* @file BlockDecorDirected.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Smaller (cutout) block with a defined facing.
*/
package wile.engineersdecor.blocks;
import wile.engineersdecor.detail.ModAuxiliaries;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.BlockDirectional;
import net.minecraft.block.material.Material;
import net.minecraft.block.properties.PropertyDirection;
import net.minecraft.block.state.BlockFaceShape;
import net.minecraft.block.state.IBlockState;
import net.minecraft.block.SoundType;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.world.World;
import net.minecraft.world.IBlockAccess;
import net.minecraft.util.EnumHand;
import net.minecraft.util.Mirror;
import net.minecraft.util.Rotation;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Arrays;
public class BlockDecorDirected extends BlockDecor
{
public static final PropertyDirection FACING = BlockDirectional.FACING;
protected final ArrayList<AxisAlignedBB> AABBs;
public BlockDecorDirected(@Nonnull String registryName, long config, @Nullable Material material, float hardness, float resistance, @Nullable SoundType sound, @Nonnull AxisAlignedBB unrotatedAABB)
{
super(registryName, config, material, hardness, resistance, sound);
final boolean is_horizontal = ((config & CFG_HORIZIONTAL)!=0);
AABBs = new ArrayList<AxisAlignedBB>(Arrays.asList(
ModAuxiliaries.getRotatedAABB(unrotatedAABB, EnumFacing.DOWN, is_horizontal),
ModAuxiliaries.getRotatedAABB(unrotatedAABB, EnumFacing.UP, is_horizontal),
ModAuxiliaries.getRotatedAABB(unrotatedAABB, EnumFacing.NORTH, is_horizontal),
ModAuxiliaries.getRotatedAABB(unrotatedAABB, EnumFacing.SOUTH, is_horizontal),
ModAuxiliaries.getRotatedAABB(unrotatedAABB, EnumFacing.WEST, is_horizontal),
ModAuxiliaries.getRotatedAABB(unrotatedAABB, EnumFacing.EAST, is_horizontal),
unrotatedAABB, unrotatedAABB // Array fill to ensure that the array size covers 4 bit (meta & 0x07).
));
}
@Override
public boolean isOpaqueCube(IBlockState state)
{ return false; }
@Override
public boolean isFullCube(IBlockState state)
{ return false; }
@Override
public boolean isNormalCube(IBlockState state)
{ return false; }
@Override
public boolean canCreatureSpawn(IBlockState state, IBlockAccess world, BlockPos pos, net.minecraft.entity.EntityLiving.SpawnPlacementType type)
{ return false; }
@Override
public int getLightValue(IBlockState state, IBlockAccess world, BlockPos pos)
{ return (int)((config & CFG_LIGHT_VALUE_MASK) >> CFG_LIGHT_VALUE_SHIFT); }
@Override
public BlockFaceShape getBlockFaceShape(IBlockAccess world, IBlockState state, BlockPos pos, EnumFacing face)
{ return BlockFaceShape.UNDEFINED; }
@Override
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos)
{ return AABBs.get(((EnumFacing)state.getValue(FACING)).getIndex() & 0x7); }
@Override
@Nullable
public AxisAlignedBB getCollisionBoundingBox(IBlockState state, IBlockAccess world, BlockPos pos)
{ return getBoundingBox(state, world, pos); }
@Override
public IBlockState getStateFromMeta(int meta)
{ return this.getDefaultState().withProperty(FACING, EnumFacing.byIndex(meta & 0x7)); }
@Override
public int getMetaFromState(IBlockState state)
{ return state.getValue(FACING).getIndex(); }
@Override
protected BlockStateContainer createBlockState()
{ return new BlockStateContainer(this, FACING); }
@Override
public IBlockState withRotation(IBlockState state, Rotation rot)
{ return state.withProperty(FACING, rot.rotate((EnumFacing)state.getValue(FACING))); }
@Override
public IBlockState withMirror(IBlockState state, Mirror mirrorIn)
{ return state.withRotation(mirrorIn.toRotation((EnumFacing)state.getValue(FACING))); }
@Override
public boolean canPlaceBlockOnSide(World world, BlockPos pos, EnumFacing side)
{
if(!super.canPlaceBlockOnSide(world, pos, side)) return false;
return !(((config & (CFG_HORIZIONTAL|CFG_LOOK_PLACEMENT))==(CFG_HORIZIONTAL)) && ((side==EnumFacing.UP)||(side==EnumFacing.DOWN)));
}
@Override
public IBlockState getStateForPlacement(World world, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer, EnumHand hand)
{
if((config & (CFG_HORIZIONTAL|CFG_LOOK_PLACEMENT)) == (CFG_HORIZIONTAL|CFG_LOOK_PLACEMENT)) {
// horizontal placement in direction the player is looking
facing = placer.getHorizontalFacing();
} else if((config & (CFG_HORIZIONTAL|CFG_LOOK_PLACEMENT)) == (CFG_HORIZIONTAL)) {
// horizontal placement on a face
facing = ((facing==EnumFacing.UP)||(facing==EnumFacing.DOWN)) ? (EnumFacing.NORTH) : facing;
} else if((config & CFG_LOOK_PLACEMENT)!=0) {
// placement in direction the player is looking, with up and down
facing = EnumFacing.getDirectionFromEntityLiving(pos, placer);
} else {
// default: placement on the face the player clicking
}
if((config & CFG_OPPOSITE_PLACEMENT)!=0) facing = facing.getOpposite();
if(((config & CFG_FLIP_PLACEMENT_SHIFTCLICK) != 0) && (placer.isSneaking())) facing = facing.getOpposite();
return getDefaultState().withProperty(FACING, facing);
}
}

View file

@ -1,83 +0,0 @@
/*
* @file BlockDecorDirectedHorizontal.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Smaller directed block with direction set narrowed
* to horizontal directions.
*/
package wile.engineersdecor.blocks;
import net.minecraft.block.BlockHorizontal;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.material.Material;
import net.minecraft.block.properties.PropertyDirection;
import net.minecraft.block.state.IBlockState;
import net.minecraft.block.SoundType;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.util.EnumHand;
import net.minecraft.util.Mirror;
import net.minecraft.util.Rotation;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class BlockDecorDirectedHorizontal extends BlockDecorDirected
{
public static final PropertyDirection FACING = BlockHorizontal.FACING;
public BlockDecorDirectedHorizontal(@Nonnull String registryName, long config, @Nullable Material material, float hardness, float resistance, @Nullable SoundType sound, @Nonnull AxisAlignedBB unrotatedAABB)
{ super(registryName, config|CFG_HORIZIONTAL, material, hardness, resistance, sound, unrotatedAABB); }
@Override
public IBlockState getStateFromMeta(int meta)
{ return this.getDefaultState().withProperty(FACING, EnumFacing.byHorizontalIndex(meta & 0x3)); }
@Override
public int getMetaFromState(IBlockState state)
{ return state.getValue(FACING).getHorizontalIndex(); }
@Override
protected BlockStateContainer createBlockState()
{ return new BlockStateContainer(this, FACING); }
@Override
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos)
{ return AABBs.get(state.getValue(FACING).getIndex() & 0x7); }
@Override
@Nullable
public AxisAlignedBB getCollisionBoundingBox(IBlockState state, IBlockAccess world, BlockPos pos)
{ return getBoundingBox(state, world, pos); }
@Override
public IBlockState withRotation(IBlockState state, Rotation rot)
{ return state; }
@Override
public IBlockState withMirror(IBlockState state, Mirror mirrorIn)
{ return state; }
@Override
public IBlockState getStateForPlacement(World world, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer, EnumHand hand)
{
if((config & CFG_LOOK_PLACEMENT) != 0) {
// horizontal placement in direction the player is looking
facing = placer.getHorizontalFacing();
} else {
// horizontal placement on a face
facing = ((facing==EnumFacing.UP)||(facing==EnumFacing.DOWN)) ? (placer.getHorizontalFacing()) : facing;
}
if((config & CFG_OPPOSITE_PLACEMENT)!=0) facing = facing.getOpposite();
if(((config & CFG_FLIP_PLACEMENT_SHIFTCLICK) != 0) && (placer.isSneaking())) facing = facing.getOpposite();
return getDefaultState().withProperty(FACING, facing);
}
}

View file

@ -1,188 +0,0 @@
/*
* @file BlockDecorDoubleGate.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Gate blocks that can be one or two segments high.
*/
package wile.engineersdecor.blocks;
import net.minecraft.entity.Entity;
import wile.engineersdecor.detail.ModAuxiliaries;
import net.minecraft.block.*;
import net.minecraft.block.material.Material;
import net.minecraft.block.properties.PropertyBool;
import net.minecraft.block.properties.PropertyInteger;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.SoundEvents;
import net.minecraft.item.Item;
import net.minecraft.util.EnumHand;
import net.minecraft.world.World;
import net.minecraft.world.IBlockAccess;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.pathfinding.PathNodeType;
import net.minecraft.block.BlockFenceGate;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class BlockDecorDoubleGate extends BlockDecorDirectedHorizontal
{
private static final AxisAlignedBB AABB_EMPTY = new AxisAlignedBB(0,0,0, 0,0,0.1);
public static final PropertyInteger SEGMENT = PropertyInteger.create("segment", 0, 1);
public static final PropertyBool OPEN = BlockFenceGate.OPEN;
public static final int SEGMENT_LOWER = 0;
public static final int SEGMENT_UPPER = 1;
private final ArrayList<AxisAlignedBB> collision_shapes_;
private final ArrayList<AxisAlignedBB> shapes_;
public BlockDecorDoubleGate(@Nonnull String registryName, long config, @Nullable Material material, float hardness, float resistance, @Nullable SoundType sound, @Nonnull AxisAlignedBB unrotatedAABB)
{
super(registryName, config, material, hardness, resistance, sound, unrotatedAABB);
AxisAlignedBB caabb = unrotatedAABB.expand(0, 0.5, 0);
collision_shapes_ = new ArrayList<AxisAlignedBB>(Arrays.asList(
NULL_AABB,
NULL_AABB,
ModAuxiliaries.getRotatedAABB(caabb, EnumFacing.NORTH, true),
ModAuxiliaries.getRotatedAABB(caabb, EnumFacing.SOUTH, true),
ModAuxiliaries.getRotatedAABB(caabb, EnumFacing.WEST, true),
ModAuxiliaries.getRotatedAABB(caabb, EnumFacing.EAST, true),
NULL_AABB,
NULL_AABB
));
shapes_ = new ArrayList<AxisAlignedBB>(Arrays.asList(
AABB_EMPTY,
AABB_EMPTY,
ModAuxiliaries.getRotatedAABB(unrotatedAABB, EnumFacing.NORTH, true),
ModAuxiliaries.getRotatedAABB(unrotatedAABB, EnumFacing.SOUTH, true),
ModAuxiliaries.getRotatedAABB(unrotatedAABB, EnumFacing.WEST, true),
ModAuxiliaries.getRotatedAABB(unrotatedAABB, EnumFacing.EAST, true),
AABB_EMPTY,
AABB_EMPTY
));
}
@Override
@SuppressWarnings("deprecation")
public IBlockState getStateFromMeta(int meta)
{ return super.getStateFromMeta(meta).withProperty(OPEN, (meta&0x4)!=0).withProperty(SEGMENT, ((meta&0x8)!=0) ? SEGMENT_UPPER:SEGMENT_LOWER); }
@Override
public int getMetaFromState(IBlockState state)
{ return super.getMetaFromState(state) | (state.getValue(OPEN)?0x4:0x0) | (state.getValue(SEGMENT)==SEGMENT_UPPER ? 0x8:0x0); }
@Override
protected BlockStateContainer createBlockState()
{ return new BlockStateContainer(this, FACING, OPEN, SEGMENT); }
@Override
@SuppressWarnings("deprecation")
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos)
{ return shapes_.get(state.getValue(FACING).getIndex() & 0x7); }
@Override
public AxisAlignedBB getCollisionBoundingBox(IBlockState state, IBlockAccess world, BlockPos pos)
{ return state.getValue(OPEN) ? NULL_AABB : collision_shapes_.get(state.getValue(FACING).getIndex() & 0x7); }
@Override
@SuppressWarnings("deprecation")
public void addCollisionBoxToList(IBlockState state, World world, BlockPos pos, AxisAlignedBB entityBox, List<AxisAlignedBB> collidingBoxes, @Nullable Entity entityIn, boolean isActualState)
{ if(!state.getValue(OPEN)) addCollisionBoxToList(pos, entityBox, collidingBoxes, collision_shapes_.get(state.getValue(FACING).getIndex() & 0x7)); }
@Override
public IBlockState getStateForPlacement(World world, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer, EnumHand hand)
{ return getInitialState(super.getStateForPlacement(world, pos, facing, hitX, hitY, hitZ, meta, placer, hand), world, pos); }
@Override
public boolean isPassable(IBlockAccess world, BlockPos pos)
{ return world.getBlockState(pos).getValue(OPEN); }
@Override
public net.minecraft.pathfinding.PathNodeType getAiPathNodeType(IBlockState state, IBlockAccess world, BlockPos pos)
{ return state.getValue(OPEN) ? PathNodeType.OPEN : PathNodeType.FENCE; }
@Override
@SuppressWarnings("deprecation")
public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, EnumFacing face, float hitX, float hitY, float hitZ)
{
if((face==EnumFacing.UP) || (face==EnumFacing.DOWN) && (player.getHeldItem(hand).getItem()==Item.getItemFromBlock(this))) return false;
if(world.isRemote) return true;
final boolean open = !state.getValue(OPEN);
world.setBlockState(pos, state.withProperty(OPEN, open),2|8|16);
if(state.getValue(SEGMENT) == SEGMENT_UPPER) {
final IBlockState adjacent = world.getBlockState(pos.down());
if(adjacent.getBlock()==this) world.setBlockState(pos.down(), adjacent.withProperty(OPEN, open), 2|8|16);
} else {
final IBlockState adjacent = world.getBlockState(pos.up());
if(adjacent.getBlock()==this) world.setBlockState(pos.up(), adjacent.withProperty(OPEN, open), 2|8|16);
}
world.playSound(null, pos, open ? SoundEvents.BLOCK_IRON_DOOR_OPEN:SoundEvents.BLOCK_IRON_DOOR_CLOSE, SoundCategory.BLOCKS, 0.7f, 1.4f);
return true;
}
@Override
@SuppressWarnings("deprecation")
public void neighborChanged(IBlockState state, World world, BlockPos pos, Block block, BlockPos fromPos)
{
if(world.isRemote) return;
boolean powered = false;
IBlockState adjacent;
BlockPos adjacent_pos;
if(state.getValue(SEGMENT) == SEGMENT_UPPER) {
adjacent_pos = pos.down();
adjacent = world.getBlockState(adjacent_pos);
if(adjacent.getBlock()!=this) adjacent = null;
if(world.getRedstonePower(pos.up(), EnumFacing.UP) > 0) {
powered = true;
} else if((adjacent!=null) && (world.isBlockPowered(pos.down(2)))) {
powered = true;
}
} else {
adjacent_pos = pos.up();
adjacent = world.getBlockState(adjacent_pos);
if(adjacent.getBlock()!=this) adjacent = null;
if(world.isBlockPowered(pos)) {
powered = true;
} else if((adjacent!=null) && (world.getRedstonePower(pos.up(2), EnumFacing.UP) > 0)) {
powered = true;
}
}
boolean sound = false;
if(powered != state.getValue(OPEN)) {
world.setBlockState(pos, state.withProperty(OPEN, powered), 2|8|16);
sound = true;
}
if((adjacent != null) && (powered != adjacent.getValue(OPEN))) {
world.setBlockState(adjacent_pos, adjacent.withProperty(OPEN, powered), 2|8|16);
sound = true;
}
if(sound) {
world.playSound(null, pos, powered?SoundEvents.BLOCK_IRON_DOOR_OPEN:SoundEvents.BLOCK_IRON_DOOR_CLOSE, SoundCategory.BLOCKS, 0.7f, 1.4f);
}
}
// -------------------------------------------------------------------------------------------------------------------
private IBlockState getInitialState(IBlockState state, IBlockAccess world, BlockPos pos)
{
final IBlockState down = world.getBlockState(pos.down());
if(down.getBlock() == this) return state.withProperty(SEGMENT, SEGMENT_UPPER).withProperty(OPEN, down.getValue(OPEN)).withProperty(FACING, down.getValue(FACING));
final IBlockState up = world.getBlockState(pos.up());
if(up.getBlock() == this) return state.withProperty(SEGMENT, SEGMENT_LOWER).withProperty(OPEN, up.getValue(OPEN)).withProperty(FACING, up.getValue(FACING));
return state.withProperty(SEGMENT, SEGMENT_LOWER).withProperty(OPEN, false);
}
}

View file

@ -1,935 +0,0 @@
/*
* @file BlockDecorDropper.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Dropper, factory automation suitable.
*/
package wile.engineersdecor.blocks;
import wile.engineersdecor.ModEngineersDecor;
import wile.engineersdecor.detail.Networking;
import net.minecraft.block.state.BlockFaceShape;
import net.minecraft.world.IBlockAccess;
import net.minecraftforge.items.wrapper.SidedInvWrapper;
import net.minecraft.block.properties.PropertyBool;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.Block;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.block.BlockDoor;
import net.minecraft.world.World;
import net.minecraft.world.Explosion;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.item.*;
import net.minecraft.inventory.*;
import net.minecraft.init.SoundEvents;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.util.*;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentTranslation;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.IOException;
public class BlockDecorDropper extends BlockDecorDirected
{
public static final PropertyBool OPEN = BlockDoor.OPEN;
public BlockDecorDropper(@Nonnull String registryName, long config, @Nullable Material material, float hardness, float resistance, @Nullable SoundType sound, @Nonnull AxisAlignedBB unrotatedAABB)
{ super(registryName, config, material, hardness, resistance, sound, unrotatedAABB); }
@Override
public BlockFaceShape getBlockFaceShape(IBlockAccess world, IBlockState state, BlockPos pos, EnumFacing face)
{ return BlockFaceShape.SOLID; }
@Override
protected BlockStateContainer createBlockState()
{ return new BlockStateContainer(this, FACING, OPEN); }
@Override
public IBlockState getStateFromMeta(int meta)
{ return super.getStateFromMeta(meta).withProperty(OPEN, (meta & 0x8)!=0); }
@Override
public int getMetaFromState(IBlockState state)
{ return super.getMetaFromState(state) | (state.getValue(OPEN) ? 0x8 : 0x0); }
@Override
public IBlockState getStateForPlacement(World world, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer, EnumHand hand)
{ return super.getStateForPlacement(world, pos, facing, hitX, hitY, hitZ, meta, placer, hand).withProperty(OPEN, false); }
@Override
@SuppressWarnings("deprecation")
public boolean hasComparatorInputOverride(IBlockState state)
{ return true; }
@Override
@SuppressWarnings("deprecation")
public int getComparatorInputOverride(IBlockState blockState, World world, BlockPos pos)
{ return Container.calcRedstone(world.getTileEntity(pos)); }
@Override
public boolean hasTileEntity(IBlockState state)
{ return true; }
@Override
@Nullable
public TileEntity createTileEntity(World world, IBlockState state)
{ return new BlockDecorDropper.BTileEntity(); }
@Override
public void onBlockPlacedBy(World world, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack)
{
if(world.isRemote) return;
if((!stack.hasTagCompound()) || (!stack.getTagCompound().hasKey("tedata"))) return;
NBTTagCompound te_nbt = stack.getTagCompound().getCompoundTag("tedata");
if(te_nbt.isEmpty()) return;
final TileEntity te = world.getTileEntity(pos);
if(!(te instanceof BlockDecorDropper.BTileEntity)) return;
((BlockDecorDropper.BTileEntity)te).readnbt(te_nbt, false);
((BlockDecorDropper.BTileEntity)te).reset_rtstate();
((BlockDecorDropper.BTileEntity)te).markDirty();
}
@Override
public boolean removedByPlayer(IBlockState state, World world, BlockPos pos, EntityPlayer player, boolean willHarvest)
{
if(world.isRemote) return true;
TileEntity te = world.getTileEntity(pos);
if(!(te instanceof BTileEntity)) return super.removedByPlayer(state, world, pos, player, willHarvest);
ItemStack stack = new ItemStack(this, 1);
NBTTagCompound te_nbt = new NBTTagCompound();
((BTileEntity) te).writenbt(te_nbt, false);
if(!te_nbt.isEmpty()) {
NBTTagCompound nbt = new NBTTagCompound();
nbt.setTag("tedata", te_nbt);
stack.setTagCompound(nbt);
}
world.spawnEntity(new EntityItem(world, pos.getX()+0.5, pos.getY()+0.5, pos.getZ()+0.5, stack));
world.setBlockToAir(pos);
world.removeTileEntity(pos);
return false;
}
@Override
public void onBlockExploded(World world, BlockPos pos, Explosion explosion)
{
if(world.isRemote) return;
TileEntity te = world.getTileEntity(pos);
if(!(te instanceof BTileEntity)) return;
for(ItemStack stack: ((BTileEntity)te).stacks_) {
if(!stack.isEmpty()) world.spawnEntity(new EntityItem(world, pos.getX(), pos.getY(), pos.getZ(), stack));
}
((BTileEntity)te).reset_rtstate();
super.onBlockExploded(world, pos, explosion);
}
@Override
public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
{
if(world.isRemote) return true;
player.openGui(ModEngineersDecor.instance, ModEngineersDecor.GuiHandler.GUIID_FACTORY_DROPPER, world, pos.getX(), pos.getY(), pos.getZ());
return true;
}
@Override
public void neighborChanged(IBlockState state, World world, BlockPos pos, Block block, BlockPos neighborPos)
{
if(!(world instanceof World) || (((World) world).isRemote)) return;
TileEntity te = world.getTileEntity(pos);
if(!(te instanceof BTileEntity)) return;
((BTileEntity)te).block_updated();
}
//--------------------------------------------------------------------------------------------------------------------
// ModEngineersDecor.GuiHandler connectors
//--------------------------------------------------------------------------------------------------------------------
public static Object getServerGuiElement(final EntityPlayer player, final World world, final BlockPos pos, final TileEntity te)
{ return (te instanceof BTileEntity) ? (new BContainer(player.inventory, world, pos, (BTileEntity)te)) : null; }
public static Object getClientGuiElement(final EntityPlayer player, final World world, final BlockPos pos, final TileEntity te)
{ return (te instanceof BTileEntity) ? (new BGui(player.inventory, world, pos, (BTileEntity)te)) : null; }
//--------------------------------------------------------------------------------------------------------------------
// GUI
//--------------------------------------------------------------------------------------------------------------------
@SideOnly(Side.CLIENT)
private static class BGui extends GuiContainer
{
private final BTileEntity te;
public BGui(InventoryPlayer playerInventory, World world, BlockPos pos, BTileEntity te)
{ super(new BContainer(playerInventory, world, pos, te)); this.te = te; }
@Override
public void initGui()
{ super.initGui(); }
@Override
public void drawScreen(int mouseX, int mouseY, float partialTicks)
{
drawDefaultBackground();
super.drawScreen(mouseX, mouseY, partialTicks);
renderHoveredToolTip(mouseX, mouseY);
}
@Override
protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException
{
super.mouseClicked(mouseX, mouseY, mouseButton);
BContainer container = (BContainer)inventorySlots;
if(container.fields_.length != 16) return;
int mx = mouseX - getGuiLeft(), my = mouseY - getGuiTop();
if(!isPointInRegion(114, 1, 61, 79, mouseX, mouseY)) {
return;
} else if(isPointInRegion(130, 10, 12, 25, mouseX, mouseY)) {
int force_percent = 100 - MathHelper.clamp(((my-10)*100)/25, 0, 100);
NBTTagCompound nbt = new NBTTagCompound();
nbt.setInteger("drop_speed", force_percent);
Networking.PacketTileNotify.sendToServer(te, nbt);
} else if(isPointInRegion(145, 10, 25, 25, mouseX, mouseY)) {
int xdev = MathHelper.clamp( (int)Math.round(((double)((mx-157) * 100)) / 12), -100, 100);
int ydev = MathHelper.clamp(-(int)Math.round(((double)((my- 22) * 100)) / 12), -100, 100);
if(Math.abs(xdev) < 9) xdev = 0;
if(Math.abs(ydev) < 9) ydev = 0;
NBTTagCompound nbt = new NBTTagCompound();
nbt.setInteger("drop_xdev", xdev);
nbt.setInteger("drop_ydev", ydev);
Networking.PacketTileNotify.sendToServer(te, nbt);
} else if(isPointInRegion(129, 40, 44, 10, mouseX, mouseY)) {
int ndrop = (mx-135);
if(ndrop < -1) {
ndrop = container.fields_[4] - 1; // -
} else if(ndrop >= 34) {
ndrop = container.fields_[4] + 1; // +
} else {
ndrop = MathHelper.clamp(1+ndrop, 1, BTileEntity.MAX_DROP_COUNT); // slider
}
NBTTagCompound nbt = new NBTTagCompound();
nbt.setInteger("drop_count", ndrop);
Networking.PacketTileNotify.sendToServer(te, nbt);
} else if(isPointInRegion(129, 50, 44, 10, mouseX, mouseY)) {
int period = (mx-135);
if(period < -1) {
period = container.fields_[6] - 3; // -
} else if(period >= 34) {
period = container.fields_[6] + 3; // +
} else {
period = (int)(0.5 + ((100.0 * period)/34));
}
period = MathHelper.clamp(period, 0, 100);
NBTTagCompound nbt = new NBTTagCompound();
nbt.setInteger("drop_period", period);
Networking.PacketTileNotify.sendToServer(te, nbt);
} else if(isPointInRegion(114, 51, 9, 9, mouseX, mouseY)) {
NBTTagCompound nbt = new NBTTagCompound();
nbt.setInteger("manual_rstrigger", 1);
Networking.PacketTileNotify.sendToServer(te, nbt);
} else if(isPointInRegion(162, 66, 7, 9, mouseX, mouseY)) {
NBTTagCompound nbt = new NBTTagCompound();
nbt.setInteger("drop_logic", container.fields_[5] ^ BTileEntity.DROPLOGIC_CONTINUOUS);
Networking.PacketTileNotify.sendToServer(te, nbt);
} else if(isPointInRegion(132, 66, 9, 9, mouseX, mouseY)) {
NBTTagCompound nbt = new NBTTagCompound();
nbt.setInteger("drop_logic", container.fields_[5] ^ BTileEntity.DROPLOGIC_FILTER_ANDGATE);
Networking.PacketTileNotify.sendToServer(te, nbt);
} else if(isPointInRegion(148, 66, 9, 9, mouseX, mouseY)) {
NBTTagCompound nbt = new NBTTagCompound();
nbt.setInteger("drop_logic", container.fields_[5] ^ BTileEntity.DROPLOGIC_EXTERN_ANDGATE);
Networking.PacketTileNotify.sendToServer(te, nbt);
}
}
@Override
protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY)
{
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
mc.getTextureManager().bindTexture(new ResourceLocation(ModEngineersDecor.MODID, "textures/gui/factory_dropper_gui.png"));
final int x0=getGuiLeft(), y0=getGuiTop(), w=getXSize(), h=getYSize();
drawTexturedModalRect(x0, y0, 0, 0, w, h);
BContainer container = (BContainer)inventorySlots;
if(container.fields_.length != 16) return; // no init, no cake.
// active drop slot
{
int drop_slot_index = container.fields_[15];
if((drop_slot_index < 0) || (drop_slot_index >= 16)) drop_slot_index = 0;
int x = (x0+9+((drop_slot_index % 6) * 18));
int y = (y0+5+((drop_slot_index / 6) * 17));
drawTexturedModalRect(x, y, 180, 45, 18, 18);
}
// filter LEDs
{
for(int i=0; i<3; ++i) {
int xt = 180 + (6 * container.fields_[12+i]), yt = 38;
int x = x0 + 31 + (i * 36), y = y0 + 65;
drawTexturedModalRect(x, y, xt, yt, 6, 6);
}
}
// force adjustment
{
int hy = 2 + (((100-container.fields_[0]) * 21) / 100);
int x = x0+135, y = y0+12, xt = 181;
int yt = 4 + (23-hy);
drawTexturedModalRect(x, y, xt, yt, 3, hy);
}
// angle adjustment
{
int x = x0 + 157 - 3 + ((container.fields_[1] * 12) / 100);
int y = y0 + 22 - 3 - ((container.fields_[2] * 12) / 100);
drawTexturedModalRect(x, y, 180, 30, 7, 7);
}
// drop count
{
int x = x0 + 134 - 2 + (container.fields_[4]);
int y = y0 + 45;
drawTexturedModalRect(x, y, 190, 31, 5, 5);
}
// drop period
{
int px = (int)Math.round(((33.0 * container.fields_[6]) / 100) + 1);
int x = x0 + 134 - 2 + MathHelper.clamp(px, 0, 33);
int y = y0 + 56;
drawTexturedModalRect(x, y, 190, 31, 5, 5);
}
// redstone input
{
if(container.fields_[11] != 0) {
drawTexturedModalRect(x0+114, y0+51, 189, 18, 9, 9);
}
}
// trigger logic
{
int filter_gate_offset = ((container.fields_[5] & BTileEntity.DROPLOGIC_FILTER_ANDGATE) != 0) ? 11 : 0;
int extern_gate_offset = ((container.fields_[5] & BTileEntity.DROPLOGIC_EXTERN_ANDGATE) != 0) ? 11 : 0;
int pulse_mode_offset = ((container.fields_[5] & BTileEntity.DROPLOGIC_CONTINUOUS ) != 0) ? 10 : 0;
drawTexturedModalRect(x0+132, y0+66, 179+filter_gate_offset, 66, 9, 9);
drawTexturedModalRect(x0+148, y0+66, 179+extern_gate_offset, 66, 9, 9);
drawTexturedModalRect(x0+162, y0+66, 200+pulse_mode_offset, 66, 9, 9);
}
// drop timer running indicator
{
if((container.fields_[9] > BTileEntity.DROP_PERIOD_OFFSET) && ((System.currentTimeMillis() % 1000) < 500)) {
drawTexturedModalRect(x0+149, y0+51, 201, 39, 3, 3);
}
}
}
}
//--------------------------------------------------------------------------------------------------------------------
// container
//--------------------------------------------------------------------------------------------------------------------
public static class BContainer extends Container
{
private static final int PLAYER_INV_START_SLOTNO = BTileEntity.NUM_OF_SLOTS;
private final World world;
private final BlockPos pos;
private final EntityPlayer player;
private final BTileEntity te;
private int fields_[] = new int[16];
public BContainer(InventoryPlayer playerInventory, World world, BlockPos pos, BTileEntity te)
{
this.player = playerInventory.player;
this.world = world;
this.pos = pos;
this.te = te;
int i=-1;
// input slots (stacks 0 to 11)
for(int y=0; y<2; ++y) {
for(int x=0; x<6; ++x) {
int xpos = 10+x*18, ypos = 6+y*17;
addSlotToContainer(new Slot(te, ++i, xpos, ypos));
}
}
// filter slots (stacks 12 to 14)
addSlotToContainer(new Slot(te, ++i, 19, 48));
addSlotToContainer(new Slot(te, ++i, 55, 48));
addSlotToContainer(new Slot(te, ++i, 91, 48));
// player slots
for(int x=0; x<9; ++x) {
addSlotToContainer(new Slot(playerInventory, x, 8+x*18, 144)); // player slots: 0..8
}
for(int y=0; y<3; ++y) {
for(int x=0; x<9; ++x) {
addSlotToContainer(new Slot(playerInventory, x+y*9+9, 8+x*18, 86+y*18)); // player slots: 9..35
}
}
}
public BlockPos getPos()
{ return pos; }
@Override
public void addListener(IContainerListener listener)
{ super.addListener(listener); listener.sendAllWindowProperties(this, te); }
@Override
public void detectAndSendChanges()
{
super.detectAndSendChanges();
for(int il=0; il<listeners.size(); ++il) {
IContainerListener lis = listeners.get(il);
for(int k=0; k<16; ++k) {
int f = te.getField(k);
if(fields_[k] != f) {
fields_[k] = f;
lis.sendWindowProperty(this, k, f);
}
}
}
}
@Override
@SideOnly(Side.CLIENT)
public void updateProgressBar(int id, int value)
{
if((id < 0) || (id >= fields_.length)) return;
fields_[id] = value;
te.setField(id, value);
}
@Override
public boolean canInteractWith(EntityPlayer player)
{ return (world.getBlockState(pos).getBlock() instanceof BlockDecorDropper) && (player.getDistanceSq(pos) <= 64); }
@Override
public ItemStack transferStackInSlot(EntityPlayer player, int index)
{
Slot slot = inventorySlots.get(index);
if((slot==null) || (!slot.getHasStack())) return ItemStack.EMPTY;
ItemStack slot_stack = slot.getStack();
ItemStack transferred = slot_stack.copy();
if((index>=0) && (index<PLAYER_INV_START_SLOTNO)) {
// Device slots
if(!mergeItemStack(slot_stack, PLAYER_INV_START_SLOTNO, PLAYER_INV_START_SLOTNO+36, false)) return ItemStack.EMPTY;
} else if((index >= PLAYER_INV_START_SLOTNO) && (index <= PLAYER_INV_START_SLOTNO+36)) {
// Player slot
if(!mergeItemStack(slot_stack, 0, BTileEntity.INPUT_SLOTS_SIZE, false)) return ItemStack.EMPTY;
} else {
// invalid slot
return ItemStack.EMPTY;
}
if(slot_stack.isEmpty()) {
slot.putStack(ItemStack.EMPTY);
} else {
slot.onSlotChanged();
}
if(slot_stack.getCount() == transferred.getCount()) return ItemStack.EMPTY;
slot.onTake(player, slot_stack);
return transferred;
}
}
//--------------------------------------------------------------------------------------------------------------------
// Tile entity
//--------------------------------------------------------------------------------------------------------------------
public static class BTileEntity extends TileEntity implements ITickable, ISidedInventory, Networking.IPacketReceiver
{
public static final int TICK_INTERVAL = 32;
public static final int NUM_OF_SLOTS = 15;
public static final int INPUT_SLOTS_FIRST = 0;
public static final int INPUT_SLOTS_SIZE = 12;
public static final int CTRL_SLOTS_FIRST = INPUT_SLOTS_SIZE;
public static final int CTRL_SLOTS_SIZE = 3;
public static final int SHUTTER_CLOSE_DELAY = 40;
public static final int MAX_DROP_COUNT = 32;
public static final int DROP_PERIOD_OFFSET = 10;
///
public static final int DROPLOGIC_FILTER_ANDGATE = 0x01;
public static final int DROPLOGIC_EXTERN_ANDGATE = 0x02;
public static final int DROPLOGIC_SILENT_DROP = 0x04;
public static final int DROPLOGIC_SILENT_OPEN = 0x08;
public static final int DROPLOGIC_CONTINUOUS = 0x10;
///
private int filter_matches_[] = new int[CTRL_SLOTS_SIZE];
private int open_timer_ = 0;
private int drop_timer_ = 0;
private boolean triggered_ = false;
private boolean block_power_signal_ = false;
private boolean block_power_updated_ = false;
private int drop_speed_ = 10;
private int drop_noise_ = 0;
private int drop_xdev_ = 0;
private int drop_ydev_ = 0;
private int drop_count_ = 1;
private int drop_logic_ = DROPLOGIC_EXTERN_ANDGATE;
private int drop_period_ = 0;
private int drop_slot_index_ = 0;
private int tick_timer_ = 0;
protected NonNullList<ItemStack> stacks_;
public static void on_config(int cooldown_ticks)
{
// ModEngineersDecor.logger.info("Config factory dropper:");
}
public BTileEntity()
{
stacks_ = NonNullList.<ItemStack>withSize(NUM_OF_SLOTS, ItemStack.EMPTY);
reset_rtstate();
}
public void reset_rtstate()
{
block_power_signal_ = false;
block_power_updated_ = false;
for(int i=0; i<filter_matches_.length; ++i) filter_matches_[i] = 0;
}
public void readnbt(NBTTagCompound nbt, boolean update_packet)
{
stacks_ = NonNullList.<ItemStack>withSize(NUM_OF_SLOTS, ItemStack.EMPTY);
ItemStackHelper.loadAllItems(nbt, stacks_);
while(stacks_.size() < NUM_OF_SLOTS) stacks_.add(ItemStack.EMPTY);
block_power_signal_ = nbt.getBoolean("powered");
open_timer_ = nbt.getInteger("open_timer");
drop_speed_ = nbt.getInteger("drop_speed");
drop_noise_ = nbt.getInteger("drop_noise");
drop_xdev_ = nbt.getInteger("drop_xdev");
drop_ydev_ = nbt.getInteger("drop_ydev");
drop_slot_index_ = nbt.getInteger("drop_slot_index");
drop_count_ = MathHelper.clamp(nbt.getInteger("drop_count"), 1, MAX_DROP_COUNT);
drop_logic_ = nbt.getInteger("drop_logic");
drop_period_ = nbt.getInteger("drop_period");
}
protected void writenbt(NBTTagCompound nbt, boolean update_packet)
{
ItemStackHelper.saveAllItems(nbt, stacks_);
nbt.setBoolean("powered", block_power_signal_);
nbt.setInteger("open_timer", open_timer_);
nbt.setInteger("drop_speed", drop_speed_);
nbt.setInteger("drop_noise", drop_noise_);
nbt.setInteger("drop_xdev", drop_xdev_);
nbt.setInteger("drop_ydev", drop_ydev_);
nbt.setInteger("drop_slot_index", drop_slot_index_);
nbt.setInteger("drop_count", drop_count_);
nbt.setInteger("drop_logic", drop_logic_);
nbt.setInteger("drop_period", drop_period_);
}
public void block_updated()
{
// RS power check, both edges
boolean powered = world.isBlockPowered(pos);
if(block_power_signal_ != powered) block_power_updated_ = true;
block_power_signal_ = powered;
tick_timer_ = 1;
}
public boolean is_input_slot(int index)
{ return (index >= INPUT_SLOTS_FIRST) && (index < (INPUT_SLOTS_FIRST+INPUT_SLOTS_SIZE)); }
// TileEntity ------------------------------------------------------------------------------
@Override
public boolean shouldRefresh(World world, BlockPos pos, IBlockState os, IBlockState ns)
{ return (os.getBlock() != ns.getBlock()) || (!(ns.getBlock() instanceof BlockDecorDropper)); }
@Override
public void readFromNBT(NBTTagCompound nbt)
{ super.readFromNBT(nbt); readnbt(nbt, false); }
@Override
public NBTTagCompound writeToNBT(NBTTagCompound nbt)
{ super.writeToNBT(nbt); writenbt(nbt, false); return nbt; }
// IWorldNamable ---------------------------------------------------------------------------
@Override
public String getName()
{ final Block block=getBlockType(); return (block!=null) ? (block.getTranslationKey() + ".name") : (""); }
@Override
public boolean hasCustomName()
{ return false; }
@Override
public ITextComponent getDisplayName()
{ return new TextComponentTranslation(getName(), new Object[0]); }
// IInventory ------------------------------------------------------------------------------
@Override
public int getSizeInventory()
{ return stacks_.size(); }
@Override
public boolean isEmpty()
{ for(ItemStack stack: stacks_) { if(!stack.isEmpty()) return false; } return true; }
@Override
public ItemStack getStackInSlot(int index)
{ return (index < getSizeInventory()) ? stacks_.get(index) : ItemStack.EMPTY; }
@Override
public ItemStack decrStackSize(int index, int count)
{ return ItemStackHelper.getAndSplit(stacks_, index, count); }
@Override
public ItemStack removeStackFromSlot(int index)
{ return ItemStackHelper.getAndRemove(stacks_, index); }
@Override
public void setInventorySlotContents(int index, ItemStack stack)
{
stacks_.set(index, stack);
if(stack.getCount() > getInventoryStackLimit()) stack.setCount(getInventoryStackLimit());
if(tick_timer_ > 8) tick_timer_ = 8;
markDirty();
}
@Override
public int getInventoryStackLimit()
{ return 64; }
@Override
public void markDirty()
{ super.markDirty(); }
@Override
public boolean isUsableByPlayer(EntityPlayer player)
{ return ((world.getTileEntity(pos) == this) && (player.getDistanceSq(pos.getX()+0.5d, pos.getY()+0.5d, pos.getZ()+0.5d) <= 64.0d)); }
@Override
public void openInventory(EntityPlayer player)
{}
@Override
public void closeInventory(EntityPlayer player)
{ markDirty(); }
@Override
public boolean isItemValidForSlot(int index, ItemStack stack)
{ return true; }
@Override
public int getField(int id)
{
switch(id) {
case 0: return drop_speed_;
case 1: return drop_xdev_;
case 2: return drop_ydev_;
case 3: return drop_noise_;
case 4: return drop_count_;
case 5: return drop_logic_;
case 6: return drop_period_;
case 9: return drop_timer_;
case 10: return open_timer_;
case 11: return block_power_signal_ ? 1 : 0;
case 12: return filter_matches_[0];
case 13: return filter_matches_[1];
case 14: return filter_matches_[2];
case 15: return drop_slot_index_;
default: return 0;
}
}
@Override
public void setField(int id, int value)
{
switch(id) {
case 0: drop_speed_ = MathHelper.clamp(value, 0, 100); return;
case 1: drop_xdev_ = MathHelper.clamp(value, -100, 100); return;
case 2: drop_ydev_ = MathHelper.clamp(value, -100, 100); return;
case 3: drop_noise_ = MathHelper.clamp(value, 0, 100); return;
case 4: drop_count_ = MathHelper.clamp(value, 1, MAX_DROP_COUNT); return;
case 5: drop_logic_ = value; return;
case 6: drop_period_ = MathHelper.clamp(value, 0, 100); return;
case 9: drop_timer_ = MathHelper.clamp(value, 0, 400); return;
case 10: open_timer_ = MathHelper.clamp(value, 0, 400); return;
case 11: block_power_signal_ = (value != 0); return;
case 12: filter_matches_[0] = (value & 0x3); return;
case 13: filter_matches_[1] = (value & 0x3); return;
case 14: filter_matches_[2] = (value & 0x3); return;
case 15: drop_slot_index_ = MathHelper.clamp(value, INPUT_SLOTS_FIRST, INPUT_SLOTS_FIRST+INPUT_SLOTS_SIZE-1); return;
default: return;
}
}
@Override
public int getFieldCount()
{ return 16; }
@Override
public void clear()
{ stacks_.clear(); }
// ISidedInventory ----------------------------------------------------------------------------
private final IItemHandler item_handler_ = new SidedInvWrapper(this, EnumFacing.UP);
private static final int[] SIDED_INV_SLOTS;
static {
SIDED_INV_SLOTS = new int[INPUT_SLOTS_SIZE];
for(int i=0; i<INPUT_SLOTS_SIZE; ++i) SIDED_INV_SLOTS[i] = i+INPUT_SLOTS_FIRST;
}
@Override
public int[] getSlotsForFace(EnumFacing side)
{ return SIDED_INV_SLOTS; }
@Override
public boolean canInsertItem(int index, ItemStack stack, EnumFacing direction)
{ return is_input_slot(index) && isItemValidForSlot(index, stack); }
@Override
public boolean canExtractItem(int index, ItemStack stack, EnumFacing direction)
{ return false; }
// Capability export ----------------------------------------------------------------------------
@Override
public boolean hasCapability(Capability<?> cap, EnumFacing facing)
{ return (cap==CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) || super.hasCapability(cap, facing); }
@Override
@SuppressWarnings("unchecked")
@Nullable
public <T> T getCapability(Capability<T> capability, @Nullable EnumFacing facing)
{
if(capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) return (T)item_handler_;
return super.getCapability(capability, facing);
}
// IPacketReceiver -------------------------------------------------------------------------------
@Override
public void onServerPacketReceived(NBTTagCompound nbt)
{}
@Override
public void onClientPacketReceived(EntityPlayer player, NBTTagCompound nbt)
{
if(nbt.hasKey("drop_speed")) drop_speed_ = MathHelper.clamp(nbt.getInteger("drop_speed"), 0, 100);
if(nbt.hasKey("drop_xdev")) drop_xdev_ = MathHelper.clamp(nbt.getInteger("drop_xdev"), -100, 100);
if(nbt.hasKey("drop_ydev")) drop_ydev_ = MathHelper.clamp(nbt.getInteger("drop_ydev"), -100, 100);
if(nbt.hasKey("drop_count")) drop_count_ = MathHelper.clamp(nbt.getInteger("drop_count"), 1, MAX_DROP_COUNT);
if(nbt.hasKey("drop_period")) drop_period_ = MathHelper.clamp(nbt.getInteger("drop_period"), 0, 100);
if(nbt.hasKey("drop_logic")) drop_logic_ = nbt.getInteger("drop_logic");
if(nbt.hasKey("manual_rstrigger") && (nbt.getInteger("manual_rstrigger")!=0)) { block_power_signal_=true; block_power_updated_=true; tick_timer_=1; }
if(nbt.hasKey("manual_trigger") && (nbt.getInteger("manual_trigger")!=0)) { tick_timer_ = 1; triggered_ = true; }
markDirty();
}
// ITickable and aux methods ---------------------------------------------------------------------
private static void drop(World world, BlockPos pos, EnumFacing facing, ItemStack stack, int speed_percent, int xdeviation, int ydeviation, int noise_percent)
{
final double ofs = facing==EnumFacing.DOWN ? 0.8 : 0.7;
Vec3d v0 = new Vec3d(facing.getXOffset(), facing.getYOffset(), facing.getZOffset());
final EntityItem ei = new EntityItem(world, (pos.getX()+0.5)+(ofs*v0.x), (pos.getY()+0.5)+(ofs*v0.y), (pos.getZ()+0.5)+(ofs*v0.z), stack);
if((xdeviation != 0) || (ydeviation != 0)) {
double vdx = 1e-2 * MathHelper.clamp(xdeviation, -100, 100);
double vdy = 1e-2 * MathHelper.clamp(ydeviation, -100, 100);
switch(facing) { // switch-case faster than coorsys fwd transform
case DOWN: v0 = v0.add( vdx, 0,-vdy); break;
case NORTH: v0 = v0.add( vdx, vdy, 0); break;
case SOUTH: v0 = v0.add(-vdx, vdy, 0); break;
case EAST: v0 = v0.add(0, vdy, vdx); break;
case WEST: v0 = v0.add(0, vdy, -vdx); break;
case UP: v0 = v0.add( vdx, 0, vdy); break;
}
}
if(noise_percent > 0) {
v0 = v0.add(
((world.rand.nextDouble()-0.5) * 1e-3 * noise_percent),
((world.rand.nextDouble()-0.5) * 1e-3 * noise_percent),
((world.rand.nextDouble()-0.5) * 1e-3 * noise_percent)
);
}
if(speed_percent < 5) speed_percent = 5;
double speed = 1e-2 * speed_percent;
if(noise_percent > 0) speed += (world.rand.nextDouble()-0.5) * 1e-4 * noise_percent;
v0 = v0.normalize().scale(speed);
ei.motionX = v0.x;
ei.motionY = v0.y;
ei.motionZ = v0.z;
world.spawnEntity(ei);
}
@Nullable
IBlockState update_blockstate()
{
IBlockState state = world.getBlockState(pos);
if(!(state.getBlock() instanceof BlockDecorDropper)) return null;
boolean open = (open_timer_ > 0);
if(state.getValue(OPEN) != open) {
state = state.withProperty(OPEN, open);
world.setBlockState(pos, state, 2|16);
if((drop_logic_ & DROPLOGIC_SILENT_OPEN) == 0) {
if(open) {
world.playSound(null, pos, SoundEvents.BLOCK_WOODEN_TRAPDOOR_OPEN, SoundCategory.BLOCKS, 0.08f, 3f);
} else {
world.playSound(null, pos, SoundEvents.BLOCK_WOODEN_TRAPDOOR_CLOSE, SoundCategory.BLOCKS, 0.08f, 3f);
}
}
}
return state;
}
private static int next_slot(int i)
{ return (i<INPUT_SLOTS_SIZE-1) ? (i+1) : INPUT_SLOTS_FIRST; }
@Override
public void update()
{
if(world.isRemote) return;
if(--open_timer_ < 0) open_timer_ = 0;
if((drop_timer_ > 0) && ((--drop_timer_) == 0)) markDirty();
if(--tick_timer_ > 0) return;
tick_timer_ = TICK_INTERVAL;
if(!(world.getBlockState(pos).getBlock() instanceof BlockDecorDropper)) return;
boolean dirty = block_power_updated_;
final boolean continuous_mode = (drop_logic_ & DROPLOGIC_CONTINUOUS)!=0;
boolean redstone_trigger = (block_power_signal_ && ((block_power_updated_) || (continuous_mode)));
boolean filter_trigger;
boolean filter_defined = false;
boolean trigger;
// Trigger logic
{
boolean droppable_slot_found = false;
for(int i=INPUT_SLOTS_FIRST; i<(INPUT_SLOTS_FIRST+INPUT_SLOTS_SIZE); ++i) {
if(stacks_.get(i).getCount() >= drop_count_) { droppable_slot_found = true; break; }
}
// From filters / inventory checks
{
int filter_nset = 0;
int last_filter_matches_[] = filter_matches_.clone();
boolean slot_assigned = false;
for(int ci=0; ci<CTRL_SLOTS_SIZE; ++ci) {
filter_matches_[ci] = 0;
final ItemStack cmp_stack = stacks_.get(CTRL_SLOTS_FIRST+ci);
if(cmp_stack.isEmpty()) continue;
filter_matches_[ci] = 1;
final int cmp_stack_count = cmp_stack.getCount();
int inventory_item_count = 0;
int slot = drop_slot_index_;
for(int i=INPUT_SLOTS_FIRST; i<(INPUT_SLOTS_FIRST+INPUT_SLOTS_SIZE); ++i) {
final ItemStack inp_stack = stacks_.get(slot);
if(!inp_stack.isItemEqual(cmp_stack)) { slot = next_slot(slot); continue; }
inventory_item_count += inp_stack.getCount();
if(inventory_item_count < cmp_stack_count) { slot = next_slot(slot); continue; }
filter_matches_[ci] = 2;
break;
}
}
int nmatched = 0;
for(int i=0; i<filter_matches_.length; ++i) {
if(filter_matches_[i] > 0) ++filter_nset;
if(filter_matches_[i] > 1) ++nmatched;
if(filter_matches_[i] != last_filter_matches_[i]) dirty = true;
}
filter_defined = (filter_nset > 0);
filter_trigger = ((filter_nset > 0) && (nmatched > 0));
if(((drop_logic_ & DROPLOGIC_FILTER_ANDGATE) != 0) && (nmatched != filter_nset)) filter_trigger = false;
}
// gates
{
if(filter_defined) {
trigger = ((drop_logic_ & DROPLOGIC_EXTERN_ANDGATE) != 0) ? (filter_trigger && redstone_trigger) : (filter_trigger || redstone_trigger);
} else {
trigger = redstone_trigger;
}
if(triggered_) { triggered_ = false; trigger = true; }
if(!droppable_slot_found) {
if(open_timer_> 10) open_timer_ = 10; // override if dropping is not possible at all.
} else if(trigger || filter_trigger || redstone_trigger) {
open_timer_ = SHUTTER_CLOSE_DELAY;
}
}
// edge detection for next cycle
{
boolean tr = world.isBlockPowered(pos);
block_power_updated_ = (block_power_signal_ != tr);
block_power_signal_ = tr;
if(block_power_updated_) dirty = true;
}
}
// block state update
final IBlockState state = update_blockstate();
if(state == null) { block_power_signal_= false; return; }
// dispense action
if(trigger && (drop_timer_ <= 0)) {
// drop stack for non-filter triggers
ItemStack drop_stacks[] = {ItemStack.EMPTY,ItemStack.EMPTY,ItemStack.EMPTY};
if(!filter_trigger) {
for(int i=0; i<INPUT_SLOTS_SIZE; ++i) {
if(drop_slot_index_ >= INPUT_SLOTS_SIZE) drop_slot_index_ = 0;
int ic = drop_slot_index_;
drop_slot_index_ = next_slot(drop_slot_index_);
ItemStack ds = stacks_.get(ic);
if((!ds.isEmpty()) && (ds.getCount() >= drop_count_)) {
drop_stacks[0] = ds.splitStack(drop_count_);
stacks_.set(ic, ds);
break;
}
}
} else {
for(int fi=0; fi<filter_matches_.length; ++fi) {
if(filter_matches_[fi] > 1) {
drop_stacks[fi] = stacks_.get(CTRL_SLOTS_FIRST+fi).copy();
int ntoremove = drop_stacks[fi].getCount();
for(int i=INPUT_SLOTS_SIZE-1; (i>=0) && (ntoremove>0); --i) {
ItemStack stack = stacks_.get(i);
if(!stack.isItemEqual(drop_stacks[fi])) continue;
if(stack.getCount() <= ntoremove) {
ntoremove -= stack.getCount();
stacks_.set(i, ItemStack.EMPTY);
} else {
stack.shrink(ntoremove);
ntoremove = 0;
stacks_.set(i, stack);
}
}
if(ntoremove > 0) drop_stacks[fi].shrink(ntoremove);
}
}
}
// drop action
boolean dropped = false;
for(int i = 0; i < drop_stacks.length; ++i) {
if(drop_stacks[i].isEmpty()) continue;
dirty = true;
drop(world, pos, state.getValue(FACING), drop_stacks[i], drop_speed_, drop_xdev_, drop_ydev_, drop_noise_);
dropped = true;
}
// cooldown
if(dropped) drop_timer_ = DROP_PERIOD_OFFSET + drop_period_ * 2; // 0.1s time base -> 100%===10s
// drop sound
if(dropped && ((drop_logic_ & DROPLOGIC_SILENT_DROP) == 0)) {
world.playSound(null, pos, SoundEvents.BLOCK_CLOTH_STEP, SoundCategory.BLOCKS, 0.1f, 4f);
}
// advance to next nonempty slot.
for(int i = 0; i < INPUT_SLOTS_SIZE; ++i) {
if(!stacks_.get(drop_slot_index_).isEmpty()) break;
drop_slot_index_ = next_slot(drop_slot_index_);
}
}
if(dirty) markDirty();
if(trigger && (tick_timer_ > 10)) tick_timer_ = 10;
}
}
}

View file

@ -1,75 +0,0 @@
/*
* @file BlockDecorFence.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Fence blocks.
*/
package wile.engineersdecor.blocks;
import net.minecraft.block.*;
import net.minecraft.block.material.Material;
import net.minecraft.block.properties.IProperty;
import net.minecraft.block.state.BlockFaceShape;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.Entity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
public class BlockDecorFence extends BlockDecorWall
{
protected static final AxisAlignedBB[] AABB_BY_INDEX = mkAABBs (1.5d, 0.5d, 16d);
protected static final AxisAlignedBB[] CLIP_AABB_BY_INDEX = mkAABBs (1.5d, 0.5d, 24d);
protected static final AxisAlignedBB[][] AABB_LIST_BY_INDEX = mkCAABBs(1.5d, 0.5d, 16d);
protected static final AxisAlignedBB[][] CLIP_AABB_LIST_BY_INDEX = mkCAABBs(1.5d, 0.5d, 24d);
public BlockDecorFence(@Nonnull String registryName, long config, @Nullable Material material, float hardness, float resistance, @Nullable SoundType sound)
{
super(registryName, config, material, hardness, resistance, sound);
setDefaultState(blockState.getBaseState().withProperty(UP, false).withProperty(NORTH, false).withProperty(EAST, false).withProperty(SOUTH, false).withProperty(WEST, false));
}
@Override
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos)
{ return AABB_BY_INDEX[getAABBIndex(getActualState(state, source, pos))]; }
@Override
@SuppressWarnings("deprecation")
public void addCollisionBoxToList(IBlockState state, World world, BlockPos pos, AxisAlignedBB entityBox, List<AxisAlignedBB> collidingBoxes, @Nullable Entity entityIn, boolean isActualState)
{
final AxisAlignedBB[] bbs = CLIP_AABB_LIST_BY_INDEX[getAABBIndex(isActualState ? state : getActualState(state, world, pos))];
for(int i=0; i<bbs.length;++i) addCollisionBoxToList(pos, entityBox, collidingBoxes, bbs[i]);
}
@Override
public AxisAlignedBB getCollisionBoundingBox(IBlockState state, IBlockAccess world, BlockPos pos)
{ return CLIP_AABB_BY_INDEX[getAABBIndex(getActualState(state, world, pos))]; }
@Override
public BlockFaceShape getBlockFaceShape(IBlockAccess world, IBlockState state, BlockPos pos, EnumFacing face)
{ return (face==EnumFacing.UP) ? (BlockFaceShape.CENTER) : ((face!=EnumFacing.DOWN) ? (BlockFaceShape.MIDDLE_POLE_THIN) : (BlockFaceShape.CENTER_SMALL)); }
@Override
protected BlockStateContainer createBlockState()
{ return new BlockStateContainer(this, new IProperty[] {UP, NORTH, EAST, WEST, SOUTH}); }
@Override
public IBlockState getActualState(IBlockState state, IBlockAccess world, BlockPos pos)
{
boolean n = canWallConnectTo(world, pos, EnumFacing.NORTH);
boolean e = canWallConnectTo(world, pos, EnumFacing.EAST);
boolean s = canWallConnectTo(world, pos, EnumFacing.SOUTH);
boolean w = canWallConnectTo(world, pos, EnumFacing.WEST);
boolean nopole = (n && s && !e && !w) || (!n && !s && e && w);
return state.withProperty(UP,!nopole).withProperty(NORTH, n).withProperty(EAST, e).withProperty(SOUTH, s).withProperty(WEST, w);
}
}

View file

@ -1,71 +0,0 @@
/*
* @file BlockDecorFloorGrating.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Floor gratings.
*/
package wile.engineersdecor.blocks;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.BlockFaceShape;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class BlockDecorFloorGrating extends BlockDecor
{
public BlockDecorFloorGrating(@Nonnull String registryName, long config, @Nullable Material material, float hardness, float resistance, @Nullable SoundType sound, @Nullable AxisAlignedBB boundingbox)
{ super(registryName, config, material, hardness, resistance, sound, (boundingbox==null) ? (new AxisAlignedBB[]{FULL_BLOCK_AABB}) : (new AxisAlignedBB[]{boundingbox})); }
@Override
public boolean isFullCube(IBlockState state)
{ return false; }
@Override
public boolean isNormalCube(IBlockState state)
{ return false; }
@Override
public boolean isOpaqueCube(IBlockState state)
{ return false; }
@Override
public BlockFaceShape getBlockFaceShape(IBlockAccess world, IBlockState state, BlockPos pos, EnumFacing face)
{ return BlockFaceShape.UNDEFINED; }
@Override
public void onEntityCollision(World world, BlockPos pos, IBlockState state, Entity entity)
{
if(!(entity instanceof EntityItem)) return;
final boolean colliding = ((entity.posY-pos.getY()) > 0.7);
if(colliding || (entity.motionY > 0)) {
double x = pos.getX() + 0.5;
double y = MathHelper.clamp(entity.posY-0.3, pos.getY(), pos.getY()+0.6);
double z = pos.getZ() + 0.5;
if(colliding) {
entity.motionX = 0;
entity.motionZ = 0;
entity.motionY = -0.3;
if((entity.posY-pos.getY()) > 0.8) y = pos.getY() + 0.6;
entity.prevPosX = x+0.1;
entity.prevPosY = y+0.1;
entity.prevPosZ = z+0.1;
}
entity.motionY = MathHelper.clamp(entity.motionY, -0.3, 0);
entity.fallDistance = 0;
entity.setPositionAndUpdate(x,y,z);
}
}
}

View file

@ -1,387 +0,0 @@
/*
* @file BlockDecorFluidFunnel.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* A device that collects and stores fluid blocks above it.
* Tracks flowing fluid to their source blocks. Compatible
* with vanilla infinite water source.
*/
package wile.engineersdecor.blocks;
import net.minecraft.block.*;
import net.minecraft.block.material.Material;
import net.minecraft.block.properties.PropertyInteger;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.*;
import net.minecraft.world.World;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.ITickable;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.fluids.*;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.fluids.capability.IFluidTankProperties;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.*;
public class BlockDecorFluidFunnel extends BlockDecor
{
public static final int FILL_LEVEL_MAX = 3;
public static final PropertyInteger FILL_LEVEL = PropertyInteger.create("level", 0, FILL_LEVEL_MAX);
public BlockDecorFluidFunnel(@Nonnull String registryName, long config, @Nullable Material material, float hardness, float resistance, @Nullable SoundType sound, @Nonnull AxisAlignedBB unrotatedAABB)
{ super(registryName, config, material, hardness, resistance, sound, unrotatedAABB); }
@Override
protected BlockStateContainer createBlockState()
{ return new BlockStateContainer(this, FILL_LEVEL); }
@Override
public IBlockState getStateFromMeta(int meta)
{ return super.getStateFromMeta(meta).withProperty(FILL_LEVEL, meta & 0x3); }
@Override
public int getMetaFromState(IBlockState state)
{ return super.getMetaFromState(state) | (state.getValue(FILL_LEVEL)); }
@Override
public IBlockState getStateForPlacement(World world, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer, EnumHand hand)
{ return super.getStateForPlacement(world, pos, facing, hitX, hitY, hitZ, meta, placer, hand).withProperty(FILL_LEVEL, 0); }
@Override
@SuppressWarnings("deprecation")
public int getComparatorInputOverride(IBlockState state, World world, BlockPos pos)
{ return MathHelper.clamp((state.getValue(FILL_LEVEL)*5), 0, 15); }
@Override
public boolean hasTileEntity(IBlockState state)
{ return true; }
@Override
@Nullable
public TileEntity createTileEntity(World world, IBlockState state)
{ return new BTileEntity(); }
@Override
public void onBlockPlacedBy(World world, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack)
{
if(world.isRemote) return;
if((!stack.hasTagCompound()) || (!stack.getTagCompound().hasKey("tedata"))) return;
NBTTagCompound te_nbt = stack.getTagCompound().getCompoundTag("tedata");
if(te_nbt.isEmpty()) return;
final TileEntity te = world.getTileEntity(pos);
if(!(te instanceof BTileEntity)) return;
((BTileEntity)te).readnbt(te_nbt, false);
((BTileEntity)te).markDirty();
}
@Override
public boolean removedByPlayer(IBlockState state, World world, BlockPos pos, EntityPlayer player, boolean willHarvest)
{
if(world.isRemote) return true;
TileEntity te = world.getTileEntity(pos);
if(!(te instanceof BTileEntity)) return super.removedByPlayer(state, world, pos, player, willHarvest);
ItemStack stack = new ItemStack(this, 1);
NBTTagCompound te_nbt = new NBTTagCompound();
((BTileEntity) te).writenbt(te_nbt, false);
if(!te_nbt.isEmpty()) {
NBTTagCompound nbt = new NBTTagCompound();
nbt.setTag("tedata", te_nbt);
stack.setTagCompound(nbt);
}
world.spawnEntity(new EntityItem(world, pos.getX()+0.5, pos.getY()+0.5, pos.getZ()+0.5, stack));
world.setBlockToAir(pos);
world.removeTileEntity(pos);
return false;
}
@Override
public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
{
if(world.isRemote) return true;
TileEntity te = world.getTileEntity(pos);
if(!(te instanceof BTileEntity)) return false;
return FluidUtil.interactWithFluidHandler(player, hand, world, pos, facing);
}
@Override
public void neighborChanged(IBlockState state, World world, BlockPos pos, Block block, BlockPos fromPos)
{ TileEntity te = world.getTileEntity(pos); if(te instanceof BTileEntity) ((BTileEntity)te).block_changed(); }
//--------------------------------------------------------------------------------------------------------------------
// Tile entity
//--------------------------------------------------------------------------------------------------------------------
public static class BTileEntity extends TileEntity implements IFluidHandler, IFluidTankProperties, ICapabilityProvider, ITickable
{
public static final int TANK_CAPACITY = 3000;
public static final int TICK_INTERVAL = 10; // ca 500ms
public static final int COLLECTION_INTERVAL = 40; // ca 2000ms, simulates suction delay and saves CPU when not drained.
public static final int MAX_TRACK_RADIUS = 16;
public static final int MAX_TRACKING_STEPS_PER_CYCLE = 72;
public static final int MAX_TRACKING_STEPS_PER_CYCLE_INTENSIVE = 1024;
public static final int MAX_TRACK_RADIUS_SQ = MAX_TRACK_RADIUS*MAX_TRACK_RADIUS;
public static final int INTENSIVE_SEARCH_TRIGGER_THRESHOLD = 16;
private final IFluidTankProperties[] fluid_props_ = {this};
private FluidStack tank_ = null;
private int tick_timer_ = 0;
private int collection_timer_ = 0;
private BlockPos last_pick_pos_ = BlockPos.ORIGIN;
private ArrayList<Vec3i> search_offsets_ = null;
private int no_fluid_found_counter_ = 0;
private int intensive_search_counter_ = 0;
private int total_pick_counter_ = 0;
public BTileEntity()
{}
public void block_changed()
{ tick_timer_ = TICK_INTERVAL; } // collect after flowing fluid has a stable state, otherwise it looks odd.
public void readnbt(NBTTagCompound nbt, boolean update_packet)
{
tank_ = (!nbt.hasKey("tank")) ? (null) : (FluidStack.loadFluidStackFromNBT(nbt.getCompoundTag("tank")));
}
protected void writenbt(NBTTagCompound nbt, boolean update_packet)
{
if(tank_ != null) nbt.setTag("tank", tank_.writeToNBT(new NBTTagCompound()));
}
// TileEntity ------------------------------------------------------------------------------
@Override
public boolean shouldRefresh(World world, BlockPos pos, IBlockState os, IBlockState ns)
{
block_changed();
return (os.getBlock() != ns.getBlock()) || (!(ns.getBlock() instanceof BlockDecorFluidFunnel));
}
@Override
public void readFromNBT(NBTTagCompound nbt)
{ super.readFromNBT(nbt); readnbt(nbt, false); }
@Override
public NBTTagCompound writeToNBT(NBTTagCompound nbt)
{ super.writeToNBT(nbt); writenbt(nbt, false); return nbt; }
// ICapabilityProvider --------------------------------------------------------------------
@Override
public boolean hasCapability(@Nonnull Capability<?> capability, @Nullable EnumFacing facing)
{ return ((capability==CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY)) || super.hasCapability(capability, facing); }
@Override
@Nullable
@SuppressWarnings("unchecked")
public <T> T getCapability(@Nonnull Capability<T> capability, @Nullable EnumFacing facing)
{
if(capability != CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) return super.getCapability(capability, facing);
return ((T)this);
}
// IFluidHandler of the output port --------------------------------------------------------
@Override
public IFluidTankProperties[] getTankProperties()
{ return fluid_props_; }
@Override
public int fill(FluidStack resource, boolean doFill)
{ return 0; }
@Override
@Nullable
public FluidStack drain(FluidStack resource, boolean doDrain)
{
if((resource==null) || (tank_==null)) return null;
return (!(tank_.isFluidEqual(resource))) ? (null) : drain(resource.amount, doDrain);
}
@Override
@Nullable
public FluidStack drain(int maxDrain, boolean doDrain)
{
if(tank_==null) return null;
maxDrain = MathHelper.clamp(maxDrain ,0 , tank_.amount);
FluidStack res = tank_.copy();
res.amount = maxDrain;
if(doDrain) tank_.amount -= maxDrain;
if(tank_.amount <= 0) tank_= null;
return res;
}
// IFluidTankProperties --------------------------------------------------------------------
@Override @Nullable public FluidStack getContents() { return (tank_==null) ? (null) : (tank_.copy()); }
@Override public int getCapacity() { return TANK_CAPACITY; }
@Override public boolean canFill() { return false; }
@Override public boolean canDrain() { return true; }
@Override public boolean canFillFluidType(FluidStack fluidStack) { return false; }
@Override public boolean canDrainFluidType(FluidStack fluidStack) { return true; }
// ITickable--------------------------------------------------------------------------------
private Fluid get_fluid(BlockPos pos)
{ return FluidRegistry.lookupFluidForBlock(world.getBlockState(pos).getBlock()); }
private boolean try_pick(BlockPos pos)
{
IFluidHandler hnd = FluidUtil.getFluidHandler(world, pos, null);
if(hnd == null) return false;
FluidStack fs = hnd.drain((tank_==null) ? (TANK_CAPACITY) : (TANK_CAPACITY-tank_.amount), true);
if(fs == null) return false;
if(tank_ == null) {
tank_ = fs.copy();
} else if(tank_.isFluidEqual(fs)) {
tank_.amount = MathHelper.clamp(tank_.amount+fs.amount, 0, TANK_CAPACITY);
} else {
return false;
}
world.setBlockToAir(pos);
world.notifyNeighborsOfStateChange(pos, world.getBlockState(pos).getBlock(), true); // explicitly update neighbours to allow these start flowing
return true;
}
private boolean can_pick(BlockPos pos, Fluid fluid)
{
IFluidHandler hnd = FluidUtil.getFluidHandler(world, pos, null);
if(hnd == null) return false;
FluidStack fs = hnd.drain((tank_==null) ? (TANK_CAPACITY) : (TANK_CAPACITY-tank_.amount), false);
return (fs != null) && (fs.getFluid().equals(fluid));
}
private void rebuild_search_offsets(boolean intensive)
{
search_offsets_ = new ArrayList<>(9);
search_offsets_.add(new Vec3i(0, 1, 0)); // up first
{
ArrayList<Vec3i> ofs = new ArrayList<Vec3i>(Arrays.asList(new Vec3i(-1, 0, 0), new Vec3i( 1, 0, 0), new Vec3i( 0, 0,-1), new Vec3i( 0, 0, 1)));
if(intensive || (total_pick_counter_ > 50)) Collections.shuffle(ofs);
search_offsets_.addAll(ofs);
}
if(intensive) {
ArrayList<Vec3i> ofs = new ArrayList<Vec3i>(Arrays.asList(new Vec3i(-1, 1, 0), new Vec3i( 1, 1, 0), new Vec3i( 0, 1,-1), new Vec3i( 0, 1, 1)));
Collections.shuffle(ofs);
search_offsets_.addAll(ofs);
}
}
private boolean try_collect(BlockPos collection_pos)
{
final Block collection_block = world.getBlockState(collection_pos).getBlock();
if((!(collection_block instanceof IFluidBlock)) && (!(collection_block instanceof BlockLiquid))) return false;
final Fluid fluid_to_collect = FluidRegistry.lookupFluidForBlock(collection_block);
if(fluid_to_collect == null) return false; // not sure if that can return null
if((tank_!=null) && (!tank_.getFluid().equals(fluid_to_collect))) return false;
if(try_pick(collection_pos)) { last_pick_pos_ = collection_pos; return true; } // Blocks directly always first. Allows water source blocks to recover/reflow to source blocks.
// Not picked, not a source block -> search highest allowed source block to pick
// ---------------------------------------------------------------------------------------------------------------
// Plan is to pick preferably surface blocks whilst not wasting much mem and cpu. Blocks will dynamically change due to flowing.
// Basic assumptions: fluid flows straight (not diagonal) and not up the hill. Only falling fluid streams are long, lateral streams are about max 16 blocks (water 8).
// Problem resolving: Threre are fluids going all over the place, and do not sometimes continue flowing without a source block.
// - Stack based trail tracking is used
// - Turtle motion with reset on fail, preferrs up, remaining motion order is shuffled to pick not in the same direction.
// - Calculation time capping, reset on fail, extended search for far blocks (e.g. stream from a high position) on many fails.
// - Preferrs fluid surface blocks if possible and anough calculation time left.
// - On fail, replace last flowing block with air and cause a block update, in case previous block updates or strange fluid block behaviour does not prevent advancing.
// - Assumption is: The search can go much further than fluids can flow, except top-bottom falling streams. so
if((last_pick_pos_==null) || (last_pick_pos_.distanceSq(collection_pos) > MAX_TRACK_RADIUS_SQ)) { last_pick_pos_ = collection_pos; search_offsets_ = null; }
BlockPos pos = last_pick_pos_;
HashSet<BlockPos> checked = new HashSet<>();
Stack<BlockPos> trail = new Stack<BlockPos>();
trail.add(pos);
checked.add(pos);
int steps=0;
boolean intensive = (no_fluid_found_counter_ >= INTENSIVE_SEARCH_TRIGGER_THRESHOLD);
if(intensive) { no_fluid_found_counter_ = 0; ++intensive_search_counter_; }
if(search_offsets_ == null) rebuild_search_offsets(intensive);
int max = intensive ? MAX_TRACKING_STEPS_PER_CYCLE_INTENSIVE : MAX_TRACKING_STEPS_PER_CYCLE;
while(++steps <= max) {
int num_adjacent = 0;
for(int i=0; i<search_offsets_.size(); ++i) {
BlockPos p = pos.add(search_offsets_.get(i));
if(checked.contains(p)) continue;
checked.add(p);
++steps;
if(fluid_to_collect.equals(get_fluid(p))) {
++num_adjacent;
pos = p;
trail.push(pos);
if(steps < MAX_TRACKING_STEPS_PER_CYCLE_INTENSIVE/2) {
// check for same fluid above (only source blocks)
final int max_surface_search = (MAX_TRACKING_STEPS_PER_CYCLE_INTENSIVE/2)-steps;
for(int k=0; k<max_surface_search; ++k) {
if(!can_pick(pos.up(), fluid_to_collect)) break;
pos = pos.up();
trail.push(pos);
}
}
if(try_pick(pos)) {
last_pick_pos_ = pos;
no_fluid_found_counter_ = 0;
search_offsets_ = null;
// probability reset, so it's not turteling too far away, mainly for large nether lava seas, not desert lakes.
if((++total_pick_counter_ > 50) && world.rand.nextInt(10)==0) last_pick_pos_ = collection_pos;
//println("PASS " + steps + " - " + (pos.subtract(collection_pos)));
return true;
}
}
}
if(trail.isEmpty()) break; // reset search
if(num_adjacent==0) pos = trail.pop();
}
if(intensive_search_counter_ > 2) world.setBlockToAir(pos);
last_pick_pos_ = collection_pos;
search_offsets_ = null; // try other search order
++no_fluid_found_counter_;
return false;
}
public void update()
{
if((world.isRemote) || (--tick_timer_ > 0)) return;
tick_timer_ = TICK_INTERVAL;
collection_timer_ += TICK_INTERVAL;
final IBlockState funnel_state = world.getBlockState(pos);
if(!(funnel_state.getBlock() instanceof BlockDecorFluidFunnel)) return;
boolean dirty = false;
// Collection
if((collection_timer_ >= COLLECTION_INTERVAL) && ((tank_==null) || (tank_.amount <= (TANK_CAPACITY-1000)))) {
collection_timer_ = 0;
if(!world.isBlockPowered(pos)) { // redstone disable feature
if(last_pick_pos_==null) last_pick_pos_ = pos.up();
if(try_collect(pos.up())) dirty = true;
}
}
// Gravity fluid transfer
if((tank_!=null) && (tank_.amount >= 1000)) {
IFluidHandler fh = FluidUtil.getFluidHandler(world, pos.down(), EnumFacing.UP);
if(fh != null) {
FluidStack fs = new FluidStack(tank_.getFluid(), 1000);
int nfilled = MathHelper.clamp(fh.fill(fs, true), 0, 1000);
tank_.amount -= nfilled;
if(tank_.amount <= 0) tank_ = null;
dirty = true;
}
}
// Block state
int fill_level = (tank_==null) ? 0 : (MathHelper.clamp(tank_.amount/1000,0,FILL_LEVEL_MAX));
if(funnel_state.getValue(FILL_LEVEL) != fill_level) world.setBlockState(pos, funnel_state.withProperty(FILL_LEVEL, fill_level), 2|16);
if(dirty) markDirty();
}
}
}

View file

@ -1,61 +0,0 @@
/*
* @file BlockDecorFull.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Full block characteristics class.
*/
package wile.engineersdecor.blocks;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.BlockFaceShape;
import net.minecraft.block.state.IBlockState;
import net.minecraft.world.IBlockAccess;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class BlockDecorFull extends BlockDecor
{
public BlockDecorFull(@Nonnull String registryName, long config, @Nullable Material material, float hardness, float resistance, @Nullable SoundType sound)
{ super(registryName, config, material, hardness, resistance, sound); }
@Override
public boolean isOpaqueCube(IBlockState state)
{ return true; }
@Override
@SuppressWarnings("deprecation")
public BlockFaceShape getBlockFaceShape(IBlockAccess world, IBlockState state, BlockPos pos, EnumFacing face)
{ return BlockFaceShape.SOLID; }
@Override
@SuppressWarnings("deprecation")
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos)
{ return FULL_BLOCK_AABB; }
@Override
@Nullable
public AxisAlignedBB getCollisionBoundingBox(IBlockState state, IBlockAccess world, BlockPos pos)
{ return FULL_BLOCK_AABB; }
@Override
@SuppressWarnings("deprecation")
public boolean isFullCube(IBlockState state)
{ return true; }
@Override
@SuppressWarnings("deprecation")
public boolean isNormalCube(IBlockState state)
{ return true; }
@Override
public int getLightValue(IBlockState state, IBlockAccess world, BlockPos pos)
{ return (int)((config & CFG_LIGHT_VALUE_MASK) >> CFG_LIGHT_VALUE_SHIFT); }
}

View file

@ -1,955 +0,0 @@
/*
* @file BlockFurnace.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* ED Lab furnace.
*/
package wile.engineersdecor.blocks;
import wile.engineersdecor.ModEngineersDecor;
import wile.engineersdecor.detail.ExtItems;
import net.minecraft.block.properties.PropertyBool;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.Block;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.world.World;
import net.minecraft.world.Explosion;
import net.minecraft.entity.item.EntityXPOrb;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.tileentity.TileEntityFurnace;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.init.SoundEvents;
import net.minecraft.init.Items;
import net.minecraft.item.*;
import net.minecraft.item.crafting.FurnaceRecipes;
import net.minecraft.inventory.*;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentTranslation;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.*;
import net.minecraft.stats.StatList;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.energy.CapabilityEnergy;
import net.minecraftforge.energy.IEnergyStorage;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.wrapper.SidedInvWrapper;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import com.google.common.collect.Maps;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Map;
import java.util.Random;
public class BlockDecorFurnace extends BlockDecorDirected
{
//--------------------------------------------------------------------------------------------------------------------
// Config
//--------------------------------------------------------------------------------------------------------------------
public static final int TICK_INTERVAL = 4;
public static final int FIFO_INTERVAL = 20;
public static final int MAX_BURNTIME = 0x7fff;
public static final int DEFAULT_BOOST_ENERGY = 32;
public static final int VANILLA_FURNACE_SPEED_INTERVAL = 200;
public static final int DEFAULT_SPEED_INTERVAL = 150;
private static double proc_fuel_efficiency_ = 1.0;
private static int proc_speed_interval_ = DEFAULT_SPEED_INTERVAL;
private static int boost_energy_consumption = DEFAULT_BOOST_ENERGY * TICK_INTERVAL;
public static void on_config(int speed_percent, int fuel_efficiency_percent, int boost_energy_per_tick)
{
double ratio = (100.0 / MathHelper.clamp(speed_percent, 10, 500)) ;
proc_speed_interval_ = MathHelper.clamp((int)(ratio * VANILLA_FURNACE_SPEED_INTERVAL), 20, 400);
proc_fuel_efficiency_ = ((double) MathHelper.clamp(fuel_efficiency_percent, 10, 500)) / 100;
boost_energy_consumption = TICK_INTERVAL * MathHelper.clamp(boost_energy_per_tick, 16, 512);
ModEngineersDecor.logger.info("Config lab furnace interval:" + proc_speed_interval_ + ", efficiency:" + proc_fuel_efficiency_);
}
//--------------------------------------------------------------------------------------------------------------------
// Block
//--------------------------------------------------------------------------------------------------------------------
public static final PropertyBool LIT = PropertyBool.create("lit");
public BlockDecorFurnace(@Nonnull String registryName, long config, @Nullable Material material, float hardness, float resistance, @Nullable SoundType sound, @Nonnull AxisAlignedBB unrotatedAABB)
{
super(registryName, config, material, hardness, resistance, sound, unrotatedAABB);
setLightOpacity(0);
}
@Override
protected BlockStateContainer createBlockState()
{ return new BlockStateContainer(this, FACING, LIT); }
@Override
public IBlockState getStateFromMeta(int meta)
{ return getDefaultState().withProperty(FACING, EnumFacing.byHorizontalIndex(meta & 0x3)).withProperty(LIT, (meta & 0x4)!=0); }
@Override
public int getMetaFromState(IBlockState state)
{ return (state.getValue(FACING).getHorizontalIndex() & 0x3) | (state.getValue(LIT) ? 4 : 0); }
@Override
public IBlockState getStateForPlacement(World world, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer, EnumHand hand)
{ return getDefaultState().withProperty(FACING, placer.getHorizontalFacing().getOpposite()).withProperty(LIT, false); }
@Override
@SuppressWarnings("deprecation")
public boolean hasComparatorInputOverride(IBlockState state)
{ return true; }
@Override
@SuppressWarnings("deprecation")
public int getComparatorInputOverride(IBlockState blockState, World world, BlockPos pos)
{ return Container.calcRedstone(world.getTileEntity(pos)); }
@Override
public boolean hasTileEntity(IBlockState state)
{ return true; }
@Override
@Nullable
public TileEntity createTileEntity(World world, IBlockState state)
{ return new BlockDecorFurnace.BTileEntity(); }
@Override
public void onBlockPlacedBy(World world, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack)
{
if(world.isRemote) return;
if((!stack.hasTagCompound()) || (!stack.getTagCompound().hasKey("inventory"))) return;
NBTTagCompound inventory_nbt = stack.getTagCompound().getCompoundTag("inventory");
if(inventory_nbt.isEmpty()) return;
final TileEntity te = world.getTileEntity(pos);
if(!(te instanceof BlockDecorFurnace.BTileEntity)) return;
((BlockDecorFurnace.BTileEntity)te).readnbt(inventory_nbt);
((BlockDecorFurnace.BTileEntity)te).markDirty();
}
@Override
public boolean removedByPlayer(IBlockState state, World world, BlockPos pos, EntityPlayer player, boolean willHarvest)
{
if(world.isRemote) return true;
TileEntity te = world.getTileEntity(pos);
if(!(te instanceof BTileEntity)) return super.removedByPlayer(state, world, pos, player, willHarvest);
ItemStack stack = new ItemStack(this, 1);
NBTTagCompound inventory_nbt = new NBTTagCompound();
ItemStackHelper.saveAllItems(inventory_nbt, ((BTileEntity)te).stacks_, false);
if(!inventory_nbt.isEmpty()) {
NBTTagCompound nbt = new NBTTagCompound();
nbt.setTag("inventory", inventory_nbt);
stack.setTagCompound(nbt);
}
world.spawnEntity(new EntityItem(world, pos.getX()+0.5, pos.getY()+0.5, pos.getZ()+0.5, stack));
world.setBlockToAir(pos);
world.removeTileEntity(pos);
return false;
}
@Override
public void onBlockExploded(World world, BlockPos pos, Explosion explosion)
{
if(world.isRemote) return;
TileEntity te = world.getTileEntity(pos);
if(!(te instanceof BTileEntity)) return;
for(ItemStack stack: ((BTileEntity)te).stacks_) {
if(!stack.isEmpty()) world.spawnEntity(new EntityItem(world, pos.getX(), pos.getY(), pos.getZ(), stack));
}
((BTileEntity)te).reset();
super.onBlockExploded(world, pos, explosion);
}
@Override
public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
{
if(world.isRemote) return true;
player.openGui(ModEngineersDecor.instance, ModEngineersDecor.GuiHandler.GUIID_SMALL_LAB_FURNACE, world, pos.getX(), pos.getY(), pos.getZ());
player.addStat(StatList.FURNACE_INTERACTION);
return true;
}
@Override
@SideOnly(Side.CLIENT)
public void randomDisplayTick(IBlockState state, World world, BlockPos pos, Random rnd)
{
if((state.getBlock()!=this) || (!state.getValue(LIT))) return;
final double rv = rnd.nextDouble();
if(rv > 0.5) return;
final double x=0.5+pos.getX(), y=0.5+pos.getY(), z=0.5+pos.getZ();
final double xc=0.52, xr=rnd.nextDouble()*0.4-0.2, yr=(y-0.3+rnd.nextDouble()*0.2);
if(rv < 0.1d) world.playSound(x, y, z, SoundEvents.BLOCK_FURNACE_FIRE_CRACKLE, SoundCategory.BLOCKS, 0.4f, 0.5f, false);
switch(state.getValue(FACING)) {
case WEST: world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, x-xc, yr, z+xr, 0.0, 0.0, 0.0); break;
case EAST: world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, x+xc, yr, z+xr, 0.0, 0.0, 0.0); break;
case NORTH: world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, x+xr, yr, z-xc, 0.0, 0.0, 0.0); break;
default: world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, x+xr, yr, z+xc, 0.0, 0.0, 0.0); break;
}
}
//--------------------------------------------------------------------------------------------------------------------
// ModEngineersDecor.GuiHandler connectors
//--------------------------------------------------------------------------------------------------------------------
public static Object getServerGuiElement(final EntityPlayer player, final World world, final BlockPos pos, final TileEntity te)
{ return (te instanceof BTileEntity) ? (new BContainer(player.inventory, world, pos, (BTileEntity)te)) : null; }
public static Object getClientGuiElement(final EntityPlayer player, final World world, final BlockPos pos, final TileEntity te)
{ return (te instanceof BTileEntity) ? (new BGui(player.inventory, world, pos, (BTileEntity)te)) : null; }
//--------------------------------------------------------------------------------------------------------------------
// GUI
//--------------------------------------------------------------------------------------------------------------------
@SideOnly(Side.CLIENT)
private static class BGui extends GuiContainer
{
private final BTileEntity te;
public BGui(InventoryPlayer playerInventory, World world, BlockPos pos, BTileEntity te)
{ super(new BContainer(playerInventory, world, pos, te)); this.te = te; }
@Override
public void initGui()
{ super.initGui(); }
@Override
public void drawScreen(int mouseX, int mouseY, float partialTicks)
{
drawDefaultBackground();
super.drawScreen(mouseX, mouseY, partialTicks);
renderHoveredToolTip(mouseX, mouseY);
}
@Override
protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY)
{
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
mc.getTextureManager().bindTexture(new ResourceLocation(ModEngineersDecor.MODID, "textures/gui/small_lab_furnace_gui.png"));
final int x0=(width-xSize)/2, y0=(height-ySize)/2, w=xSize, h=ySize;
drawTexturedModalRect(x0, y0, 0, 0, w, h);
if(BTileEntity.isBurning(te)) {
final int k = flame_px(13);
drawTexturedModalRect(x0+59, y0+36+12-k, 176, 12-k, 14, k+1);
}
drawTexturedModalRect(x0+79, y0+36, 176, 15, 1+progress_px(17), 15);
}
private int progress_px(int pixels)
{ final int tc=te.getField(2), T=te.getField(3); return ((T>0) && (tc>0)) ? (tc * pixels / T) : (0); }
private int flame_px(int pixels)
{ int ibt = te.getField(1); return ((te.getField(0) * pixels) / ((ibt>0) ? (ibt) : (proc_speed_interval_))); }
}
//--------------------------------------------------------------------------------------------------------------------
// container slots
//--------------------------------------------------------------------------------------------------------------------
public static class BSlotInpFifo extends Slot
{
public BSlotInpFifo(IInventory inv, int index, int xpos, int ypos)
{ super(inv, index, xpos, ypos); }
}
public static class BSlotFuelFifo extends Slot
{
public BSlotFuelFifo(IInventory inv, int index, int xpos, int ypos)
{ super(inv, index, xpos, ypos); }
}
public static class BSlotOutFifo extends BSlotResult
{
public BSlotOutFifo(EntityPlayer player, BTileEntity te, int index, int xpos, int ypos)
{ super(player, te, index, xpos, ypos); }
}
public static class BSlotResult extends Slot
{
// This class is basically SlotFurnaceOutput.onCrafting(), except that the recipe overrides
// are used, unfortunately a copy is needed due to private instance variables.
private final EntityPlayer player;
private int removeCount = 0;
public BSlotResult(EntityPlayer player, BTileEntity te, int index, int xpos, int ypos)
{ super(te, index, xpos, ypos); this.player = player; }
@Override
public boolean isItemValid(ItemStack stack)
{ return false; }
@Override
public ItemStack decrStackSize(int amount)
{ removeCount += getHasStack() ? Math.min(amount, getStack().getCount()) : 0; return super.decrStackSize(amount); }
@Override
public ItemStack onTake(EntityPlayer thePlayer, ItemStack stack)
{ onCrafting(stack); super.onTake(thePlayer, stack); return stack; }
@Override
protected void onCrafting(ItemStack stack, int amount)
{ removeCount += amount; onCrafting(stack); }
@Override
protected void onCrafting(ItemStack stack)
{
stack.onCrafting(player.world, player, removeCount);
if(!player.world.isRemote) {
int xp = removeCount;
float sxp = BRecipes.instance().getSmeltingExperience(stack);
if(sxp == 0) {
xp = 0;
} else if(sxp < 1.0) {
xp = (int)((sxp*xp) + Math.round(Math.random()+0.75));
}
while(xp > 0) {
int k = EntityXPOrb.getXPSplit(xp);
xp -= k;
player.world.spawnEntity(new EntityXPOrb(player.world, player.posX, player.posY+0.5, player.posZ+0.5, k));
}
}
removeCount = 0;
net.minecraftforge.fml.common.FMLCommonHandler.instance().firePlayerSmeltedEvent(player, stack);
}
}
//--------------------------------------------------------------------------------------------------------------------
// container
//--------------------------------------------------------------------------------------------------------------------
public static class BContainer extends Container
{
private static final int PLAYER_INV_START_SLOTNO = 11;
private final World world;
private final BlockPos pos;
private final EntityPlayer player;
private final BTileEntity te;
private int proc_time_elapsed_;
private int burntime_left_;
private int fuel_burntime_;
private int proc_time_needed_;
public BContainer(InventoryPlayer playerInventory, World world, BlockPos pos, BTileEntity te)
{
this.player = playerInventory.player;
this.world = world;
this.pos = pos;
this.te = te;
addSlotToContainer(new Slot(te, 0, 59, 17)); // smelting input
addSlotToContainer(new SlotFurnaceFuel(te, 1, 59, 53)); // fuel
addSlotToContainer(new BSlotResult(playerInventory.player, te, 2, 101, 35)); // smelting result
addSlotToContainer(new BSlotInpFifo(te, 3, 34, 17)); // input fifo 0
addSlotToContainer(new BSlotInpFifo(te, 4, 16, 17)); // input fifo 1
addSlotToContainer(new BSlotFuelFifo(te, 5, 34, 53)); // fuel fifo 0
addSlotToContainer(new BSlotFuelFifo(te, 6, 16, 53)); // fuel fifo 1
addSlotToContainer(new BSlotOutFifo(playerInventory.player, te, 7, 126, 35)); // out fifo 0
addSlotToContainer(new BSlotOutFifo(playerInventory.player, te, 8, 144, 35)); // out fifo 1
addSlotToContainer(new Slot(te, 9, 126, 61)); // aux slot 1
addSlotToContainer(new Slot(te, 10, 144, 61)); // aux slot 2
for(int x=0; x<9; ++x) {
addSlotToContainer(new Slot(playerInventory, x, 8+x*18, 144)); // player slots: 0..8
}
for(int y=0; y<3; ++y) {
for(int x=0; x<9; ++x) {
addSlotToContainer(new Slot(playerInventory, x+y*9+9, 8+x*18, 86+y*18)); // player slots: 9..35
}
}
}
@Override
public void addListener(IContainerListener listener)
{ super.addListener(listener); listener.sendAllWindowProperties(this, te); }
@Override
public void detectAndSendChanges()
{
super.detectAndSendChanges();
for(int i=0; i<listeners.size(); ++i) {
IContainerListener lis = listeners.get(i);
if(proc_time_elapsed_ != te.getField(2)) lis.sendWindowProperty(this, 2, te.getField(2));
if(burntime_left_ != te.getField(0)) lis.sendWindowProperty(this, 0, te.getField(0));
if(fuel_burntime_ != te.getField(1)) lis.sendWindowProperty(this, 1, te.getField(1));
if(proc_time_needed_ != te.getField(3)) lis.sendWindowProperty(this, 3, te.getField(3));
}
proc_time_elapsed_ = te.getField(2);
burntime_left_ = te.getField(0);
fuel_burntime_ = te.getField(1);
proc_time_needed_ = te.getField(3);
}
@Override
@SideOnly(Side.CLIENT)
public void updateProgressBar(int id, int data)
{ te.setField(id, data); }
@Override
public boolean canInteractWith(EntityPlayer player)
{ return (world.getBlockState(pos).getBlock() instanceof BlockDecorFurnace) && (player.getDistanceSq(pos) <= 64); }
@Override
public ItemStack transferStackInSlot(EntityPlayer player, int index)
{
Slot slot = inventorySlots.get(index);
if((slot==null) || (!slot.getHasStack())) return ItemStack.EMPTY;
ItemStack slot_stack = slot.getStack();
ItemStack transferred = slot_stack.copy();
if((index==2) || (index==7) || (index==8)) {
// Output slots
if(!mergeItemStack(slot_stack, PLAYER_INV_START_SLOTNO, PLAYER_INV_START_SLOTNO+36, true)) return ItemStack.EMPTY;
slot.onSlotChange(slot_stack, transferred);
} else if((index==0) || (index==3) || (index==4)) {
// Input slots
if(!mergeItemStack(slot_stack, PLAYER_INV_START_SLOTNO, PLAYER_INV_START_SLOTNO+36, false)) return ItemStack.EMPTY;
} else if((index==1) || (index==5) || (index==6)) {
// Fuel slots
if(!mergeItemStack(slot_stack, PLAYER_INV_START_SLOTNO, PLAYER_INV_START_SLOTNO+36, false)) return ItemStack.EMPTY;
} else if((index==9) || (index==10)) {
if(!mergeItemStack(slot_stack, PLAYER_INV_START_SLOTNO, PLAYER_INV_START_SLOTNO+36, false)) return ItemStack.EMPTY;
} else if((index >= PLAYER_INV_START_SLOTNO) && (index <= PLAYER_INV_START_SLOTNO+36)) {
// Player inventory
if(!BRecipes.instance().getSmeltingResult(slot_stack).isEmpty()) {
if(
(!mergeItemStack(slot_stack, 0, 1, false)) && // smelting input
(!mergeItemStack(slot_stack, 3, 4, false)) && // fifo0
(!mergeItemStack(slot_stack, 4, 5, false)) // fifo1
) return ItemStack.EMPTY;
} else if(TileEntityFurnace.isItemFuel(slot_stack)) {
if(
(!mergeItemStack(slot_stack, 1, 2, false)) && // fuel input
(!mergeItemStack(slot_stack, 5, 6, false)) && // fuel fifo0
(!mergeItemStack(slot_stack, 6, 7, false)) // fuel fifo1
) return ItemStack.EMPTY;
} else if((index >= PLAYER_INV_START_SLOTNO) && (index < PLAYER_INV_START_SLOTNO+27)) {
// player inventory --> player hotbar
if(!mergeItemStack(slot_stack, PLAYER_INV_START_SLOTNO+27, PLAYER_INV_START_SLOTNO+36, false)) return ItemStack.EMPTY;
} else if((index >= PLAYER_INV_START_SLOTNO+27) && (index < PLAYER_INV_START_SLOTNO+36) && (!mergeItemStack(slot_stack, PLAYER_INV_START_SLOTNO, PLAYER_INV_START_SLOTNO+27, false))) {
// player hotbar --> player inventory
return ItemStack.EMPTY;
}
} else {
// invalid slot
return ItemStack.EMPTY;
}
if(slot_stack.isEmpty()) {
slot.putStack(ItemStack.EMPTY);
} else {
slot.onSlotChanged();
}
if(slot_stack.getCount() == transferred.getCount()) return ItemStack.EMPTY;
slot.onTake(player, slot_stack);
return transferred;
}
}
//--------------------------------------------------------------------------------------------------------------------
// Tile entity
//--------------------------------------------------------------------------------------------------------------------
public static class BTileEntity extends TileEntity implements ITickable, ISidedInventory, IEnergyStorage
{
public static final int NUM_OF_SLOTS = 11;
public static final int SMELTING_INPUT_SLOT_NO = 0;
public static final int SMELTING_FUEL_SLOT_NO = 1;
public static final int SMELTING_OUTPUT_SLOT_NO = 2;
public static final int FIFO_INPUT_0_SLOT_NO = 3;
public static final int FIFO_INPUT_1_SLOT_NO = 4;
public static final int FIFO_FUEL_0_SLOT_NO = 5;
public static final int FIFO_FUEL_1_SLOT_NO = 6;
public static final int FIFO_OUTPUT_0_SLOT_NO = 7;
public static final int FIFO_OUTPUT_1_SLOT_NO = 8;
public static final int AUX_0_SLOT_NO = 9;
public static final int AUX_1_SLOT_NO =10;
private int tick_timer_;
private int fifo_timer_;
private int burntime_left_;
private int fuel_burntime_;
private int proc_time_elapsed_;
private int proc_time_needed_;
private int boost_energy_; // small, not saved in nbt.
private boolean heater_inserted_ = false;
protected ItemStack current_smelting_input_stack_ = ItemStack.EMPTY;
protected NonNullList<ItemStack> stacks_;
public BTileEntity()
{ reset(); }
protected void reset()
{
stacks_ = NonNullList.<ItemStack>withSize(NUM_OF_SLOTS, ItemStack.EMPTY);
current_smelting_input_stack_ = ItemStack.EMPTY;
proc_time_elapsed_ = 0;
proc_time_needed_ = 0;
burntime_left_ = 0;
fuel_burntime_ = -1;
fifo_timer_ = 0;
tick_timer_ = 0;
}
public void readnbt(NBTTagCompound compound)
{
reset();
ItemStackHelper.loadAllItems(compound, this.stacks_);
while(this.stacks_.size() < NUM_OF_SLOTS) this.stacks_.add(ItemStack.EMPTY);
burntime_left_ = compound.getInteger("BurnTime");
proc_time_needed_ = MathHelper.clamp(compound.getInteger("CookTimeTotal"), 10, 65535);
proc_time_elapsed_ = MathHelper.clamp(compound.getInteger("CookTime"), 0, proc_time_needed_);
fuel_burntime_ = compound.getInteger("FuelBurnTime");
}
protected void writenbt(NBTTagCompound compound)
{
compound.setInteger("BurnTime", MathHelper.clamp(burntime_left_,0 , MAX_BURNTIME));
compound.setInteger("CookTime", MathHelper.clamp(proc_time_elapsed_, 0, MAX_BURNTIME));
compound.setInteger("CookTimeTotal", MathHelper.clamp(proc_time_needed_, 10, MAX_BURNTIME));
compound.setInteger("FuelBurnTime", MathHelper.clamp(fuel_burntime_, 0, MAX_BURNTIME));
ItemStackHelper.saveAllItems(compound, stacks_);
}
// TileEntity ------------------------------------------------------------------------------
@Override
public boolean shouldRefresh(World world, BlockPos pos, IBlockState os, IBlockState ns)
{ return (os.getBlock() != ns.getBlock()) || (!(ns.getBlock() instanceof BlockDecorFurnace)); }
@Override
public void readFromNBT(NBTTagCompound compound)
{ super.readFromNBT(compound); readnbt(compound); }
@Override
public NBTTagCompound writeToNBT(NBTTagCompound compound)
{ super.writeToNBT(compound); writenbt(compound); return compound; }
// IWorldNamable ---------------------------------------------------------------------------
@Override
public String getName()
{ final Block block=getBlockType(); return (block!=null) ? (block.getTranslationKey() + ".name") : (""); }
@Override
public boolean hasCustomName()
{ return false; }
@Override
public ITextComponent getDisplayName()
{ return new TextComponentTranslation(getName(), new Object[0]); }
// IInventory ------------------------------------------------------------------------------
@Override
public int getSizeInventory()
{ return stacks_.size(); }
@Override
public boolean isEmpty()
{ for(ItemStack stack: stacks_) { if(!stack.isEmpty()) return false; } return true; }
@Override
public ItemStack getStackInSlot(int index)
{ return (index < getSizeInventory()) ? stacks_.get(index) : ItemStack.EMPTY; }
@Override
public ItemStack decrStackSize(int index, int count)
{ return ItemStackHelper.getAndSplit(stacks_, index, count); }
@Override
public ItemStack removeStackFromSlot(int index)
{ return ItemStackHelper.getAndRemove(stacks_, index); }
@Override
public void setInventorySlotContents(int index, ItemStack stack)
{
ItemStack slot_stack = stacks_.get(index);
boolean already_in_slot = (!stack.isEmpty()) && (stack.isItemEqual(slot_stack)) && (ItemStack.areItemStackTagsEqual(stack, slot_stack));
stacks_.set(index, stack);
if(stack.getCount() > getInventoryStackLimit()) stack.setCount(getInventoryStackLimit());
if((index == SMELTING_INPUT_SLOT_NO) && (!already_in_slot)) {
proc_time_needed_ = getCookTime(stack);
proc_time_elapsed_ = 0;
markDirty();
}
}
@Override
public int getInventoryStackLimit()
{ return 64; }
@Override
public void markDirty()
{ super.markDirty(); }
@Override
public boolean isUsableByPlayer(EntityPlayer player)
{ return ((world.getTileEntity(pos) == this) && (player.getDistanceSq(pos.getX()+0.5d, pos.getY()+0.5d, pos.getZ()+0.5d) <= 64.0d)); }
@Override
public void openInventory(EntityPlayer player)
{}
@Override
public void closeInventory(EntityPlayer player)
{ markDirty(); }
@Override
public boolean isItemValidForSlot(int index, ItemStack stack)
{
switch(index) {
case SMELTING_OUTPUT_SLOT_NO:
case FIFO_OUTPUT_0_SLOT_NO:
case FIFO_OUTPUT_1_SLOT_NO:
return false;
case SMELTING_INPUT_SLOT_NO:
case FIFO_INPUT_0_SLOT_NO:
case FIFO_INPUT_1_SLOT_NO:
return true;
case AUX_0_SLOT_NO:
case AUX_1_SLOT_NO:
return true;
default: {
ItemStack slot_stack = stacks_.get(FIFO_FUEL_1_SLOT_NO);
return isItemFuel(stack) || SlotFurnaceFuel.isBucket(stack) && (slot_stack.getItem() != Items.BUCKET);
}
}
}
@Override
public int getField(int id)
{
switch (id) {
case 0: return burntime_left_;
case 1: return fuel_burntime_;
case 2: return proc_time_elapsed_;
case 3: return proc_time_needed_;
default: return 0;
}
}
@Override
public void setField(int id, int value)
{
switch(id) {
case 0: burntime_left_ = value; break;
case 1: fuel_burntime_ = value; break;
case 2: proc_time_elapsed_ = value; break;
case 3: proc_time_needed_ = value; break;
}
}
@Override
public int getFieldCount()
{ return 4; }
@Override
public void clear()
{ stacks_.clear(); }
public boolean isBurning()
{ return burntime_left_ > 0; }
@SideOnly(Side.CLIENT)
public static boolean isBurning(IInventory inventory)
{ return inventory.getField(0) > 0; }
public int getCookTime(ItemStack stack)
{ return proc_speed_interval_ < 10 ? 10 : proc_speed_interval_; }
private boolean transferItems(final int index_from, final int index_to, int count)
{
ItemStack from = stacks_.get(index_from);
if(from.isEmpty()) return false;
ItemStack to = stacks_.get(index_to);
if(from.getCount() < count) count = from.getCount();
if(count <= 0) return false;
boolean changed = true;
if(to.isEmpty()) {
stacks_.set(index_to, from.splitStack(count));
} else if(to.getCount() >= to.getMaxStackSize()) {
changed = false;
} else if((!from.isItemEqual(to)) || (!ItemStack.areItemStackTagsEqual(from, to))) {
changed = false;
} else {
if((to.getCount()+count) >= to.getMaxStackSize()) {
from.shrink(to.getMaxStackSize()-to.getCount());
to.setCount(to.getMaxStackSize());
} else {
from.shrink(count);
to.grow(count);
}
}
if(from.isEmpty() && from!=ItemStack.EMPTY) {
stacks_.set(index_from, ItemStack.EMPTY);
changed = true;
}
return changed;
}
protected boolean canSmelt()
{
final ItemStack in_stack = stacks_.get(SMELTING_INPUT_SLOT_NO);
if(in_stack.isEmpty()) return false;
final ItemStack recipe_result_items = BRecipes.instance().getSmeltingResult(in_stack);
if(recipe_result_items.isEmpty()) return false;
final ItemStack result_stack = stacks_.get(SMELTING_OUTPUT_SLOT_NO);
if(result_stack.isEmpty()) return true;
if(!result_stack.isItemEqual(recipe_result_items)) return false;
if(result_stack.getCount() + recipe_result_items.getCount() <= getInventoryStackLimit() && result_stack.getCount() + recipe_result_items.getCount() <= result_stack.getMaxStackSize()) return true;
return result_stack.getCount() + recipe_result_items.getCount() <= recipe_result_items.getMaxStackSize();
}
public void smeltItem()
{
if(!canSmelt()) return;
final ItemStack smelting_input_stack = stacks_.get(SMELTING_INPUT_SLOT_NO);
final ItemStack recipe_result_items = BRecipes.instance().getSmeltingResult(smelting_input_stack);
final ItemStack smelting_output_stack = stacks_.get(SMELTING_OUTPUT_SLOT_NO);
if(smelting_output_stack.isEmpty()) {
stacks_.set(SMELTING_OUTPUT_SLOT_NO, recipe_result_items.copy());
} else if(smelting_output_stack.getItem() == recipe_result_items.getItem()) {
smelting_output_stack.grow(recipe_result_items.getCount());
}
smelting_input_stack.shrink(1);
}
public static int getItemBurnTime(ItemStack stack)
{ return TileEntityFurnace.getItemBurnTime(stack); }
public static boolean isItemFuel(ItemStack stack)
{ return TileEntityFurnace.isItemFuel(stack); }
// ISidedInventory ----------------------------------------------------------------------------
private static final int[] SLOTS_TOP = new int[] {FIFO_INPUT_1_SLOT_NO};
private static final int[] SLOTS_BOTTOM = new int[] {FIFO_OUTPUT_1_SLOT_NO};
private static final int[] SLOTS_SIDES = new int[] {FIFO_FUEL_1_SLOT_NO};
private final IItemHandler sided_itemhandler_top_ = new SidedInvWrapper(this, EnumFacing.UP);
private final IItemHandler sided_itemhandler_down_ = new SidedInvWrapper(this, EnumFacing.DOWN);
private final IItemHandler sided_itemhandler_sides_ = new SidedInvWrapper(this, EnumFacing.WEST);
@Override
public int[] getSlotsForFace(EnumFacing side)
{
if(side == EnumFacing.DOWN) return SLOTS_BOTTOM;
if(side == EnumFacing.UP) return SLOTS_TOP;
return SLOTS_SIDES;
}
@Override
public boolean canInsertItem(int index, ItemStack itemStackIn, EnumFacing direction)
{ return isItemValidForSlot(index, itemStackIn); }
@Override
public boolean canExtractItem(int index, ItemStack stack, EnumFacing direction)
{
if((direction!=EnumFacing.DOWN) || ((index!=SMELTING_FUEL_SLOT_NO) && (index!=FIFO_FUEL_0_SLOT_NO) && (index!=FIFO_FUEL_1_SLOT_NO) )) return true;
return (stack.getItem()==Items.BUCKET);
}
// IEnergyStorage ----------------------------------------------------------------------------
@Override
public boolean canExtract()
{ return false; }
@Override
public boolean canReceive()
{ return true; }
@Override
public int getMaxEnergyStored()
{ return boost_energy_consumption; }
@Override
public int getEnergyStored()
{ return boost_energy_; }
@Override
public int extractEnergy(int maxExtract, boolean simulate)
{ return 0; }
@Override
public int receiveEnergy(int maxReceive, boolean simulate)
{ // only speedup support, no buffering, not in nbt -> no markdirty
if((boost_energy_ >= boost_energy_consumption) || (maxReceive < boost_energy_consumption)) return 0;
if(!simulate) boost_energy_ = boost_energy_consumption;
return boost_energy_consumption;
}
// Capability export ----------------------------------------------------------------------------
@Override
public boolean hasCapability(Capability<?> cap, EnumFacing facing)
{ return ((cap==CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) || (cap==CapabilityEnergy.ENERGY)) || super.hasCapability(cap, facing); }
@Override
@SuppressWarnings("unchecked")
@Nullable
public <T> T getCapability(Capability<T> capability, @Nullable EnumFacing facing)
{
if((facing != null) && (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)) {
if(facing == EnumFacing.DOWN) return (T) sided_itemhandler_down_;
if(facing == EnumFacing.UP) return (T) sided_itemhandler_top_;
return (T) sided_itemhandler_sides_;
} else if(capability == CapabilityEnergy.ENERGY) {
return (T)this;
} else {
return super.getCapability(capability, facing);
}
}
// ITickable ------------------------------------------------------------------------------------
@Override
public void update()
{
if(--tick_timer_ > 0) return;
tick_timer_ = TICK_INTERVAL;
if(!((world.getBlockState(getPos()).getBlock()) instanceof BlockDecorFurnace)) return;
final boolean was_burning = isBurning();
if(was_burning) burntime_left_ -= TICK_INTERVAL;
if(fuel_burntime_ < 0) fuel_burntime_ = getItemBurnTime(stacks_.get(SMELTING_FUEL_SLOT_NO));
if(burntime_left_ < 0) burntime_left_ = 0;
if(world.isRemote) return;
boolean dirty = false;
if(--fifo_timer_ <= 0) {
fifo_timer_ = FIFO_INTERVAL/TICK_INTERVAL;
// note, intentionally not using bitwise OR piping.
if(transferItems(FIFO_OUTPUT_0_SLOT_NO, FIFO_OUTPUT_1_SLOT_NO, 1)) dirty = true;
if(transferItems(SMELTING_OUTPUT_SLOT_NO, FIFO_OUTPUT_0_SLOT_NO, 1)) dirty = true;
if(transferItems(FIFO_FUEL_0_SLOT_NO, SMELTING_FUEL_SLOT_NO, 1)) dirty = true;
if(transferItems(FIFO_FUEL_1_SLOT_NO, FIFO_FUEL_0_SLOT_NO, 1)) dirty = true;
if(transferItems(FIFO_INPUT_0_SLOT_NO, SMELTING_INPUT_SLOT_NO, 1)) dirty = true;
if(transferItems(FIFO_INPUT_1_SLOT_NO, FIFO_INPUT_0_SLOT_NO, 1)) dirty = true;
heater_inserted_ = (ExtItems.IE_EXTERNAL_HEATER==null) // without IE always allow electrical boost
|| (stacks_.get(AUX_0_SLOT_NO).getItem()==ExtItems.IE_EXTERNAL_HEATER)
|| (stacks_.get(AUX_1_SLOT_NO).getItem()==ExtItems.IE_EXTERNAL_HEATER);
}
final ItemStack fuel = stacks_.get(SMELTING_FUEL_SLOT_NO);
final ItemStack last_inp_stack = current_smelting_input_stack_;
current_smelting_input_stack_ = stacks_.get(SMELTING_INPUT_SLOT_NO);
if(isBurning() || (!fuel.isEmpty()) && (!current_smelting_input_stack_.isEmpty())) {
if(!current_smelting_input_stack_.isItemEqual(last_inp_stack)) {
proc_time_elapsed_ = 0;
proc_time_needed_ = getCookTime(current_smelting_input_stack_);
}
final boolean can_smelt = canSmelt();
if(can_smelt && (burntime_left_ <= 0)) { // Refuel
burntime_left_ = (int)MathHelper.clamp((proc_fuel_efficiency_ * getItemBurnTime(fuel)), 0, MAX_BURNTIME);
fuel_burntime_ = (burntime_left_ * proc_speed_interval_) / VANILLA_FURNACE_SPEED_INTERVAL;
if(isBurning()) {
dirty = true;
if(!fuel.isEmpty()) {
Item fuel_item = fuel.getItem();
fuel.shrink(1);
if(fuel.isEmpty()) stacks_.set(SMELTING_FUEL_SLOT_NO, fuel_item.getContainerItem(fuel));
}
}
}
if((burntime_left_ > 0) && can_smelt) { // Smelting process
proc_time_elapsed_ += TICK_INTERVAL;
if(heater_inserted_ && (boost_energy_ >= boost_energy_consumption)) { boost_energy_ = 0; proc_time_elapsed_ += TICK_INTERVAL; }
if(proc_time_elapsed_ >= proc_time_needed_) {
proc_time_elapsed_ = 0;
proc_time_needed_ = getCookTime(current_smelting_input_stack_);
smeltItem();
dirty = true;
}
} else {
proc_time_elapsed_ = MathHelper.clamp(proc_time_elapsed_-2, 0, proc_time_needed_);
}
} else if(!isBurning() && (proc_time_elapsed_ > 0)) {
proc_time_elapsed_ = MathHelper.clamp(proc_time_elapsed_-2, 0, proc_time_needed_);
}
if(was_burning != isBurning()) {
dirty = true;
world.setBlockState(pos, world.getBlockState(pos).withProperty(LIT, isBurning()));
}
if(dirty) markDirty();
}
}
//--------------------------------------------------------------------------------------------------------------------
// Furnace recipe overrides
//--------------------------------------------------------------------------------------------------------------------
// Based on net.minecraft.item.crafting.FurnaceRecipes, copy as
// needed methods are private.
public static class BRecipes
{
private static final BRecipes RECIPPE_OVERRIDES = new BRecipes();
private final Map<ItemStack, ItemStack> recipes_ = Maps.<ItemStack, ItemStack>newHashMap();
private final Map<ItemStack, Float> experiences_ = Maps.<ItemStack, Float>newHashMap();
public static BRecipes instance()
{ return RECIPPE_OVERRIDES; }
private BRecipes()
{}
public Map<ItemStack, ItemStack> getRecipes()
{ return recipes_; }
public void reset()
{ recipes_.clear(); experiences_.clear(); }
public ItemStack getSmeltingResult(final ItemStack stack)
{
ItemStack res = override_result(stack);
if(res.isEmpty()) res = FurnaceRecipes.instance().getSmeltingResult(stack);
return res;
}
public float getSmeltingExperience(ItemStack stack)
{
float ret = stack.getItem().getSmeltingExperience(stack);
if(ret != -1) return ret;
for(Map.Entry<ItemStack, Float> e : experiences_.entrySet()) {
if(compare(stack, e.getKey())) return e.getValue();
}
return FurnaceRecipes.instance().getSmeltingExperience(stack);
}
public void add(Block input, ItemStack stack, float experience)
{ add(Item.getItemFromBlock(input), stack, experience); }
public void add(Item input, ItemStack stack, float experience)
{ add(new ItemStack(input, 1, 32767), stack, experience); }
public void add(ItemStack input, ItemStack stack, float xp)
{
// Forced override setting
if(input==ItemStack.EMPTY) return;
if(recipes_.containsKey(input)) recipes_.remove(input);
if(experiences_.containsKey(input)) experiences_.remove(input);
if((stack==null) || (stack==ItemStack.EMPTY)) return;
recipes_.put(input, stack);
experiences_.put(stack, xp);
}
public ItemStack override_result(ItemStack stack)
{
for(Map.Entry<ItemStack, ItemStack> e:recipes_.entrySet()) {
if(compare(stack, e.getKey())) return e.getValue();
}
return ItemStack.EMPTY;
}
private boolean compare(final ItemStack stack1, final ItemStack stack2)
{ return (stack2.getItem() == stack1.getItem()) && ((stack2.getMetadata() == 32767) || (stack2.getMetadata() == stack1.getMetadata())); }
}
}

View file

@ -1,810 +0,0 @@
/*
* @file BlockDecorFurnaceElectrical.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* ED small electrical pass-through furnace.
*/
package wile.engineersdecor.blocks;
import wile.engineersdecor.ModContent;
import wile.engineersdecor.ModEngineersDecor;
import wile.engineersdecor.detail.Networking;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.world.World;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.init.Items;
import net.minecraft.item.*;
import net.minecraft.inventory.*;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.*;
import net.minecraft.stats.StatList;
import net.minecraft.init.Blocks;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.energy.CapabilityEnergy;
import net.minecraftforge.energy.IEnergyStorage;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.IOException;
import java.util.Random;
public class BlockDecorFurnaceElectrical extends BlockDecorFurnace
{
//--------------------------------------------------------------------------------------------------------------------
// Config
//--------------------------------------------------------------------------------------------------------------------
private static int energy_consumption_ = BTileEntity.DEFAULT_SCALED_ENERGY_CONSUMPTION;
private static int transfer_energy_consumption_ = BTileEntity.DEFAULT_SCALED_ENERGY_CONSUMPTION/8;
private static int proc_speed_percent_ = BTileEntity.DEFAULT_SPEED_PERCENT;
private static double speed_setting_factor_[] = {0.0, 1.0, 1.5, 2.0};
private static boolean with_automatic_inventory_pulling_ = false;
public static void on_config(int speed_percent, int standard_energy_per_tick, boolean with_automatic_inventory_pulling)
{
proc_speed_percent_ = MathHelper.clamp(speed_percent, 10, 500);
energy_consumption_ = MathHelper.clamp(standard_energy_per_tick, 10, 256) * BTileEntity.HEAT_INCREMENT * proc_speed_percent_ / 100;
transfer_energy_consumption_ = MathHelper.clamp(energy_consumption_/8, 8, BTileEntity.HEAT_INCREMENT);
with_automatic_inventory_pulling_ = with_automatic_inventory_pulling;
ModEngineersDecor.logger.info("Config electrical furnace speed:" + proc_speed_percent_ + ", power consumption:" + energy_consumption_);
}
//--------------------------------------------------------------------------------------------------------------------
// Block
//--------------------------------------------------------------------------------------------------------------------
public BlockDecorFurnaceElectrical(@Nonnull String registryName, long config, @Nullable Material material, float hardness, float resistance, @Nullable SoundType sound, @Nonnull AxisAlignedBB unrotatedAABB)
{
super(registryName, config, material, hardness, resistance, sound, unrotatedAABB);
}
@Override
@Nullable
public TileEntity createTileEntity(World world, IBlockState state)
{ return new BlockDecorFurnaceElectrical.BTileEntity(); }
@Override
public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
{
if(world.isRemote) return true;
player.openGui(ModEngineersDecor.instance, ModEngineersDecor.GuiHandler.GUIID_ELECTRICAL_LAB_FURNACE, world, pos.getX(), pos.getY(), pos.getZ());
player.addStat(StatList.FURNACE_INTERACTION);
return true;
}
@Override
public void onBlockPlacedBy(World world, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack)
{
world.setBlockState(pos, state.withProperty(LIT, false));
if(world.isRemote) return;
if((!stack.hasTagCompound()) || (!stack.getTagCompound().hasKey("inventory"))) return;
NBTTagCompound inventory_nbt = stack.getTagCompound().getCompoundTag("inventory");
if(inventory_nbt.isEmpty()) return;
final TileEntity te = world.getTileEntity(pos);
if(!(te instanceof BlockDecorFurnaceElectrical.BTileEntity)) return;
((BlockDecorFurnaceElectrical.BTileEntity)te).readnbt(inventory_nbt);
((BlockDecorFurnaceElectrical.BTileEntity)te).markDirty();
}
@Override
@SideOnly(Side.CLIENT)
public void randomDisplayTick(IBlockState state, World world, BlockPos pos, Random rnd)
{}
//--------------------------------------------------------------------------------------------------------------------
// ModEngineersDecor.GuiHandler connectors
//--------------------------------------------------------------------------------------------------------------------
public static Object getServerGuiElement(final EntityPlayer player, final World world, final BlockPos pos, final TileEntity te)
{ return (te instanceof BTileEntity) ? (new BContainer(player.inventory, world, pos, (BTileEntity)te)) : null; }
public static Object getClientGuiElement(final EntityPlayer player, final World world, final BlockPos pos, final TileEntity te)
{ return (te instanceof BTileEntity) ? (new BGui(player.inventory, world, pos, (BTileEntity)te)) : null; }
//--------------------------------------------------------------------------------------------------------------------
// GUI
//--------------------------------------------------------------------------------------------------------------------
@SideOnly(Side.CLIENT)
private static class BGui extends GuiContainer
{
private final BTileEntity te;
public BGui(InventoryPlayer playerInventory, World world, BlockPos pos, BTileEntity te)
{ super(new BContainer(playerInventory, world, pos, te)); this.te = te; }
@Override
public void initGui()
{ super.initGui(); }
@Override
public void drawScreen(int mouseX, int mouseY, float partialTicks)
{
drawDefaultBackground();
super.drawScreen(mouseX, mouseY, partialTicks);
renderHoveredToolTip(mouseX, mouseY);
}
@Override
protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY)
{
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
mc.getTextureManager().bindTexture(new ResourceLocation(ModEngineersDecor.MODID, "textures/gui/small_electrical_furnace_gui.png"));
final int x0=(width-xSize)/2, y0=(height-ySize)/2, w=xSize, h=ySize;
drawTexturedModalRect(x0, y0, 0, 0, w, h);
if(BTileEntity.isBurning(te)) {
if(BlockDecorFurnace.BTileEntity.isBurning(te)) {
final int hi = 13;
final int k = heat_px(hi);
drawTexturedModalRect(x0+61, y0+53+hi-k, 177, hi-k, 13, k);
}
}
drawTexturedModalRect(x0+79, y0+30, 176, 15, 1+progress_px(17), 15);
int we = energy_px(32, 8);
if(we>0) drawTexturedModalRect(x0+88, y0+53, 185, 30, we, 13);
switch(te.getField(4)) {
case 0: drawTexturedModalRect(x0+144, y0+57, 180, 57, 6, 9); break;
case 1: drawTexturedModalRect(x0+142, y0+58, 190, 58, 9, 6); break;
case 2: drawTexturedModalRect(x0+144, y0+56, 200, 57, 6, 9); break;
case 3: drawTexturedModalRect(x0+143, y0+58, 210, 58, 9, 6); break;
default: break;
}
}
private int progress_px(int pixels)
{ final int tc=te.getField(2), T=te.getField(3); return ((T>0) && (tc>0)) ? (tc * pixels / T) : (0); }
private int heat_px(int pixels)
{
int k = ((te.getField(0) * (pixels+1)) / (BlockDecorFurnaceElectrical.BTileEntity.HEAT_CAPACITY));
return (k < pixels) ? k : pixels;
}
private int energy_px(int maxwidth, int quantization)
{
int k = ((maxwidth * te.getField(1) * 9) / 8) / (te.getMaxEnergyStored()+1);
k = (k >= maxwidth-2) ? maxwidth : k;
if(quantization > 0) k = ((k+(quantization/2))/quantization) * quantization;
return k;
}
@Override
protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException
{
BContainer container = (BContainer)inventorySlots;
int mx = (int)(mouseX - getGuiLeft() + .5), my = (int)(mouseY - getGuiTop() + .5);
int speed = -1;
if((!isPointInRegion(136, 48, 28, 28, mouseX, mouseY))) {
super.mouseClicked(mouseX, mouseY, mouseButton);
} else if(isPointInRegion(144, 64, 6, 10, mouseX, mouseY)) {
speed = 0;
} else if(isPointInRegion(134, 58, 10, 6, mouseX, mouseY)) {
speed = 1;
} else if(isPointInRegion(144, 48, 6, 10, mouseX, mouseY)) {
speed = 2;
} else if(isPointInRegion(150, 58, 10, 6, mouseX, mouseY)) {
speed = 3;
}
if(speed >= 0) {
NBTTagCompound nbt = new NBTTagCompound();
nbt.setInteger("speed", speed);
Networking.PacketTileNotify.sendToServer(te, nbt);
}
}
}
//--------------------------------------------------------------------------------------------------------------------
// Container
//--------------------------------------------------------------------------------------------------------------------
public static class BContainer extends Container
{
private static final int PLAYER_INV_START_SLOTNO = 7;
private final World world;
private final BlockPos pos;
private final EntityPlayer player;
private final BTileEntity te;
private int burntime_left_, energy_stored_, proc_time_elapsed_, proc_time_needed_, speed_;
public BContainer(InventoryPlayer playerInventory, World world, BlockPos pos, BTileEntity te)
{
this.player = playerInventory.player;
this.world = world;
this.pos = pos;
this.te = te;
addSlotToContainer(new Slot(te, 0, 59, 28)); // smelting input
addSlotToContainer(new Slot(te, 1, 16, 52)); // aux
addSlotToContainer(new BSlotResult(playerInventory.player, te, 2, 101, 28)); // smelting result
addSlotToContainer(new BSlotInpFifo(te, 3, 34, 28)); // input fifo 0
addSlotToContainer(new BSlotInpFifo(te, 4, 16, 28)); // input fifo 1
addSlotToContainer(new BSlotOutFifo(playerInventory.player, te, 5, 126, 28)); // out fifo 0
addSlotToContainer(new BSlotOutFifo(playerInventory.player, te, 6, 144, 28)); // out fifo 1
for(int x=0; x<9; ++x) {
addSlotToContainer(new Slot(playerInventory, x, 8+x*18, 144)); // player slots: 0..8
}
for(int y=0; y<3; ++y) {
for(int x=0; x<9; ++x) {
addSlotToContainer(new Slot(playerInventory, x+y*9+9, 8+x*18, 86+y*18)); // player slots: 9..35
}
}
}
@Override
public void addListener(IContainerListener listener)
{ super.addListener(listener); listener.sendAllWindowProperties(this, te); }
@Override
public void detectAndSendChanges()
{
super.detectAndSendChanges();
for(int i=0; i<listeners.size(); ++i) {
IContainerListener lis = listeners.get(i);
if(burntime_left_ != te.getField(0)) lis.sendWindowProperty(this, 0, te.getField(0));
if(energy_stored_ != te.getField(1)) lis.sendWindowProperty(this, 1, te.getField(1));
if(proc_time_elapsed_ != te.getField(2)) lis.sendWindowProperty(this, 2, te.getField(2));
if(proc_time_needed_ != te.getField(3)) lis.sendWindowProperty(this, 3, te.getField(3));
if(speed_ != te.getField(4)) lis.sendWindowProperty(this, 4, te.getField(4));
}
burntime_left_ = te.getField(0);
energy_stored_ = te.getField(1);
proc_time_elapsed_ = te.getField(2);
proc_time_needed_ = te.getField(3);
speed_ = te.getField(4);
}
@Override
@SideOnly(Side.CLIENT)
public void updateProgressBar(int id, int data)
{ te.setField(id, data); }
@Override
public boolean canInteractWith(EntityPlayer player)
{ return (world.getBlockState(pos).getBlock() instanceof BlockDecorFurnaceElectrical) && (player.getDistanceSq(pos) <= 64); }
@Override
public ItemStack transferStackInSlot(EntityPlayer player, int index)
{
Slot slot = inventorySlots.get(index);
if((slot==null) || (!slot.getHasStack())) return ItemStack.EMPTY;
ItemStack slot_stack = slot.getStack();
ItemStack transferred = slot_stack.copy();
if((index==2) || (index==5) || (index==6)) {
// Output slots
if(!mergeItemStack(slot_stack, PLAYER_INV_START_SLOTNO, PLAYER_INV_START_SLOTNO+36, true)) return ItemStack.EMPTY;
slot.onSlotChange(slot_stack, transferred);
} else if((index==0) || (index==3) || (index==4)) {
// Input slots
if(!mergeItemStack(slot_stack, PLAYER_INV_START_SLOTNO, PLAYER_INV_START_SLOTNO+36, false)) return ItemStack.EMPTY;
} else if(index==1) {
// Bypass slot
if(!mergeItemStack(slot_stack, PLAYER_INV_START_SLOTNO, PLAYER_INV_START_SLOTNO+36, false)) return ItemStack.EMPTY;
} else if((index >= PLAYER_INV_START_SLOTNO) && (index <= PLAYER_INV_START_SLOTNO+36)) {
// Player inventory
if(!BRecipes.instance().getSmeltingResult(slot_stack).isEmpty()) {
if(
(!mergeItemStack(slot_stack, 0, 1, false)) && // smelting input
(!mergeItemStack(slot_stack, 3, 4, false)) && // fifo0
(!mergeItemStack(slot_stack, 4, 5, false)) // fifo1
) return ItemStack.EMPTY;
} else if((index >= PLAYER_INV_START_SLOTNO) && (index < PLAYER_INV_START_SLOTNO+27)) {
// player inventory --> player hotbar
if(!mergeItemStack(slot_stack, PLAYER_INV_START_SLOTNO+27, PLAYER_INV_START_SLOTNO+36, false)) return ItemStack.EMPTY;
} else if((index >= PLAYER_INV_START_SLOTNO+27) && (index < PLAYER_INV_START_SLOTNO+36) && (!mergeItemStack(slot_stack, PLAYER_INV_START_SLOTNO, PLAYER_INV_START_SLOTNO+27, false))) {
// player hotbar --> player inventory
return ItemStack.EMPTY;
}
} else {
// invalid slot
return ItemStack.EMPTY;
}
if(slot_stack.isEmpty()) {
slot.putStack(ItemStack.EMPTY);
} else {
slot.onSlotChanged();
}
if(slot_stack.getCount() == transferred.getCount()) return ItemStack.EMPTY;
slot.onTake(player, slot_stack);
return transferred;
}
}
//--------------------------------------------------------------------------------------------------------------------
// Tile entity
//--------------------------------------------------------------------------------------------------------------------
public static class BTileEntity extends BlockDecorFurnace.BTileEntity implements ITickable, ISidedInventory, IEnergyStorage, Networking.IPacketReceiver
{
public static final int TICK_INTERVAL = 4;
public static final int FIFO_INTERVAL = 20;
public static final int HEAT_CAPACITY = 200;
public static final int HEAT_INCREMENT = 20;
public static final int MAX_ENERGY_TRANSFER = 256;
public static final int MAX_ENERGY_BUFFER = 32000;
public static final int MAX_SPEED_SETTING = 3;
public static final int NUM_OF_SLOTS = 7;
public static final int SMELTING_INPUT_SLOT_NO = 0;
public static final int SMELTING_AUX_SLOT_NO = 1;
public static final int SMELTING_OUTPUT_SLOT_NO = 2;
public static final int FIFO_INPUT_0_SLOT_NO = 3;
public static final int FIFO_INPUT_1_SLOT_NO = 4;
public static final int FIFO_OUTPUT_0_SLOT_NO = 5;
public static final int FIFO_OUTPUT_1_SLOT_NO = 6;
public static final int DEFAULT_SPEED_PERCENT = 200;
public static final int DEFAULT_ENERGY_CONSUMPTION = 16 ;
public static final int DEFAULT_SCALED_ENERGY_CONSUMPTION = DEFAULT_ENERGY_CONSUMPTION * HEAT_INCREMENT * DEFAULT_SPEED_PERCENT/100;
// BTileEntity ------------------------------------------------------------------------------
private int burntime_left_;
private int proc_time_elapsed_;
private int proc_time_needed_;
private int energy_stored_;
private int speed_;
private int tick_timer_;
private int fifo_timer_;
private boolean enabled_ = false;
public BTileEntity()
{ super(); reset(); }
public void reset()
{
stacks_ = NonNullList.<ItemStack>withSize(NUM_OF_SLOTS, ItemStack.EMPTY);
burntime_left_ = 0;
proc_time_elapsed_ = 0;
proc_time_needed_ = 0;
fifo_timer_ = 0;
tick_timer_ = 0;
energy_stored_= 0;
speed_ = 1;
}
public void readnbt(NBTTagCompound compound)
{
reset();
ItemStackHelper.loadAllItems(compound, this.stacks_);
while(this.stacks_.size() < NUM_OF_SLOTS) this.stacks_.add(ItemStack.EMPTY);
burntime_left_ = compound.getInteger("BurnTime");
proc_time_elapsed_ = compound.getInteger("CookTime");
proc_time_needed_ = compound.getInteger("CookTimeTotal");
energy_stored_ = compound.getInteger("Energy");
speed_ = compound.getInteger("SpeedSetting");
speed_ = (speed_ < 0) ? (1) : ((speed_>MAX_SPEED_SETTING) ? MAX_SPEED_SETTING : speed_);
}
protected void writenbt(NBTTagCompound compound)
{
compound.setInteger("BurnTime", MathHelper.clamp(burntime_left_,0 , HEAT_CAPACITY));
compound.setInteger("CookTime", MathHelper.clamp(proc_time_elapsed_, 0, MAX_BURNTIME));
compound.setInteger("CookTimeTotal", MathHelper.clamp(proc_time_needed_, 0, MAX_BURNTIME));
compound.setInteger("Energy", MathHelper.clamp(energy_stored_,0 , MAX_ENERGY_BUFFER));
compound.setInteger("SpeedSetting", MathHelper.clamp(speed_, 0, MAX_SPEED_SETTING));
ItemStackHelper.saveAllItems(compound, stacks_);
}
// TileEntity ------------------------------------------------------------------------------
// IWorldNamable ---------------------------------------------------------------------------
// IInventory ------------------------------------------------------------------------------
@Override
public boolean isItemValidForSlot(int index, ItemStack stack)
{
switch(index) {
case SMELTING_INPUT_SLOT_NO:
case FIFO_INPUT_0_SLOT_NO:
case FIFO_INPUT_1_SLOT_NO:
return true;
default:
return false;
}
}
@Override
public int getField(int id)
{
switch (id) {
case 0: return burntime_left_;
case 1: return energy_stored_;
case 2: return proc_time_elapsed_;
case 3: return proc_time_needed_;
case 4: return speed_;
default: return 0;
}
}
@Override
public void setField(int id, int value)
{
switch(id) {
case 0: burntime_left_ = value; break;
case 1: energy_stored_ = value; break;
case 2: proc_time_elapsed_ = value; break;
case 3: proc_time_needed_ = value; break;
case 4: speed_ = value; break;
}
}
@Override
public int getFieldCount()
{ return 7; }
public boolean isBurning()
{ return (burntime_left_ > 0); }
private boolean transferItems(final int index_from, final int index_to, int count)
{
ItemStack from = stacks_.get(index_from);
if(from.isEmpty()) return false;
ItemStack to = stacks_.get(index_to);
if(from.getCount() < count) count = from.getCount();
if(count <= 0) return false;
boolean changed = true;
if(to.isEmpty()) {
stacks_.set(index_to, from.splitStack(count));
} else if(to.getCount() >= to.getMaxStackSize()) {
changed = false;
} else if((!from.isItemEqual(to)) || (!ItemStack.areItemStackTagsEqual(from, to))) {
changed = false;
} else {
if((to.getCount()+count) >= to.getMaxStackSize()) {
from.shrink(to.getMaxStackSize()-to.getCount());
to.setCount(to.getMaxStackSize());
} else {
from.shrink(count);
to.grow(count);
}
}
if(from.isEmpty() && from!=ItemStack.EMPTY) {
stacks_.set(index_from, ItemStack.EMPTY);
changed = true;
}
return changed;
}
@Override
public ItemStack getStackInSlot(int index)
{ return ((index < 0) || (index >= SIDED_INV_SLOTS.length)) ? ItemStack.EMPTY : stacks_.get(SIDED_INV_SLOTS[index]); }
// ISidedInventory ----------------------------------------------------------------------------
private static final int[] SIDED_INV_SLOTS = new int[] {
SMELTING_INPUT_SLOT_NO, SMELTING_AUX_SLOT_NO, SMELTING_OUTPUT_SLOT_NO,
FIFO_INPUT_0_SLOT_NO, FIFO_INPUT_1_SLOT_NO, FIFO_OUTPUT_0_SLOT_NO, FIFO_OUTPUT_1_SLOT_NO
};
@Override
public int[] getSlotsForFace(EnumFacing side)
{ return SIDED_INV_SLOTS; }
@Override
public boolean canInsertItem(int index, ItemStack itemStackIn, EnumFacing direction)
{ return isItemValidForSlot(index, itemStackIn); }
@Override
public boolean canExtractItem(int index, ItemStack stack, EnumFacing direction)
{ return ((index!=SMELTING_INPUT_SLOT_NO) && (index!=FIFO_INPUT_0_SLOT_NO) && (index!=FIFO_INPUT_1_SLOT_NO)) || (stack.getItem()==Items.BUCKET); }
// IEnergyStorage ----------------------------------------------------------------------------
@Override
public boolean canExtract()
{ return false; }
@Override
public boolean canReceive()
{ return true; }
@Override
public int getMaxEnergyStored()
{ return MAX_ENERGY_BUFFER; }
@Override
public int getEnergyStored()
{ return energy_stored_; }
@Override
public int extractEnergy(int maxExtract, boolean simulate)
{ return 0; }
@Override
public int receiveEnergy(int maxReceive, boolean simulate)
{
if(energy_stored_ >= MAX_ENERGY_BUFFER) return 0;
int n = Math.min(maxReceive, (MAX_ENERGY_BUFFER - energy_stored_));
if(n > MAX_ENERGY_TRANSFER) n = MAX_ENERGY_TRANSFER;
if(!simulate) {energy_stored_ += n; markDirty(); }
return n;
}
// IItemHandler --------------------------------------------------------------------------------
protected static class BItemHandler implements IItemHandler
{
private BTileEntity te;
BItemHandler(BTileEntity te)
{ this.te = te; }
@Override
public int getSlots()
{ return SIDED_INV_SLOTS.length; }
@Override
@Nonnull
public ItemStack getStackInSlot(int index)
{ return te.getStackInSlot(index); }
@Override
public int getSlotLimit(int index)
{ return te.getInventoryStackLimit(); }
@Override
public boolean isItemValid(int slot, @Nonnull ItemStack stack)
{ return true; }
@Override
@Nonnull
public ItemStack insertItem(int index, @Nonnull ItemStack stack, boolean simulate)
{
if(stack.isEmpty()) return ItemStack.EMPTY;
if((index < 0) || (index >= SIDED_INV_SLOTS.length)) return ItemStack.EMPTY;
int slotno = SIDED_INV_SLOTS[index];
ItemStack slotstack = getStackInSlot(slotno);
if(!slotstack.isEmpty()) {
if(slotstack.getCount() >= Math.min(slotstack.getMaxStackSize(), getSlotLimit(index))) return stack;
if(!ItemHandlerHelper.canItemStacksStack(stack, slotstack)) return stack;
if(!te.canInsertItem(slotno, stack, EnumFacing.UP) || (!te.isItemValidForSlot(slotno, stack))) return stack;
int n = Math.min(stack.getMaxStackSize(), getSlotLimit(index)) - slotstack.getCount();
if(stack.getCount() <= n) {
if(!simulate) {
ItemStack copy = stack.copy();
copy.grow(slotstack.getCount());
te.setInventorySlotContents(slotno, copy);
}
return ItemStack.EMPTY;
} else {
stack = stack.copy();
if(!simulate) {
ItemStack copy = stack.splitStack(n);
copy.grow(slotstack.getCount());
te.setInventorySlotContents(slotno, copy);
return stack;
} else {
stack.shrink(n);
return stack;
}
}
} else {
if(!te.canInsertItem(slotno, stack, EnumFacing.UP) || (!te.isItemValidForSlot(slotno, stack))) return stack;
int n = Math.min(stack.getMaxStackSize(), getSlotLimit(index));
if(n < stack.getCount()) {
stack = stack.copy();
if(!simulate) {
te.setInventorySlotContents(slotno, stack.splitStack(n));
return stack;
} else {
stack.shrink(n);
return stack;
}
} else {
if(!simulate) te.setInventorySlotContents(slotno, stack);
return ItemStack.EMPTY;
}
}
}
@Override
@Nonnull
public ItemStack extractItem(int index, int amount, boolean simulate) {
if(amount == 0) return ItemStack.EMPTY;
if((index < 0) || (index >= SIDED_INV_SLOTS.length)) return ItemStack.EMPTY;
int slotno = SIDED_INV_SLOTS[index];
ItemStack stackInSlot = getStackInSlot(slotno);
if(stackInSlot.isEmpty()) return ItemStack.EMPTY;
if(!te.canExtractItem(slotno, stackInSlot, EnumFacing.DOWN)) return ItemStack.EMPTY;
if(simulate) {
if(stackInSlot.getCount() < amount) return stackInSlot.copy();
ItemStack ostack = stackInSlot.copy();
ostack.setCount(amount);
return ostack;
} else {
ItemStack ostack = te.decrStackSize(slotno, Math.min(stackInSlot.getCount(), amount));
te.markDirty();
return ostack;
}
}
}
protected BItemHandler item_handler_ = new BItemHandler(this);
// Capability export ----------------------------------------------------------------------------
@Override
public boolean hasCapability(Capability<?> cap, EnumFacing facing)
{ return ((cap==CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) || (cap==CapabilityEnergy.ENERGY)) || super.hasCapability(cap, facing); }
@Override
@SuppressWarnings("unchecked")
@Nullable
public <T> T getCapability(Capability<T> capability, @Nullable EnumFacing facing)
{
if(capability == CapabilityEnergy.ENERGY) return ((T)this);
if(capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) return (T)item_handler_;
return super.getCapability(capability, facing);
}
// IPacketReceiver -------------------------------------------------------------------------------
@Override
public void onServerPacketReceived(NBTTagCompound nbt)
{}
@Override
public void onClientPacketReceived(EntityPlayer player, NBTTagCompound nbt)
{
if(nbt.hasKey("speed")) speed_ = MathHelper.clamp(nbt.getInteger("speed"), 0, MAX_SPEED_SETTING);
markDirty();
}
// ITickable ------------------------------------------------------------------------------------
private boolean is_accepted_hopper(final ItemStack stack)
{ return (stack.getItem() == Item.getItemFromBlock(Blocks.HOPPER)) || (stack.getItem() == Item.getItemFromBlock(ModContent.FACTORY_HOPPER)); }
private boolean adjacent_inventory_shift(boolean inp, boolean out)
{
boolean dirty = false;
if(energy_stored_ < transfer_energy_consumption_) return false;
final IBlockState state = world.getBlockState(pos);
if(!(state.getBlock() instanceof BlockDecorFurnaceElectrical)) return false;
final EnumFacing out_facing = state.getValue(FACING);
final EnumFacing inp_facing = state.getValue(FACING).getOpposite();
if(out && (!stacks_.get(FIFO_OUTPUT_1_SLOT_NO).isEmpty())) {
TileEntity te = world.getTileEntity(pos.offset(out_facing));
if((te!=null) && (te.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, inp_facing))) {
IItemHandler hnd = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, inp_facing);
ItemStack remaining = ItemHandlerHelper.insertItemStacked(hnd, stacks_.get(FIFO_OUTPUT_1_SLOT_NO).copy(), false);
stacks_.set(FIFO_OUTPUT_1_SLOT_NO, remaining);
energy_stored_ -= transfer_energy_consumption_;
dirty = true;
}
}
if(with_automatic_inventory_pulling_ || is_accepted_hopper(stacks_.get(SMELTING_AUX_SLOT_NO))) {
if(inp && (stacks_.get(FIFO_INPUT_1_SLOT_NO).isEmpty())) {
TileEntity te = world.getTileEntity(pos.offset(inp_facing));
if((te!=null) && (te.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, out_facing))) {
IItemHandler hnd = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, out_facing);
for(int i=0; i< hnd.getSlots(); ++i) {
ItemStack adj_stack = hnd.getStackInSlot(i);
if(!adj_stack.isEmpty()) {
ItemStack my_stack = adj_stack.copy();
if(my_stack.getCount() > getInventoryStackLimit()) my_stack.setCount(getInventoryStackLimit());
adj_stack.shrink(my_stack.getCount());
stacks_.set(FIFO_INPUT_1_SLOT_NO, my_stack);
energy_stored_ -= transfer_energy_consumption_;
dirty = true;
break;
}
}
}
}
}
return dirty;
}
// returns TE dirty
private boolean heat_up()
{
if(energy_stored_ < (energy_consumption())) return false;
if(burntime_left_ >= (HEAT_CAPACITY-HEAT_INCREMENT)) return false;
energy_stored_ -= energy_consumption();
burntime_left_ += HEAT_INCREMENT;
this.markDirty();
return true;
}
int energy_consumption()
{
switch(speed_) {
case 1: return energy_consumption_;
case 2: return energy_consumption_ * 2;
case 3: return energy_consumption_ * 4;
default: return 0;
}
}
private void sync_blockstate()
{
final IBlockState state = world.getBlockState(pos);
if((state.getBlock() instanceof BlockDecorFurnaceElectrical) && (state.getValue(LIT) != isBurning())) {
world.setBlockState(pos, state.withProperty(LIT, isBurning()), 2);
}
}
@Override
public void update()
{
if(--tick_timer_ > 0) return;
tick_timer_ = TICK_INTERVAL;
if(!(world.getBlockState(pos).getBlock() instanceof BlockDecorFurnaceElectrical)) return;
final boolean was_burning = isBurning();
if(was_burning) burntime_left_ -= TICK_INTERVAL;
if(burntime_left_ < 0) burntime_left_ = 0;
if(world.isRemote) return;
boolean update_blockstate = (was_burning != isBurning());
boolean dirty = update_blockstate;
boolean shift_in = false;
boolean shift_out = false;
if(--fifo_timer_ <= 0) {
fifo_timer_ = FIFO_INTERVAL/TICK_INTERVAL;
if(transferItems(FIFO_OUTPUT_0_SLOT_NO, FIFO_OUTPUT_1_SLOT_NO, 64)) { dirty = true; } else { shift_out = true; }
if(transferItems(SMELTING_OUTPUT_SLOT_NO, FIFO_OUTPUT_0_SLOT_NO, 64)) dirty = true;
if(transferItems(FIFO_INPUT_0_SLOT_NO, SMELTING_INPUT_SLOT_NO, 64)) dirty = true;
if(transferItems(FIFO_INPUT_1_SLOT_NO, FIFO_INPUT_0_SLOT_NO, 64)) { dirty = true; } else { shift_in = true; }
}
if(energy_stored_ < energy_consumption()) {
enabled_ = false;
} else if(energy_stored_ >= (MAX_ENERGY_BUFFER/2)) {
enabled_ = true;
}
final ItemStack last_inp_stack = current_smelting_input_stack_;
current_smelting_input_stack_ = stacks_.get(SMELTING_INPUT_SLOT_NO);
if((!current_smelting_input_stack_.isEmpty()) && (enabled_) && (speed_>0) && (speed_<=MAX_SPEED_SETTING)) {
if(!current_smelting_input_stack_.isItemEqual(current_smelting_input_stack_)) {
proc_time_elapsed_ = 0;
proc_time_needed_ = getCookTime(current_smelting_input_stack_);
}
final boolean can_smelt = canSmelt();
if((!can_smelt) && (BRecipes.instance().getSmeltingResult(current_smelting_input_stack_).isEmpty())) {
// bypass
if(transferItems(SMELTING_INPUT_SLOT_NO, SMELTING_OUTPUT_SLOT_NO, 1)) dirty = true;
} else {
// smelt
if(!isBurning() && can_smelt) {
if(heat_up()) { dirty = true; update_blockstate = true; }
}
if(isBurning() && can_smelt) {
if(heat_up()) dirty = true;
proc_time_elapsed_ += (TICK_INTERVAL * proc_speed_percent_ * speed_setting_factor_[speed_] / 100);
if(proc_time_elapsed_ >= proc_time_needed_) {
proc_time_elapsed_ = 0;
proc_time_needed_ = getCookTime(current_smelting_input_stack_);
smeltItem();
dirty = true;
shift_out = true;
}
} else {
proc_time_elapsed_ = 0;
}
}
} else if(proc_time_elapsed_ > 0) {
proc_time_elapsed_ -= ((stacks_.get(SMELTING_INPUT_SLOT_NO)).isEmpty() ? 20 : 1);
if(proc_time_elapsed_ < 0) { proc_time_elapsed_ = 0; shift_out = true; update_blockstate = true; }
}
if(update_blockstate) {
dirty = true;
sync_blockstate();
}
if(adjacent_inventory_shift(shift_in, shift_out)) dirty = true;
if(dirty) markDirty();
}
}
}

View file

@ -1,91 +0,0 @@
/*
* @file BlockDecorGlassBlock.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Full block-size glass blocks.
*/
package wile.engineersdecor.blocks;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.BlockFaceShape;
import net.minecraft.block.state.IBlockState;
import net.minecraft.util.BlockRenderLayer;
import net.minecraft.world.IBlockAccess;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class BlockDecorGlassBlock extends BlockDecor
{
public BlockDecorGlassBlock(@Nonnull String registryName, long config, @Nullable Material material, float hardness, float resistance, @Nullable SoundType sound)
{
super(registryName, config, material, hardness, resistance, sound);
setLightOpacity(0);
}
@Override
@SideOnly(Side.CLIENT)
public BlockRenderLayer getRenderLayer()
{ return BlockRenderLayer.TRANSLUCENT; }
@Override
@SideOnly(Side.CLIENT)
public boolean shouldSideBeRendered(IBlockState state, IBlockAccess world, BlockPos pos, EnumFacing side)
{
final IBlockState neighbourState = world.getBlockState(pos.offset(side));
return ((neighbourState==null) || (!(neighbourState.getBlock() instanceof BlockDecorGlassBlock)));
}
@Override
@SideOnly(Side.CLIENT)
@SuppressWarnings("deprecation")
public float getAmbientOcclusionLightValue(IBlockState state)
{ return 0.9F; }
@Override
public boolean isOpaqueCube(IBlockState state)
{ return false; }
@Override
public boolean isFullCube(IBlockState state)
{ return true; }
@Override
public boolean isNormalCube(IBlockState state)
{ return false; }
@Override
public int getLightOpacity(IBlockState state, IBlockAccess world, BlockPos pos)
{ return 2; }
@Override
public int getLightValue(IBlockState state, IBlockAccess world, BlockPos pos)
{ return 0; }
@Override
public boolean canCreatureSpawn(IBlockState state, IBlockAccess world, BlockPos pos, net.minecraft.entity.EntityLiving.SpawnPlacementType type)
{ return false; }
@Override
public BlockFaceShape getBlockFaceShape(IBlockAccess world, IBlockState state, BlockPos pos, EnumFacing face)
{ return BlockFaceShape.SOLID; }
@Override
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos)
{ return FULL_BLOCK_AABB; }
@Override
@Nullable
public AxisAlignedBB getCollisionBoundingBox(IBlockState state, IBlockAccess world, BlockPos pos)
{ return FULL_BLOCK_AABB; }
}

View file

@ -1,217 +0,0 @@
/*
* @file BlockDecorHalfSlab.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Half slab ("slab slices") characteristics class. Actually
* it's now a quater slab, but who cares.
*/
package wile.engineersdecor.blocks;
import wile.engineersdecor.detail.ModAuxiliaries;
import wile.engineersdecor.detail.ModConfig;
import net.minecraft.block.Block;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraft.block.properties.PropertyInteger;
import net.minecraft.block.state.BlockFaceShape;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.BlockRenderLayer;
import net.minecraft.util.EnumHand;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
public class BlockDecorHalfSlab extends BlockDecor
{
public static final PropertyInteger PARTS = PropertyInteger.create("parts", 0, 14);
protected static final AxisAlignedBB AABBs[] = {
new AxisAlignedBB(0, 0./16, 0, 1, 2./16, 1), new AxisAlignedBB(0, 0./16, 0, 1, 4./16, 1),
new AxisAlignedBB(0, 0./16, 0, 1, 6./16, 1), new AxisAlignedBB(0, 0./16, 0, 1, 8./16, 1),
new AxisAlignedBB(0, 0./16, 0, 1, 10./16, 1), new AxisAlignedBB(0, 0./16, 0, 1, 12./16, 1),
new AxisAlignedBB(0, 0./16, 0, 1, 14./16, 1), new AxisAlignedBB(0, 0./16, 0, 1, 16./16, 1),
new AxisAlignedBB(0, 2./16, 0, 1, 16./16, 1), new AxisAlignedBB(0, 4./16, 0, 1, 16./16, 1),
new AxisAlignedBB(0, 6./16, 0, 1, 16./16, 1), new AxisAlignedBB(0, 8./16, 0, 1, 16./16, 1),
new AxisAlignedBB(0, 10./16, 0, 1, 16./16, 1), new AxisAlignedBB(0, 12./16, 0, 1, 16./16, 1),
new AxisAlignedBB(0, 14./16, 0, 1, 16./16, 1), new AxisAlignedBB(0,0,0,1,1,1), // <- with 4bit fill
};
protected static final int num_slabs_contained_in_parts_[] = {
1,2,3,4,5,6,7,8,7,6,5,4,3,2,1 ,0x1 // <- with 4bit fill
};
public BlockDecorHalfSlab(@Nonnull String registryName, long config, @Nullable Material material, float hardness, float resistance, @Nullable SoundType sound)
{ super(registryName, config, material, hardness, resistance, sound); }
protected boolean is_cube(IBlockState state)
{ return state.getValue(PARTS) == 0x07; }
@Override
@SideOnly(Side.CLIENT)
public void addInformation(ItemStack stack, @Nullable World world, List<String> tooltip, ITooltipFlag flag)
{
if(!ModAuxiliaries.Tooltip.addInformation(stack, world, tooltip, flag, true)) return;
if(!ModConfig.optout.without_direct_slab_pickup) {
ModAuxiliaries.Tooltip.addInformation("engineersdecor.tooltip.slabpickup", "engineersdecor.tooltip.slabpickup", tooltip, flag, true);
}
}
@Override
@SideOnly(Side.CLIENT)
public BlockRenderLayer getRenderLayer()
{ return (((config & CFG_TRANSLUCENT)!=0) ? (BlockRenderLayer.TRANSLUCENT) : (BlockRenderLayer.CUTOUT)); }
@Override
@SuppressWarnings("deprecation")
public IBlockState getStateFromMeta(int meta)
{ return getDefaultState().withProperty(PARTS, MathHelper.clamp(meta, 0,14)); }
@Override
public int getMetaFromState(IBlockState state)
{ return state.getValue(PARTS); }
@Override
protected BlockStateContainer createBlockState()
{ return new BlockStateContainer(this, PARTS); }
@Override
@SuppressWarnings("deprecation")
public boolean isOpaqueCube(IBlockState state)
{ return ((config & CFG_TRANSLUCENT)==0) && is_cube(state); }
@Override
@SuppressWarnings("deprecation")
public BlockFaceShape getBlockFaceShape(IBlockAccess world, IBlockState state, BlockPos pos, EnumFacing face)
{
final int parts = state.getValue(PARTS);
switch(face) {
case UP:
if(parts >= 0x07) return BlockFaceShape.SOLID;
break;
case DOWN:
if(parts <= 0x07) return BlockFaceShape.SOLID;
break;
default:
if((parts > 0x05) && (parts < 0x0a)) return BlockFaceShape.SOLID;
}
return BlockFaceShape.UNDEFINED;
}
@Override
@SuppressWarnings("deprecation")
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos)
{ return AABBs[state.getValue(PARTS) & 0xf]; }
@Override
@Nullable
public AxisAlignedBB getCollisionBoundingBox(IBlockState state, IBlockAccess world, BlockPos pos)
{ return getBoundingBox(state, world, pos); }
@Override
@SuppressWarnings("deprecation")
public boolean isFullCube(IBlockState state)
{ return is_cube(state); }
@Override
@SuppressWarnings("deprecation")
public boolean isNormalCube(IBlockState state)
{ return is_cube(state); }
@Override
@SuppressWarnings("deprecation")
public boolean canEntitySpawn(IBlockState state, Entity entity)
{ return false; }
@Override
public void harvestBlock(World world, EntityPlayer player, BlockPos pos, IBlockState state, @Nullable TileEntity te, ItemStack stack)
{ spawnAsEntity(world, pos, new ItemStack(Item.getItemFromBlock(this), num_slabs_contained_in_parts_[state.getValue(PARTS) & 0xf])); }
@Override
public boolean canPlaceBlockOnSide(World world, BlockPos pos, EnumFacing side)
{ return world.getBlockState(pos).getBlock() != this; }
@Override
@SuppressWarnings("deprecation")
public IBlockState getStateForPlacement(World world, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer)
{ return getDefaultState().withProperty(PARTS, ((facing==EnumFacing.UP) || ((facing!=EnumFacing.DOWN) && (hitY < 0.6))) ? 0 : 14); }
@Override
public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
{
final ItemStack stack = player.getHeldItem(hand);
if(stack.isEmpty() || (Block.getBlockFromItem(stack.getItem()) != this)) return false;
if((facing != EnumFacing.UP) && (facing != EnumFacing.DOWN)) return false;
int parts = state.getValue(PARTS);
if((facing != EnumFacing.UP) && (parts > 7)) {
world.setBlockState(pos, state.withProperty(PARTS, parts-1), 3);
} else if((facing != EnumFacing.DOWN) && (parts < 7)) {
world.setBlockState(pos, state.withProperty(PARTS, parts+1), 3);
} else {
return (parts != 7);
}
if(world.isRemote) return true;
if(!player.isCreative()) {
stack.shrink(1);
if(player.inventory != null) player.inventory.markDirty(); // @todo: check if inventory can actually be null
}
SoundType st = this.getSoundType(state, world, pos, null);
world.playSound(null, pos, st.getPlaceSound(), SoundCategory.BLOCKS, (st.getVolume()+1f)/2.5f, 0.9f*st.getPitch());
return true;
}
@Override
public void onBlockClicked(World world, BlockPos pos, EntityPlayer player)
{
if((world.isRemote) || (ModConfig.optout.without_direct_slab_pickup)) return;
final ItemStack stack = player.getHeldItemMainhand();
if(stack.isEmpty() || (Block.getBlockFromItem(stack.getItem()) != this)) return;
if(stack.getCount() >= stack.getMaxStackSize()) return;
Vec3d lv = player.getLookVec();
EnumFacing facing = EnumFacing.getFacingFromVector((float)lv.x, (float)lv.y, (float)lv.z);
if((facing != EnumFacing.UP) && (facing != EnumFacing.DOWN)) return;
IBlockState state = world.getBlockState(pos);
if(state.getBlock() != this) return;
int parts = state.getValue(PARTS);
if((facing == EnumFacing.DOWN) && (parts <= 7)) {
if(parts > 0) {
world.setBlockState(pos, state.withProperty(PARTS, parts-1), 3);
} else {
world.setBlockToAir(pos);
}
} else if((facing == EnumFacing.UP) && (parts >= 7)) {
if(parts < 14) {
world.setBlockState(pos, state.withProperty(PARTS, parts + 1), 3);
} else {
world.setBlockToAir(pos);
}
} else {
return;
}
if(!player.isCreative()) {
stack.grow(1);
if(player.inventory != null) player.inventory.markDirty(); // @todo: check if inventory can actually be null
}
SoundType st = this.getSoundType(state, world, pos, null);
world.playSound(player, pos, st.getPlaceSound(), SoundCategory.BLOCKS, (st.getVolume()+1f)/2.5f, 0.9f*st.getPitch());
}
}

View file

@ -1,876 +0,0 @@
/*
* @file BlockDecorHopper.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Hopper, factory automation suitable.
*/
package wile.engineersdecor.blocks;
import net.minecraft.entity.Entity;
import net.minecraft.util.math.*;
import wile.engineersdecor.ModEngineersDecor;
import wile.engineersdecor.detail.Networking;
import net.minecraft.block.state.BlockFaceShape;
import net.minecraft.world.IBlockAccess;
import net.minecraftforge.items.wrapper.SidedInvWrapper;
import net.minecraft.block.Block;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.block.BlockHopper;
import net.minecraft.world.World;
import net.minecraft.world.Explosion;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityHopper;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.item.*;
import net.minecraft.inventory.*;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.util.*;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentTranslation;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.IOException;
import java.util.List;
public class BlockDecorHopper extends BlockDecorDirected
{
public BlockDecorHopper(@Nonnull String registryName, long config, @Nullable Material material, float hardness, float resistance, @Nullable SoundType sound, @Nonnull AxisAlignedBB unrotatedAABB)
{ super(registryName, config, material, hardness, resistance, sound, unrotatedAABB); }
@Override
public BlockFaceShape getBlockFaceShape(IBlockAccess world, IBlockState state, BlockPos pos, EnumFacing face)
{ return BlockFaceShape.SOLID; }
@Override
@SuppressWarnings("deprecation")
public boolean hasComparatorInputOverride(IBlockState state)
{ return true; }
@Override
@SuppressWarnings("deprecation")
public int getComparatorInputOverride(IBlockState blockState, World world, BlockPos pos)
{ return Container.calcRedstone(world.getTileEntity(pos)); }
@Override
public boolean hasTileEntity(IBlockState state)
{ return true; }
@Override
@Nullable
public TileEntity createTileEntity(World world, IBlockState state)
{ return new BTileEntity(); }
@Override
public void onBlockPlacedBy(World world, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack)
{
if(world.isRemote) return;
if((!stack.hasTagCompound()) || (!stack.getTagCompound().hasKey("tedata"))) return;
NBTTagCompound te_nbt = stack.getTagCompound().getCompoundTag("tedata");
if(te_nbt.isEmpty()) return;
final TileEntity te = world.getTileEntity(pos);
if(!(te instanceof BTileEntity)) return;
((BTileEntity)te).readnbt(te_nbt, false);
((BTileEntity)te).reset_rtstate();
((BTileEntity)te).markDirty();
}
@Override
public boolean removedByPlayer(IBlockState state, World world, BlockPos pos, EntityPlayer player, boolean willHarvest)
{
if(world.isRemote) return true;
TileEntity te = world.getTileEntity(pos);
if(!(te instanceof BTileEntity)) return super.removedByPlayer(state, world, pos, player, willHarvest);
ItemStack stack = new ItemStack(this, 1);
NBTTagCompound te_nbt = new NBTTagCompound();
((BTileEntity) te).writenbt(te_nbt, false);
if(!te_nbt.isEmpty()) {
NBTTagCompound nbt = new NBTTagCompound();
nbt.setTag("tedata", te_nbt);
stack.setTagCompound(nbt);
}
world.spawnEntity(new EntityItem(world, pos.getX()+0.5, pos.getY()+0.5, pos.getZ()+0.5, stack));
world.setBlockToAir(pos);
world.removeTileEntity(pos);
return false;
}
@Override
public void onBlockExploded(World world, BlockPos pos, Explosion explosion)
{
if(world.isRemote) return;
TileEntity te = world.getTileEntity(pos);
if(!(te instanceof BTileEntity)) return;
for(ItemStack stack: ((BTileEntity)te).stacks_) {
if(!stack.isEmpty()) world.spawnEntity(new EntityItem(world, pos.getX(), pos.getY(), pos.getZ(), stack));
}
((BTileEntity)te).reset_rtstate();
super.onBlockExploded(world, pos, explosion);
}
@Override
public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
{
if(world.isRemote) return true;
player.openGui(ModEngineersDecor.instance, ModEngineersDecor.GuiHandler.GUIID_FACTORY_HOPPER, world, pos.getX(), pos.getY(), pos.getZ());
return true;
}
@Override
public void neighborChanged(IBlockState state, World world, BlockPos pos, Block block, BlockPos neighborPos)
{
if(!(world instanceof World) || (((World) world).isRemote)) return;
TileEntity te = world.getTileEntity(pos);
if(!(te instanceof BTileEntity)) return;
((BTileEntity)te).block_updated();
}
@Override
public void onFallenUpon(World world, BlockPos pos, Entity entity, float fallDistance)
{
super.onFallenUpon(world, pos, entity, fallDistance);
if(!(entity instanceof EntityItem)) return;
TileEntity te = world.getTileEntity(pos);
if(!(te instanceof BTileEntity)) return;
((BTileEntity)te).collection_timer_ = 0;
}
//--------------------------------------------------------------------------------------------------------------------
// ModEngineersDecor.GuiHandler connectors
//--------------------------------------------------------------------------------------------------------------------
public static Object getServerGuiElement(final EntityPlayer player, final World world, final BlockPos pos, final TileEntity te)
{ return (te instanceof BTileEntity) ? (new BContainer(player.inventory, world, pos, (BTileEntity)te)) : null; }
public static Object getClientGuiElement(final EntityPlayer player, final World world, final BlockPos pos, final TileEntity te)
{ return (te instanceof BTileEntity) ? (new BGui(player.inventory, world, pos, (BTileEntity)te)) : null; }
//--------------------------------------------------------------------------------------------------------------------
// GUI
//--------------------------------------------------------------------------------------------------------------------
@SideOnly(Side.CLIENT)
private static class BGui extends GuiContainer
{
private final BTileEntity te;
public BGui(InventoryPlayer playerInventory, World world, BlockPos pos, BTileEntity te)
{ super(new BContainer(playerInventory, world, pos, te)); this.te = te; }
@Override
public void initGui()
{ super.initGui(); }
@Override
public void drawScreen(int mouseX, int mouseY, float partialTicks)
{
drawDefaultBackground();
super.drawScreen(mouseX, mouseY, partialTicks);
renderHoveredToolTip(mouseX, mouseY);
}
@Override
protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException
{
super.mouseClicked(mouseX, mouseY, mouseButton);
BContainer container = (BContainer)inventorySlots;
if(container.fields_.length != 7) return;
int mx = mouseX - getGuiLeft(), my = mouseY - getGuiTop();
if(!isPointInRegion(126, 1, 49, 60, mouseX, mouseY)) {
return;
} else if(isPointInRegion(128, 9, 44, 10, mouseX, mouseY)) {
int range = (mx-133);
if(range < -1) {
range = container.fields_[0] - 1; // -
} else if(range >= 34) {
range = container.fields_[0] + 1; // +
} else {
range = (int)(0.5 + ((((double)BTileEntity.MAX_COLLECTION_RANGE) * range)/34)); // slider
range = MathHelper.clamp(range, 0, BTileEntity.MAX_COLLECTION_RANGE);
}
NBTTagCompound nbt = new NBTTagCompound();
nbt.setInteger("range", range);
Networking.PacketTileNotify.sendToServer(te, nbt);
} else if(isPointInRegion(128, 21, 44, 10, mouseX, mouseY)) {
int period = (mx-133);
if(period < -1) {
period = container.fields_[3] - 3; // -
} else if(period >= 35) {
period = container.fields_[3] + 3; // +
} else {
period = (int)(0.5 + ((100.0 * period)/34));
}
period = MathHelper.clamp(period, 0, 100);
NBTTagCompound nbt = new NBTTagCompound();
nbt.setInteger("period", period);
Networking.PacketTileNotify.sendToServer(te, nbt);
} else if(isPointInRegion(128, 34, 44, 10, mouseX, mouseY)) {
int ndrop = (mx-134);
if(ndrop < -1) {
ndrop = container.fields_[1] - 1; // -
} else if(ndrop >= 34) {
ndrop = container.fields_[1] + 1; // +
} else {
ndrop = MathHelper.clamp(1+ndrop, 1, BTileEntity.MAX_TRANSFER_COUNT); // slider
}
NBTTagCompound nbt = new NBTTagCompound();
nbt.setInteger("xsize", ndrop);
Networking.PacketTileNotify.sendToServer(te, nbt);
} else if(isPointInRegion(133, 49, 9, 9, mouseX, mouseY)) {
NBTTagCompound nbt = new NBTTagCompound();
nbt.setInteger("manual_trigger", 1);
Networking.PacketTileNotify.sendToServer(te, nbt);
} else if(isPointInRegion(145, 49, 9, 9, mouseX, mouseY)) {
NBTTagCompound nbt = new NBTTagCompound();
nbt.setInteger("logic", container.fields_[2] ^ BTileEntity.LOGIC_INVERTED);
Networking.PacketTileNotify.sendToServer(te, nbt);
} else if(isPointInRegion(159, 49, 7, 9, mouseX, mouseY)) {
NBTTagCompound nbt = new NBTTagCompound();
nbt.setInteger("logic", container.fields_[2] ^ BTileEntity.LOGIC_CONTINUOUS);
Networking.PacketTileNotify.sendToServer(te, nbt);
}
}
@Override
protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY)
{
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
mc.getTextureManager().bindTexture(new ResourceLocation(ModEngineersDecor.MODID, "textures/gui/factory_hopper_gui.png"));
final int x0=getGuiLeft(), y0=getGuiTop(), w=getXSize(), h=getYSize();
drawTexturedModalRect(x0, y0, 0, 0, w, h);
BContainer container = (BContainer)inventorySlots;
if(container.fields_.length != 7) return; // no init, no cake.
// active slot
{
int slot_index = container.fields_[6];
if((slot_index < 0) || (slot_index >= BTileEntity.NUM_OF_SLOTS)) slot_index = 0;
int x = (x0+10+((slot_index % 6) * 18));
int y = (y0+8+((slot_index / 6) * 17));
drawTexturedModalRect(x, y, 200, 8, 18, 18);
}
// collection range
{
int lut[] = { 133, 141, 149, 157, 166 };
int px = lut[MathHelper.clamp(container.fields_[0], 0, BTileEntity.MAX_COLLECTION_RANGE)];
int x = x0 + px - 2;
int y = y0 + 14;
drawTexturedModalRect(x, y, 179, 40, 5, 5);
}
// transfer period
{
int px = (int)Math.round(((33.5 * container.fields_[3]) / 100) + 1);
int x = x0 + 132 - 2 + MathHelper.clamp(px, 0, 34);
int y = y0 + 27;
drawTexturedModalRect(x, y, 179, 40, 5, 5);
}
// transfer count
{
int x = x0 + 133 - 2 + (container.fields_[1]);
int y = y0 + 40;
drawTexturedModalRect(x, y, 179, 40, 5, 5);
}
// redstone input
{
if(container.fields_[5] != 0) {
drawTexturedModalRect(x0+133, y0+49, 217, 49, 9, 9);
}
}
// trigger logic
{
int inverter_offset = ((container.fields_[2] & BTileEntity.LOGIC_INVERTED) != 0) ? 11 : 0;
drawTexturedModalRect(x0+145, y0+49, 177+inverter_offset, 49, 9, 9);
int pulse_mode_offset = ((container.fields_[2] & BTileEntity.LOGIC_CONTINUOUS ) != 0) ? 9 : 0;
drawTexturedModalRect(x0+159, y0+49, 199+pulse_mode_offset, 49, 9, 9);
}
// delay timer running indicator
{
if((container.fields_[4] > BTileEntity.PERIOD_OFFSET) && ((System.currentTimeMillis() % 1000) < 500)) {
drawTexturedModalRect(x0+148, y0+22, 187, 22, 3, 3);
}
}
}
}
//--------------------------------------------------------------------------------------------------------------------
// container
//--------------------------------------------------------------------------------------------------------------------
public static class BContainer extends Container
{
private static final int PLAYER_INV_START_SLOTNO = BTileEntity.NUM_OF_SLOTS;
private final World world;
private final BlockPos pos;
private final EntityPlayer player;
private final BTileEntity te;
private int fields_[] = new int[7];
public BContainer(InventoryPlayer playerInventory, World world, BlockPos pos, BTileEntity te)
{
this.player = playerInventory.player;
this.world = world;
this.pos = pos;
this.te = te;
int i=-1;
// device slots (stacks 0 to 17)
for(int y=0; y<3; ++y) {
for(int x=0; x<6; ++x) {
int xpos = 11+x*18, ypos = 9+y*17;
addSlotToContainer(new Slot(te, ++i, xpos, ypos));
}
}
// player slots
for(int x=0; x<9; ++x) {
addSlotToContainer(new Slot(playerInventory, x, 8+x*18, 129)); // player slots: 0..8
}
for(int y=0; y<3; ++y) {
for(int x=0; x<9; ++x) {
addSlotToContainer(new Slot(playerInventory, x+y*9+9, 8+x*18, 71+y*18)); // player slots: 9..35
}
}
}
public BlockPos getPos()
{ return pos; }
@Override
public void addListener(IContainerListener listener)
{ super.addListener(listener); listener.sendAllWindowProperties(this, te); }
@Override
public void detectAndSendChanges()
{
super.detectAndSendChanges();
for(int il=0; il<listeners.size(); ++il) {
IContainerListener lis = listeners.get(il);
for(int k=0; k<fields_.length; ++k) {
int f = te.getField(k);
if(fields_[k] != f) {
fields_[k] = f;
lis.sendWindowProperty(this, k, f);
}
}
}
}
@Override
@SideOnly(Side.CLIENT)
public void updateProgressBar(int id, int value)
{
if((id < 0) || (id >= fields_.length)) return;
fields_[id] = value;
te.setField(id, value);
}
@Override
public boolean canInteractWith(EntityPlayer player)
{ return (world.getBlockState(pos).getBlock() instanceof BlockDecorHopper) && (player.getDistanceSq(pos) <= 64); }
@Override
public ItemStack transferStackInSlot(EntityPlayer player, int index)
{
Slot slot = inventorySlots.get(index);
if((slot==null) || (!slot.getHasStack())) return ItemStack.EMPTY;
ItemStack slot_stack = slot.getStack();
ItemStack transferred = slot_stack.copy();
if((index>=0) && (index<PLAYER_INV_START_SLOTNO)) {
// Device slots
if(!mergeItemStack(slot_stack, PLAYER_INV_START_SLOTNO, PLAYER_INV_START_SLOTNO+36, false)) return ItemStack.EMPTY;
} else if((index >= PLAYER_INV_START_SLOTNO) && (index <= PLAYER_INV_START_SLOTNO+36)) {
// Player slot
if(!mergeItemStack(slot_stack, 0, BTileEntity.NUM_OF_SLOTS, false)) return ItemStack.EMPTY;
} else {
// invalid slot
return ItemStack.EMPTY;
}
if(slot_stack.isEmpty()) {
slot.putStack(ItemStack.EMPTY);
} else {
slot.onSlotChanged();
}
if(slot_stack.getCount() == transferred.getCount()) return ItemStack.EMPTY;
slot.onTake(player, slot_stack);
return transferred;
}
}
//--------------------------------------------------------------------------------------------------------------------
// Tile entity
//--------------------------------------------------------------------------------------------------------------------
public static class BTileEntity extends TileEntity implements ITickable, ISidedInventory, Networking.IPacketReceiver
{
public static final int TICK_INTERVAL = 10;
public static final int COLLECTION_INTERVAL = 25;
public static final int NUM_OF_SLOTS = 18;
public static final int MAX_TRANSFER_COUNT = 32;
public static final int MAX_COLLECTION_RANGE = 4;
public static final int PERIOD_OFFSET = 10;
///
public static final int LOGIC_INVERTED = 0x01;
public static final int LOGIC_CONTINUOUS = 0x02;
///
private boolean block_power_signal_ = false;
private boolean block_power_updated_ = false;
private int collection_timer_ = 0;
private int delay_timer_ = 0;
private int transfer_count_ = 1;
private int logic_ = LOGIC_INVERTED|LOGIC_CONTINUOUS;
private int transfer_period_ = 0;
private int collection_range_ = 0;
private int current_slot_index_ = 0;
private int tick_timer_ = 0;
protected NonNullList<ItemStack> stacks_;
public static void on_config(int cooldown_ticks)
{
// ModEngineersDecor.logger.info("Config factory hopper:");
}
public BTileEntity()
{
stacks_ = NonNullList.<ItemStack>withSize(NUM_OF_SLOTS, ItemStack.EMPTY);
reset_rtstate();
}
public void reset_rtstate()
{
block_power_signal_ = false;
block_power_updated_ = false;
}
public void readnbt(NBTTagCompound nbt, boolean update_packet)
{
stacks_ = NonNullList.<ItemStack>withSize(NUM_OF_SLOTS, ItemStack.EMPTY);
ItemStackHelper.loadAllItems(nbt, stacks_);
while(stacks_.size() < NUM_OF_SLOTS) stacks_.add(ItemStack.EMPTY);
block_power_signal_ = nbt.getBoolean("powered");
current_slot_index_ = nbt.getInteger("act_slot_index");
transfer_count_ = MathHelper.clamp(nbt.getInteger("xsize"), 1, MAX_TRANSFER_COUNT);
logic_ = nbt.getInteger("logic");
transfer_period_ = nbt.getInteger("period");
collection_range_ = nbt.getInteger("range");
}
protected void writenbt(NBTTagCompound nbt, boolean update_packet)
{
ItemStackHelper.saveAllItems(nbt, stacks_);
nbt.setBoolean("powered", block_power_signal_);
nbt.setInteger("act_slot_index", current_slot_index_);
nbt.setInteger("xsize", transfer_count_);
nbt.setInteger("logic", logic_);
nbt.setInteger("period", transfer_period_);
nbt.setInteger("range", collection_range_);
}
public void block_updated()
{
// RS power check, both edges
boolean powered = world.isBlockPowered(pos);
if(block_power_signal_ != powered) block_power_updated_ = true;
block_power_signal_ = powered;
tick_timer_ = 1;
}
public boolean is_input_slot(int index)
{ return (index >= 0) && (index < NUM_OF_SLOTS); }
// TileEntity ------------------------------------------------------------------------------
@Override
public boolean shouldRefresh(World world, BlockPos pos, IBlockState os, IBlockState ns)
{ return (os.getBlock() != ns.getBlock()) || (!(ns.getBlock() instanceof BlockDecorHopper)); }
@Override
public void readFromNBT(NBTTagCompound nbt)
{ super.readFromNBT(nbt); readnbt(nbt, false); }
@Override
public NBTTagCompound writeToNBT(NBTTagCompound nbt)
{ super.writeToNBT(nbt); writenbt(nbt, false); return nbt; }
// IWorldNamable ---------------------------------------------------------------------------
@Override
public String getName()
{ final Block block=getBlockType(); return (block!=null) ? (block.getTranslationKey() + ".name") : (""); }
@Override
public boolean hasCustomName()
{ return false; }
@Override
public ITextComponent getDisplayName()
{ return new TextComponentTranslation(getName(), new Object[0]); }
// IInventory ------------------------------------------------------------------------------
@Override
public int getSizeInventory()
{ return stacks_.size(); }
@Override
public boolean isEmpty()
{ for(ItemStack stack: stacks_) { if(!stack.isEmpty()) return false; } return true; }
@Override
public ItemStack getStackInSlot(int index)
{ return (index < getSizeInventory()) ? stacks_.get(index) : ItemStack.EMPTY; }
@Override
public ItemStack decrStackSize(int index, int count)
{ return ItemStackHelper.getAndSplit(stacks_, index, count); }
@Override
public ItemStack removeStackFromSlot(int index)
{ return ItemStackHelper.getAndRemove(stacks_, index); }
@Override
public void setInventorySlotContents(int index, ItemStack stack)
{
stacks_.set(index, stack);
if(stack.getCount() > getInventoryStackLimit()) stack.setCount(getInventoryStackLimit());
if(tick_timer_ > 8) tick_timer_ = 8;
markDirty();
}
@Override
public int getInventoryStackLimit()
{ return 64; }
@Override
public void markDirty()
{ super.markDirty(); }
@Override
public boolean isUsableByPlayer(EntityPlayer player)
{ return ((world.getTileEntity(pos) == this) && (player.getDistanceSq(pos.getX()+0.5d, pos.getY()+0.5d, pos.getZ()+0.5d) <= 64.0d)); }
@Override
public void openInventory(EntityPlayer player)
{}
@Override
public void closeInventory(EntityPlayer player)
{ markDirty(); }
@Override
public boolean isItemValidForSlot(int index, ItemStack stack)
{ return true; }
@Override
public int getField(int id)
{
switch(id) {
case 0: return collection_range_;
case 1: return transfer_count_;
case 2: return logic_;
case 3: return transfer_period_;
case 4: return delay_timer_;
case 5: return block_power_signal_ ? 1 : 0;
case 6: return current_slot_index_;
default: return 0;
}
}
@Override
public void setField(int id, int value)
{
switch(id) {
case 0: collection_range_ = MathHelper.clamp(value,0, MAX_COLLECTION_RANGE); return;
case 1: transfer_count_ = MathHelper.clamp(value,1, MAX_TRANSFER_COUNT); return;
case 2: logic_ = value; return;
case 3: transfer_period_ = MathHelper.clamp(value,0, 100); return;
case 4: delay_timer_ = MathHelper.clamp(value,0, 400); return;
case 5: block_power_signal_ = (value != 0); return;
case 6: current_slot_index_ = MathHelper.clamp(value, 0, NUM_OF_SLOTS-1); return;
default: return;
}
}
@Override
public int getFieldCount()
{ return 7; }
@Override
public void clear()
{ stacks_.clear(); }
// ISidedInventory ----------------------------------------------------------------------------
private final IItemHandler item_handler_ = new SidedInvWrapper(this, EnumFacing.UP);
private final IItemHandler down_item_handler_ = new SidedInvWrapper(this, EnumFacing.DOWN);
private static final int[] SIDED_INV_SLOTS;
static {
SIDED_INV_SLOTS = new int[NUM_OF_SLOTS];
for(int i=0; i<NUM_OF_SLOTS; ++i) SIDED_INV_SLOTS[i] = i;
}
@Override
public int[] getSlotsForFace(EnumFacing side)
{ return SIDED_INV_SLOTS; }
@Override
public boolean canInsertItem(int index, ItemStack stack, EnumFacing direction)
{ return is_input_slot(index) && isItemValidForSlot(index, stack); }
@Override
public boolean canExtractItem(int index, ItemStack stack, EnumFacing direction)
{ return direction==EnumFacing.DOWN; }
// Capability export ----------------------------------------------------------------------------
@Override
public boolean hasCapability(Capability<?> cap, EnumFacing facing)
{ return (cap==CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) || super.hasCapability(cap, facing); }
@Override
@SuppressWarnings("unchecked")
@Nullable
public <T> T getCapability(Capability<T> capability, @Nullable EnumFacing facing)
{
if(capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
return (facing == EnumFacing.DOWN) ? ((T)down_item_handler_) : ((T)item_handler_);
}
return super.getCapability(capability, facing);
}
// IPacketReceiver -------------------------------------------------------------------------------
@Override
public void onServerPacketReceived(NBTTagCompound nbt)
{}
@Override
public void onClientPacketReceived(EntityPlayer player, NBTTagCompound nbt)
{
if(nbt.hasKey("xsize")) transfer_count_ = MathHelper.clamp(nbt.getInteger("xsize"), 1, MAX_TRANSFER_COUNT);
if(nbt.hasKey("period")) transfer_period_ = MathHelper.clamp(nbt.getInteger("period"), 0, 100);
if(nbt.hasKey("range")) collection_range_ = MathHelper.clamp(nbt.getInteger("range"), 0, MAX_COLLECTION_RANGE);
if(nbt.hasKey("logic")) logic_ = nbt.getInteger("logic");
if(nbt.hasKey("manual_trigger") && (nbt.getInteger("manual_trigger")!=0)) { block_power_signal_=true; block_power_updated_=true; tick_timer_=1; }
markDirty();
}
// ITickable and aux methods ---------------------------------------------------------------------
private static int next_slot(int i)
{ return (i<NUM_OF_SLOTS-1) ? (i+1) : 0; }
private int try_insert_into_hopper(final ItemStack stack)
{
final int max_to_insert = stack.getCount();
int n_to_insert = max_to_insert;
int first_empty_slot = -1;
for(int i=0; i<stacks_.size(); ++i) {
final ItemStack slotstack = stacks_.get(i);
if((first_empty_slot < 0) && slotstack.isEmpty()) { first_empty_slot=i; continue; }
if(!stack.isItemEqual(slotstack)) continue;
int nspace = slotstack.getMaxStackSize() - slotstack.getCount();
if(nspace <= 0) {
continue;
} else if(nspace >= n_to_insert) {
slotstack.grow(n_to_insert);
n_to_insert = 0;
break;
} else {
slotstack.grow(nspace);
n_to_insert -= nspace;
}
}
if((n_to_insert > 0) && (first_empty_slot >= 0)) {
ItemStack new_stack = stack.copy();
new_stack.setCount(n_to_insert);
stacks_.set(first_empty_slot, new_stack);
n_to_insert = 0;
}
return max_to_insert - n_to_insert;
}
private boolean try_insert(EnumFacing facing)
{
ItemStack current_stack = ItemStack.EMPTY;
for(int i=0; i<NUM_OF_SLOTS; ++i) {
if(current_slot_index_ >= NUM_OF_SLOTS) current_slot_index_ = 0;
current_stack = stacks_.get(current_slot_index_);
if(!current_stack.isEmpty()) break;
current_slot_index_ = next_slot(current_slot_index_);
}
if(current_stack.isEmpty()) {
current_slot_index_ = 0;
return false;
}
final TileEntity te = world.getTileEntity(pos.offset(facing));
if((te == null) || (!te.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, facing.getOpposite()))) {
delay_timer_ = TICK_INTERVAL+2; // no reason to recalculate this all the time if there is nothere to insert.
return false;
} else if(te instanceof TileEntityHopper) {
EnumFacing f = world.getBlockState(pos.offset(facing)).getValue(BlockHopper.FACING);
if(f==facing.getOpposite()) return false; // no back transfer
} else if(te instanceof BTileEntity) {
EnumFacing f = world.getBlockState(pos.offset(facing)).getValue(FACING);
if(f==facing.getOpposite()) return false;
}
ItemStack insert_stack = current_stack.copy();
if(insert_stack.getCount() > transfer_count_) insert_stack.setCount(transfer_count_);
final int initial_insert_stack_size = insert_stack.getCount();
final IItemHandler ih = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, facing.getOpposite());
int first_empty_slot_index = -1;
if((ih == null) || ih.getSlots() <= 0) return false;
for(int i=0; i<ih.getSlots(); ++i) {
if(!ih.isItemValid(i, insert_stack)) continue;
final ItemStack target_stack = ih.getStackInSlot(i);
if((first_empty_slot_index < 0) && target_stack.isEmpty()) first_empty_slot_index = i;
if(!target_stack.isItemEqual(insert_stack)) continue;
insert_stack = ih.insertItem(i, insert_stack.copy(), false);
if(insert_stack.isEmpty()) break;
}
if((first_empty_slot_index >= 0) && (!insert_stack.isEmpty())) {
insert_stack = ih.insertItem(first_empty_slot_index, insert_stack.copy(), false);
}
final int num_inserted = initial_insert_stack_size-insert_stack.getCount();
if(num_inserted > 0) {
current_stack.shrink(num_inserted);
stacks_.set(current_slot_index_, current_stack);
}
if(!insert_stack.isEmpty()) current_slot_index_ = next_slot(current_slot_index_);
return (num_inserted > 0);
}
private boolean try_item_handler_extract(final IItemHandler ih)
{
final int end = ih.getSlots();
int n_to_extract = transfer_count_;
for(int i=0; i<end; ++i) {
if(ih.getStackInSlot(i).isEmpty()) continue;
ItemStack stack = ih.extractItem(i, n_to_extract, true);
if(stack.isEmpty()) continue;
int n_accepted = try_insert_into_hopper(stack);
if(n_accepted > 0) {
ItemStack test = ih.extractItem(i, n_accepted, false);
n_to_extract -= n_accepted;
if(n_to_extract <= 0) break;
}
}
return (n_to_extract < transfer_count_);
}
private boolean try_inventory_extract(final IInventory inv)
{
final int end = inv.getSizeInventory();
int n_to_extract = transfer_count_;
for(int i=0; i<end; ++i) {
ItemStack stack = inv.getStackInSlot(i).copy();
if(stack.isEmpty()) continue;
int n_accepted = try_insert_into_hopper(stack);
if(n_accepted > 0) {
stack.shrink(n_accepted);
n_to_extract -= n_accepted;
if(stack.isEmpty()) stack = ItemStack.EMPTY;
inv.setInventorySlotContents(i, stack);
if(n_to_extract <= 0) break;
}
}
if(n_to_extract < transfer_count_) {
inv.markDirty();
return true;
} else {
return false;
}
}
private boolean try_collect(EnumFacing facing)
{
AxisAlignedBB collection_volume;
BlockPos rpos;
if(facing==EnumFacing.UP) {
rpos = pos.add(0.5, 1.5,0.5);
collection_volume = (new AxisAlignedBB(pos.up())).grow(0.1+collection_range_, 0.6, 0.1+collection_range_);
} else {
rpos = pos.add(0.5, -1.5,0.5);
collection_volume = (new AxisAlignedBB(pos.down(2))).grow(0.1+collection_range_, 1, 0.1+collection_range_);
}
final List<EntityItem> items = world.getEntitiesWithinAABB(EntityItem.class, collection_volume);
if(items.size() <= 0) return false;
final int max_to_collect = 3;
int n_collected = 0;
for(EntityItem ie:items) {
boolean is_direct_collection_tange = ie.getDistanceSq(rpos)<0.7;
if(!is_direct_collection_tange && (ie.cannotPickup() || (!ie.onGround))) continue;
ItemStack stack = ie.getItem();
int n_accepted = try_insert_into_hopper(stack);
if(n_accepted <= 0) continue;
if(n_accepted == stack.getCount()) {
ie.setDead();
} else {
stack.shrink(n_accepted);
}
if((!is_direct_collection_tange) && (++n_collected >= max_to_collect)) break;
}
return (n_collected > 0);
}
@Override
public void update()
{
// Tick cycle pre-conditions
if(world.isRemote) return;
if((delay_timer_ > 0) && ((--delay_timer_) == 0)) markDirty();
if(--tick_timer_ > 0) return;
tick_timer_ = TICK_INTERVAL;
final IBlockState state = world.getBlockState(pos);
if(!(state.getBlock() instanceof BlockDecorHopper)) { block_power_signal_= false; return; }
// Cycle init
boolean dirty = block_power_updated_;
boolean rssignal = ((logic_ & LOGIC_INVERTED)!=0)==(!block_power_signal_);
boolean trigger = (rssignal && ((block_power_updated_) || ((logic_ & LOGIC_CONTINUOUS)!=0)));
final EnumFacing hopper_facing = state.getValue(FACING);
// Trigger edge detection for next cycle
{
boolean tr = world.isBlockPowered(pos);
block_power_updated_ = (block_power_signal_ != tr);
block_power_signal_ = tr;
if(block_power_updated_) dirty = true;
}
// Collection
if(rssignal) {
EnumFacing hopper_input_facing = (hopper_facing==EnumFacing.UP) ? EnumFacing.DOWN : EnumFacing.UP;
TileEntity te = world.getTileEntity(pos.offset(hopper_input_facing));
boolean has_item_handler = ((te!=null) && te.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, hopper_input_facing.getOpposite()));
if(has_item_handler || (te instanceof ISidedInventory)) {
// IItemHandler pulling
if(has_item_handler) {
final IItemHandler ih = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, hopper_facing.getOpposite());
if((ih != null) && try_item_handler_extract(ih)) dirty = true;
} else {
try_inventory_extract((IInventory)te);
}
} else if((collection_timer_ -= TICK_INTERVAL) <= 0) {
// Ranged collection
collection_timer_ = COLLECTION_INTERVAL;
if(try_collect(hopper_input_facing)) dirty = true;
}
}
// Insertion
if(trigger && (delay_timer_ <= 0)) {
delay_timer_ = PERIOD_OFFSET + transfer_period_ * 2;
if(try_insert(hopper_facing)) dirty = true;
}
if(dirty) markDirty();
if(trigger && (tick_timer_ > TICK_INTERVAL)) tick_timer_ = TICK_INTERVAL;
}
}
}

View file

@ -1,144 +0,0 @@
/*
* @file BlockDecorHorizontalSupport.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Horizontal ceiling support. Symmetric x axis, fixed in
* xz plane, therefore boolean placement state.
*/
package wile.engineersdecor.blocks;
import net.minecraft.block.SoundType;
import net.minecraft.block.properties.PropertyBool;
import net.minecraft.block.properties.PropertyInteger;
import net.minecraft.util.EnumHand;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import wile.engineersdecor.ModContent;
import wile.engineersdecor.detail.ModAuxiliaries;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.BlockFaceShape;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.world.World;
import net.minecraft.world.IBlockAccess;
import net.minecraft.util.Mirror;
import net.minecraft.util.Rotation;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Arrays;
public class BlockDecorHorizontalSupport extends BlockDecor
{
public static final PropertyBool EASTWEST = PropertyBool.create("eastwest");
public static final PropertyBool LEFTBEAM = PropertyBool.create("leftbeam");
public static final PropertyBool RIGHTBEAM = PropertyBool.create("rightbeam");
public static final PropertyInteger DOWNCONNECT = PropertyInteger.create("downconnect", 0, 2);
protected final ArrayList<AxisAlignedBB> AABBs;
public BlockDecorHorizontalSupport(@Nonnull String registryName, long config, @Nullable Material material, float hardness, float resistance, @Nullable SoundType sound, @Nonnull AxisAlignedBB unrotatedAABB)
{
super(registryName, config|CFG_HORIZIONTAL, material, hardness, resistance, sound);
AABBs = new ArrayList<AxisAlignedBB>(Arrays.asList(
// Effective bounding box
ModAuxiliaries.getRotatedAABB(unrotatedAABB.grow(2.0/16, 0, 0), EnumFacing.NORTH, true),
ModAuxiliaries.getRotatedAABB(unrotatedAABB.grow(2.0/16, 0, 0), EnumFacing.WEST, true),
// Displayed bounding box
ModAuxiliaries.getRotatedAABB(unrotatedAABB, EnumFacing.NORTH, true),
ModAuxiliaries.getRotatedAABB(unrotatedAABB, EnumFacing.WEST, true)
));
}
@Override
public boolean isOpaqueCube(IBlockState state)
{ return false; }
@Override
public boolean isFullCube(IBlockState state)
{ return false; }
@Override
public boolean isNormalCube(IBlockState state)
{ return false; }
@Override
public boolean canCreatureSpawn(IBlockState state, IBlockAccess world, BlockPos pos, net.minecraft.entity.EntityLiving.SpawnPlacementType type)
{ return false; }
@Override
public BlockFaceShape getBlockFaceShape(IBlockAccess world, IBlockState state, BlockPos pos, EnumFacing face)
{ return BlockFaceShape.UNDEFINED; }
@SideOnly(Side.CLIENT)
public AxisAlignedBB getSelectedBoundingBox(IBlockState state, World world, BlockPos pos)
{ return AABBs.get(state.getValue(EASTWEST) ? 0x3 : 0x2).offset(pos); }
@Override
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos)
{ return AABBs.get(state.getValue(EASTWEST) ? 0x1 : 0x0); }
@Override
@Nullable
public AxisAlignedBB getCollisionBoundingBox(IBlockState state, IBlockAccess world, BlockPos pos)
{ return getBoundingBox(state, world, pos); }
@Override
public IBlockState getStateFromMeta(int meta)
{ return getDefaultState().withProperty(EASTWEST, ((meta & 0x1) != 0)); }
@Override
public int getMetaFromState(IBlockState state)
{ return (state.getValue(EASTWEST) ? 0x1:0x0); }
@Override
public IBlockState getActualState(IBlockState state, IBlockAccess world, BlockPos pos)
{
boolean ew = state.getValue(EASTWEST);
final IBlockState rstate = world.getBlockState((!ew) ? (pos.east()) : (pos.south()) );
final IBlockState lstate = world.getBlockState((!ew) ? (pos.west()) : (pos.north()) );
final IBlockState dstate = world.getBlockState(pos.down());
int down_connector = 0;
if((dstate.getBlock() instanceof BlockDecorStraightPole)) {
final EnumFacing dfacing = dstate.getValue(BlockDecorStraightPole.FACING);
final BlockDecorStraightPole pole = (BlockDecorStraightPole)dstate.getBlock();
if((dfacing.getAxis() == EnumFacing.Axis.Y)) {
if((pole==ModContent.THICK_STEEL_POLE) || ((pole==ModContent.THICK_STEEL_POLE_HEAD) && (dfacing==EnumFacing.UP))) {
down_connector = 2;
} else if((pole==ModContent.THIN_STEEL_POLE) || ((pole==ModContent.THIN_STEEL_POLE_HEAD) && (dfacing==EnumFacing.UP))) {
down_connector = 1;
}
}
}
return state.withProperty(RIGHTBEAM, (rstate.getBlock()==this) && (rstate.getValue(EASTWEST) != ew))
.withProperty(LEFTBEAM , (lstate.getBlock()==this) && (lstate.getValue(EASTWEST) != ew))
.withProperty(DOWNCONNECT , down_connector);
}
@Override
protected BlockStateContainer createBlockState()
{ return new BlockStateContainer(this, EASTWEST, RIGHTBEAM, LEFTBEAM, DOWNCONNECT); }
@Override
public IBlockState withRotation(IBlockState state, Rotation rot)
{ return (rot==Rotation.CLOCKWISE_180) ? state : state.withProperty(EASTWEST, !state.getValue(EASTWEST)); }
@Override
public IBlockState withMirror(IBlockState state, Mirror mirrorIn)
{ return state; }
@Override
public boolean canPlaceBlockOnSide(World world, BlockPos pos, EnumFacing side)
{ return super.canPlaceBlockOnSide(world, pos, side); }
@Override
public IBlockState getStateForPlacement(World world, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer, EnumHand hand)
{ return getActualState(getDefaultState().withProperty(EASTWEST, (placer.getHorizontalFacing().getAxis()==EnumFacing.Axis.X)), world, pos); }
}

View file

@ -1,589 +0,0 @@
/*
* @file BlockDecorLabeledCrate.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Storage crate with a content hint.
*/
package wile.engineersdecor.blocks;
import wile.engineersdecor.ModEngineersDecor;
import net.minecraft.block.Block;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.*;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.play.server.SPacketUpdateTileEntity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentTranslation;
import net.minecraft.world.Explosion;
import net.minecraft.world.World;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class BlockDecorLabeledCrate extends BlockDecorDirectedHorizontal
{
public static void on_config(int stack_limit)
{
}
//--------------------------------------------------------------------------------------------------------------------
// Block
//--------------------------------------------------------------------------------------------------------------------
public BlockDecorLabeledCrate(@Nonnull String registryName, long config, @Nullable Material material, float hardness, float resistance, @Nullable SoundType sound, @Nonnull AxisAlignedBB unrotatedAABB)
{ super(registryName, config, material, hardness, resistance, sound, unrotatedAABB); }
@Override
public boolean hasTileEntity(IBlockState state)
{ return true; }
@Override
@Nullable
public TileEntity createTileEntity(World world, IBlockState state)
{ return new LabeledCrateTileEntity(); }
@Override
public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
{
if(world.isRemote) return true;
player.openGui(ModEngineersDecor.instance, ModEngineersDecor.GuiHandler.GUIID_LABELED_CRATE, world, pos.getX(), pos.getY(), pos.getZ());
return true;
}
@Override
public void onBlockPlacedBy(World world, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack)
{
if(world.isRemote) return;
if((!stack.hasTagCompound()) || (!stack.getTagCompound().hasKey("inventory"))) return;
NBTTagCompound inventory_nbt = stack.getTagCompound().getCompoundTag("inventory");
if(inventory_nbt.isEmpty()) return;
final TileEntity te = world.getTileEntity(pos);
if(!(te instanceof LabeledCrateTileEntity)) return;
((LabeledCrateTileEntity)te).readnbt(inventory_nbt);
((LabeledCrateTileEntity)te).markDirty();
}
private ItemStack itemize_with_inventory(World world, BlockPos pos)
{
TileEntity te = world.getTileEntity(pos);
if(!(te instanceof LabeledCrateTileEntity)) return ItemStack.EMPTY;
ItemStack stack = new ItemStack(this, 1);
NBTTagCompound inventory_nbt = new NBTTagCompound();
ItemStackHelper.saveAllItems(inventory_nbt, ((LabeledCrateTileEntity)te).stacks_, false);
if(!inventory_nbt.isEmpty()) {
NBTTagCompound nbt = new NBTTagCompound();
nbt.setTag("inventory", inventory_nbt);
stack.setTagCompound(nbt);
}
return stack;
}
@Override
public boolean removedByPlayer(IBlockState state, World world, BlockPos pos, EntityPlayer player, boolean willHarvest)
{
if(world.isRemote) return true;
final ItemStack stack = itemize_with_inventory(world, pos);
if(stack != ItemStack.EMPTY) {
world.spawnEntity(new EntityItem(world, pos.getX()+0.5, pos.getY()+0.5, pos.getZ()+0.5, stack));
world.setBlockToAir(pos);
world.removeTileEntity(pos);
return false;
} else {
return super.removedByPlayer(state, world, pos, player, willHarvest);
}
}
@Override
public void onBlockExploded(World world, BlockPos pos, Explosion explosion)
{
if(world.isRemote) return;
TileEntity te = world.getTileEntity(pos);
if(!(te instanceof LabeledCrateTileEntity)) return;
for(ItemStack stack: ((LabeledCrateTileEntity)te).stacks_) {
if(!stack.isEmpty()) world.spawnEntity(new EntityItem(world, pos.getX(), pos.getY(), pos.getZ(), stack));
}
((LabeledCrateTileEntity)te).reset();
super.onBlockExploded(world, pos, explosion);
}
@Override
@SuppressWarnings("deprecation")
public boolean hasComparatorInputOverride(IBlockState state)
{ return true; }
@Override
@SuppressWarnings("deprecation")
public int getComparatorInputOverride(IBlockState blockState, World world, BlockPos pos)
{ return Container.calcRedstone(world.getTileEntity(pos)); }
//--------------------------------------------------------------------------------------------------------------------
// GUI
//--------------------------------------------------------------------------------------------------------------------
@SideOnly(Side.CLIENT)
private static class BGui extends GuiContainer
{
private final LabeledCrateTileEntity te;
public BGui(InventoryPlayer playerInventory, World world, BlockPos pos, LabeledCrateTileEntity te)
{
super(new BContainer(playerInventory, world, pos, te));
this.te = te;
xSize = 213;
ySize = 206;
}
@Override
public void initGui()
{ super.initGui(); }
@Override
public void drawScreen(int mouseX, int mouseY, float partialTicks)
{
drawDefaultBackground();
super.drawScreen(mouseX, mouseY, partialTicks);
renderHoveredToolTip(mouseX, mouseY);
}
@Override
protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY)
{
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
mc.getTextureManager().bindTexture(new ResourceLocation(ModEngineersDecor.MODID, "textures/gui/labeled_crate_gui.png"));
final int x0=guiLeft, y0=guiTop, w=xSize, h=ySize;
drawTexturedModalRect(x0, y0, 0, 0, w, h);
}
}
//--------------------------------------------------------------------------------------------------------------------
// Tile entity
//--------------------------------------------------------------------------------------------------------------------
public static class LabeledCrateTileEntity extends TileEntity implements ISidedInventory
{
public static final int NUM_OF_FIELDS = 1;
public static final int NUM_OF_SLOTS = 55;
public static final int ITEMFRAME_SLOTNO = 54;
// LabeledCrateTileEntity --------------------------------------------------------------------------
protected NonNullList<ItemStack> stacks_ = NonNullList.<ItemStack>withSize(NUM_OF_SLOTS, ItemStack.EMPTY);
public LabeledCrateTileEntity()
{ reset(); }
protected void reset()
{ stacks_ = NonNullList.<ItemStack>withSize(NUM_OF_SLOTS, ItemStack.EMPTY); }
public void readnbt(NBTTagCompound compound)
{
NonNullList<ItemStack> stacks = NonNullList.<ItemStack>withSize(NUM_OF_SLOTS, ItemStack.EMPTY);
ItemStackHelper.loadAllItems(compound, stacks);
while(stacks.size() < NUM_OF_SLOTS) stacks.add(ItemStack.EMPTY);
stacks_ = stacks;
}
protected void writenbt(NBTTagCompound compound)
{ ItemStackHelper.saveAllItems(compound, stacks_); }
public ItemStack getItemFrameStack()
{ return (stacks_.size() > ITEMFRAME_SLOTNO)?(stacks_.get(ITEMFRAME_SLOTNO)):(ItemStack.EMPTY); }
// TileEntity ------------------------------------------------------------------------------
@Override
public boolean shouldRefresh(World world, BlockPos pos, IBlockState os, IBlockState ns)
{ return (os.getBlock()!=ns.getBlock())||(!(ns.getBlock() instanceof BlockDecorLabeledCrate));}
@Override
public void readFromNBT(NBTTagCompound compound)
{ super.readFromNBT(compound); readnbt(compound); }
@Override
public NBTTagCompound writeToNBT(NBTTagCompound compound)
{ super.writeToNBT(compound); writenbt(compound); return compound; }
@Override
public NBTTagCompound getUpdateTag()
{ NBTTagCompound nbt = super.getUpdateTag(); writenbt(nbt); return nbt; }
@Override
@Nullable
public SPacketUpdateTileEntity getUpdatePacket()
{ return new SPacketUpdateTileEntity(pos, 1, getUpdateTag()); }
@Override
public void onDataPacket(NetworkManager net, SPacketUpdateTileEntity pkt) // on client
{ super.readFromNBT(pkt.getNbtCompound()); readnbt(pkt.getNbtCompound()); super.onDataPacket(net, pkt); }
@Override
public void handleUpdateTag(NBTTagCompound tag) // on client
{ readFromNBT(tag); }
// INameable ---------------------------------------------------------------------------
@Override
public String getName()
{ final Block block = getBlockType(); return (block!=null)?(block.getTranslationKey()+".name"):(""); }
@Override
public boolean hasCustomName()
{ return false; }
@Override
public ITextComponent getDisplayName()
{ return new TextComponentTranslation(getName(), new Object[0]); }
// IInventory ------------------------------------------------------------------------------
@Override
public int getSizeInventory()
{ return stacks_.size(); }
@Override
public boolean isEmpty()
{ for(ItemStack stack : stacks_) { if(!stack.isEmpty()) return false; } return true; }
@Override
public ItemStack getStackInSlot(int index)
{ return ((index >= 0)&&(index < getSizeInventory()))?stacks_.get(index):ItemStack.EMPTY; }
@Override
public ItemStack decrStackSize(int index, int count)
{ return ItemStackHelper.getAndSplit(stacks_, index, count); }
@Override
public ItemStack removeStackFromSlot(int index)
{ return ItemStackHelper.getAndRemove(stacks_, index); }
@Override
public void setInventorySlotContents(int index, ItemStack stack)
{
if(stack.getCount() > getInventoryStackLimit()) stack.setCount(getInventoryStackLimit());
stacks_.set(index, stack);
markDirty();
if(!getWorld().isRemote) {
// This should result in sending TE data (getUpdateTag etc) to the client for the TER.
IBlockState state = world.getBlockState(getPos());
getWorld().notifyBlockUpdate(getPos(), state, state, 2|16|32);
}
}
@Override
public int getInventoryStackLimit()
{ return 64; }
@Override
public void markDirty()
{ super.markDirty(); }
@Override
public boolean isUsableByPlayer(EntityPlayer player)
{ return getPos().distanceSq(player.getPosition()) < 36; }
@Override
public void openInventory(EntityPlayer player)
{}
@Override
public void closeInventory(EntityPlayer player)
{ markDirty(); }
@Override
public boolean isItemValidForSlot(int index, ItemStack stack)
{ return (index!=ITEMFRAME_SLOTNO); }
@Override
public void clear()
{ stacks_.clear(); }
// Fields -----------------------------------------------------------------------------------------------
@Override
public int getField(int id)
{ return 0; }
@Override
public void setField(int id, int value)
{}
@Override
public int getFieldCount()
{ return 0; }
// ISidedInventory ----------------------------------------------------------------------------
private static final int[] SIDED_INV_SLOTS;
static {
SIDED_INV_SLOTS = new int[LabeledCrateTileEntity.NUM_OF_SLOTS-1];
for(int i = 0; i < SIDED_INV_SLOTS.length; ++i) SIDED_INV_SLOTS[i] = i;
}
@Override
public int[] getSlotsForFace(EnumFacing side)
{ return SIDED_INV_SLOTS; }
@Override
public boolean canInsertItem(int index, ItemStack stack, EnumFacing direction)
{ return true; }
@Override
public boolean canExtractItem(int index, ItemStack stack, EnumFacing direction)
{ return true; }
// IItemHandler --------------------------------------------------------------------------------
protected static class BItemHandler implements IItemHandler
{
private LabeledCrateTileEntity te;
BItemHandler(LabeledCrateTileEntity te)
{
this.te = te;
}
@Override
public int getSlots()
{
return ITEMFRAME_SLOTNO;
} // iframe slot is the last
@Override
public int getSlotLimit(int index)
{
return te.getInventoryStackLimit();
}
@Override
public boolean isItemValid(int slot, @Nonnull ItemStack stack)
{
return true;
}
@Override
@Nonnull
public ItemStack insertItem(int slotno, @Nonnull ItemStack stack, boolean simulate)
{
if(stack.isEmpty()) return ItemStack.EMPTY;
if((slotno < 0)||((slotno >= NUM_OF_SLOTS))||((slotno==ITEMFRAME_SLOTNO))) return ItemStack.EMPTY;
ItemStack slotstack = getStackInSlot(slotno);
if(!slotstack.isEmpty()) {
if(slotstack.getCount() >= Math.min(slotstack.getMaxStackSize(), getSlotLimit(slotno))) return stack;
if(!ItemHandlerHelper.canItemStacksStack(stack, slotstack)) return stack;
if(!te.canInsertItem(slotno, stack, EnumFacing.UP)||(!te.isItemValidForSlot(slotno, stack))) return stack;
int n = Math.min(stack.getMaxStackSize(), getSlotLimit(slotno))-slotstack.getCount();
if(stack.getCount() <= n) {
if(!simulate) {
ItemStack copy = stack.copy();
copy.grow(slotstack.getCount());
te.setInventorySlotContents(slotno, copy);
}
return ItemStack.EMPTY;
}
else {
stack = stack.copy();
if(!simulate) {
ItemStack copy = stack.splitStack(n);
copy.grow(slotstack.getCount());
te.setInventorySlotContents(slotno, copy);
return stack;
}
else {
stack.shrink(n);
return stack;
}
}
}
else {
if(!te.canInsertItem(slotno, stack, EnumFacing.UP)||(!te.isItemValidForSlot(slotno, stack))) return stack;
int n = Math.min(stack.getMaxStackSize(), getSlotLimit(slotno));
if(n < stack.getCount()) {
stack = stack.copy();
if(!simulate) {
te.setInventorySlotContents(slotno, stack.splitStack(n));
return stack;
}
else {
stack.shrink(n);
return stack;
}
}
else {
if(!simulate) te.setInventorySlotContents(slotno, stack);
return ItemStack.EMPTY;
}
}
}
@Override
@Nonnull
public ItemStack extractItem(int index, int amount, boolean simulate)
{
if((index < 0)||((index >= NUM_OF_SLOTS))||((index==ITEMFRAME_SLOTNO))) return ItemStack.EMPTY;
if(!simulate) return ItemStackHelper.getAndSplit(te.stacks_, index, amount);
ItemStack stack = te.stacks_.get(index).copy();
if(stack.getCount() > amount) stack.setCount(amount);
return stack;
}
@Override
@Nonnull
public ItemStack getStackInSlot(int index)
{
return te.getStackInSlot(index);
}
}
// Capability export ----------------------------------------------------------------------------
private final IItemHandler item_handler_ = new BItemHandler(this);
@Override
public boolean hasCapability(Capability<?> cap, EnumFacing facing)
{
return (cap==CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)||super.hasCapability(cap, facing);
}
@Override
@SuppressWarnings("unchecked")
@Nullable
public <T> T getCapability(Capability<T> capability, @Nullable EnumFacing facing)
{
if(capability==CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) return (T)item_handler_;
return super.getCapability(capability, facing);
}
}
//--------------------------------------------------------------------------------------------------------------------
// Container
//--------------------------------------------------------------------------------------------------------------------
public static class BContainer extends Container
{
//------------------------------------------------------------------------------------------------------------------
private static final int PLAYER_INV_START_SLOTNO = LabeledCrateTileEntity.NUM_OF_SLOTS;
private final World world;
private final BlockPos pos;
private final EntityPlayer player;
private final LabeledCrateTileEntity te;
//------------------------------------------------------------------------------------------------------------------
public BContainer(InventoryPlayer playerInventory, World world, BlockPos pos, LabeledCrateTileEntity te)
{
this.player = playerInventory.player;
this.world = world;
this.pos = pos;
this.te = te;
int i=-1;
// storage slots (stacks 0 to 53)
for(int y=0; y<6; ++y) {
for(int x=0; x<9; ++x) {
int xpos = 28+x*18, ypos = 10+y*18;
addSlotToContainer(new Slot(te, ++i, xpos, ypos));
}
}
// picture frame slot (54)
addSlotToContainer(new Slot(te, ++i, 191, 100) {
@Override public int getSlotStackLimit(){return 1;}
});
// player slots
for(int x=0; x<9; ++x) {
addSlotToContainer(new Slot(playerInventory, x, 28+x*18, 183)); // player slots: 0..8
}
for(int y=0; y<3; ++y) {
for(int x=0; x<9; ++x) {
addSlotToContainer(new Slot(playerInventory, x+y*9+9, 28+x*18, 125+y*18)); // player slots: 9..35
}
}
}
@Override
public void addListener(IContainerListener listener)
{ super.addListener(listener); listener.sendAllWindowProperties(this, te); }
@Override
public void detectAndSendChanges()
{ super.detectAndSendChanges(); }
@Override
@SideOnly(Side.CLIENT)
public void updateProgressBar(int id, int data)
{ te.setField(id, data); }
@Override
public boolean canInteractWith(EntityPlayer player)
{ return (world.getBlockState(pos).getBlock() instanceof BlockDecorLabeledCrate) && (player.getDistanceSq(pos) <= 64); }
@Override
public boolean canMergeSlot(ItemStack stack, Slot slot)
{ return (slot.getSlotStackLimit() > 1); }
@Override
public void onContainerClosed(EntityPlayer player)
{ super.onContainerClosed(player); }
@Override
public ItemStack transferStackInSlot(EntityPlayer player, int index)
{
Slot slot = getSlot(index);
if((slot==null) || (!slot.getHasStack())) return ItemStack.EMPTY;
ItemStack slot_stack = slot.getStack();
ItemStack transferred = slot_stack.copy();
if((index>=0) && (index<PLAYER_INV_START_SLOTNO)) {
// Crate slots
if(!mergeItemStack(slot_stack, PLAYER_INV_START_SLOTNO, PLAYER_INV_START_SLOTNO+36, false)) return ItemStack.EMPTY;
} else if((index >= PLAYER_INV_START_SLOTNO) && (index <= PLAYER_INV_START_SLOTNO+36)) {
// Player slot
if(!mergeItemStack(slot_stack, 0, PLAYER_INV_START_SLOTNO-1, false)) return ItemStack.EMPTY;
} else {
// invalid slot
return ItemStack.EMPTY;
}
if(slot_stack.isEmpty()) {
slot.putStack(ItemStack.EMPTY);
} else {
slot.onSlotChanged();
}
if(slot_stack.getCount() == transferred.getCount()) return ItemStack.EMPTY;
slot.onTake(player, slot_stack);
return transferred;
}
}
//--------------------------------------------------------------------------------------------------------------------
// ModEngineersDecor.GuiHandler connectors
//--------------------------------------------------------------------------------------------------------------------
public static Object getServerGuiElement(final EntityPlayer player, final World world, final BlockPos pos, final TileEntity te)
{ return (te instanceof LabeledCrateTileEntity) ? (new BContainer(player.inventory, world, pos, (LabeledCrateTileEntity)te)) : null; }
public static Object getClientGuiElement(final EntityPlayer player, final World world, final BlockPos pos, final TileEntity te)
{ return (te instanceof LabeledCrateTileEntity) ? (new BGui(player.inventory, world, pos, (LabeledCrateTileEntity)te)) : null; }
}

View file

@ -1,142 +0,0 @@
/*
* @file BlockDecorLadder.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Ladder block. The implementation is based on the vanilla
* net.minecraft.block.BlockLadder. Minor changes to enable
* later configuration (for block list based construction
* time configuration), does not drop when the block behind
* is broken, etc.
*/
package wile.engineersdecor.blocks;
import net.minecraft.block.BlockLadder;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.EnumPushReaction;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.entity.MoverType;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.MathHelper;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import wile.engineersdecor.ModEngineersDecor;
import wile.engineersdecor.detail.ModAuxiliaries;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.BlockFaceShape;
import net.minecraft.block.state.IBlockState;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.util.*;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
public class BlockDecorLadder extends BlockLadder
{
//--------------------------------------------------------------------------------------------------------------------
// Config
//--------------------------------------------------------------------------------------------------------------------
protected static final double ladder_speed = 0.7;
protected static boolean with_ladder_speed_boost = true;
public static final void on_config(boolean without_ladder_speed_boost)
{
with_ladder_speed_boost = !without_ladder_speed_boost;
}
//--------------------------------------------------------------------------------------------------------------------
// Block
//--------------------------------------------------------------------------------------------------------------------
protected static final AxisAlignedBB EDLADDER_SOUTH_AABB = ModAuxiliaries.getPixeledAABB(3, 0, 0, 13, 16, 3);
protected static final AxisAlignedBB EDLADDER_EAST_AABB = ModAuxiliaries.getRotatedAABB(EDLADDER_SOUTH_AABB, EnumFacing.EAST, false);
protected static final AxisAlignedBB EDLADDER_WEST_AABB = ModAuxiliaries.getRotatedAABB(EDLADDER_SOUTH_AABB, EnumFacing.WEST, false);
protected static final AxisAlignedBB EDLADDER_NORTH_AABB = ModAuxiliaries.getRotatedAABB(EDLADDER_SOUTH_AABB, EnumFacing.NORTH, false);
public BlockDecorLadder(@Nonnull String registryName, long config, @Nullable Material material, float hardness, float resistance, @Nullable SoundType sound)
{
super();
setCreativeTab(ModEngineersDecor.CREATIVE_TAB_ENGINEERSDECOR);
setRegistryName(ModEngineersDecor.MODID, registryName);
setTranslationKey(ModEngineersDecor.MODID + "." + registryName);
setTickRandomly(false);
setHardness((hardness > 0) ? hardness : 5.0f);
setResistance((resistance > 0) ? resistance : 10.0f);
setSoundType((sound==null) ? SoundType.STONE : sound);
setLightOpacity(0);
}
@Override
@SideOnly(Side.CLIENT)
public void addInformation(ItemStack stack, @Nullable World world, List<String> tooltip, ITooltipFlag flag)
{ ModAuxiliaries.Tooltip.addInformation(stack, world, tooltip, flag, true); }
@Override
@SuppressWarnings("deprecation")
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos)
{
switch ((EnumFacing)state.getValue(FACING)) {
case NORTH: return EDLADDER_NORTH_AABB;
case SOUTH: return EDLADDER_SOUTH_AABB;
case WEST: return EDLADDER_WEST_AABB;
default: return EDLADDER_EAST_AABB;
}
}
@Override
public boolean canSpawnInBlock()
{ return false; }
@Override
public boolean canCreatureSpawn(IBlockState state, IBlockAccess world, BlockPos pos, net.minecraft.entity.EntityLiving.SpawnPlacementType type)
{ return false; }
@Override
@SuppressWarnings("deprecation")
public EnumPushReaction getPushReaction(IBlockState state)
{ return EnumPushReaction.NORMAL; }
@Override
public boolean canPlaceBlockOnSide(World world, BlockPos pos, EnumFacing side)
{ return canAttachTo(world, pos.west(), side) || canAttachTo(world, pos.east(), side) || canAttachTo(world, pos.north(), side) || canAttachTo(world, pos.south(), side); }
@Override
public IBlockState getStateForPlacement(World world, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer, EnumHand hand)
{
if(facing.getAxis().isHorizontal() && canAttachTo(world, pos.offset(facing.getOpposite()), facing)) return this.getDefaultState().withProperty(FACING, facing);
for(EnumFacing e:EnumFacing.Plane.HORIZONTAL) {
if(this.canAttachTo(world, pos.offset(e.getOpposite()), e)) return this.getDefaultState().withProperty(FACING, e);
}
return this.getDefaultState();
}
private boolean canAttachTo(World world, BlockPos pos, EnumFacing side)
{
final IBlockState state = world.getBlockState(pos);
return (!isExceptBlockForAttachWithPiston(state.getBlock())) && (state.getBlockFaceShape(world, pos, side) == BlockFaceShape.SOLID);
}
// Player update event, forwarded from the main mod instance.
public static void onPlayerUpdateEvent(final EntityPlayer player)
{
if(!with_ladder_speed_boost) return;
if(!player.isOnLadder() || (player.isSneaking()) || (player.isSpectator())) return;
if((Math.abs(player.motionY) < 0.1) || (Math.abs(player.motionY) > ladder_speed) || ((player.getLookVec().y > 0) != (player.motionY > 0))) return;
if(Math.abs(player.getLookVec().y) < 0.9) return;
final BlockPos pos = new BlockPos(player.posX, player.posY, player.posZ);
if(!(player.world.getBlockState(pos).getBlock() instanceof BlockDecorLadder)) return;
player.fallDistance = 0;
player.motionY = (player.motionY < -0.25) ? (-ladder_speed) : ((player.motionY > 0.25) ? (ladder_speed) : (player.motionY));
player.motionX = MathHelper.clamp(player.motionX, -0.05, 0.05);
player.motionZ = MathHelper.clamp(player.motionZ, -0.05, 0.05);
player.move(MoverType.PLAYER, player.motionX, player.motionY, player.motionZ);
}
}

View file

@ -1,577 +0,0 @@
/*
* @file BlockDecorMilker.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Frequently attracts and milks nearby cows
*/
package wile.engineersdecor.blocks;
import wile.engineersdecor.ModEngineersDecor;
import net.minecraft.entity.passive.EntityCow;
import net.minecraft.init.SoundEvents;
import net.minecraft.block.state.IBlockState;
import net.minecraft.block.state.BlockFaceShape;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraft.block.properties.PropertyBool;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraft.world.Explosion;
import net.minecraft.entity.MoverType;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.init.Items;
import net.minecraft.item.*;
import net.minecraft.util.*;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.energy.CapabilityEnergy;
import net.minecraftforge.energy.IEnergyStorage;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper;
import net.minecraftforge.items.wrapper.PlayerMainInvWrapper;
import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidRegistry;
import net.minecraftforge.fluids.FluidUtil;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.fluids.capability.IFluidTankProperties;
import wile.engineersdecor.detail.ExtItems;
import wile.engineersdecor.detail.ItemHandling;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Map.Entry;
import java.util.UUID;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class BlockDecorMilker extends BlockDecorDirectedHorizontal
{
//--------------------------------------------------------------------------------------------------------------------
// Config
//--------------------------------------------------------------------------------------------------------------------
public static final int BUCKET_SIZE = 1000;
public static final int TICK_INTERVAL = 80;
public static final int PROCESSING_TICK_INTERVAL = 20;
public static final int TANK_CAPACITY = BUCKET_SIZE * 12;
public static final int MAX_MILKING_TANK_LEVEL = TANK_CAPACITY-500;
public static final int FILLED_INDICATION_THRESHOLD = BUCKET_SIZE;
public static final int MAX_ENERGY_BUFFER = 16000;
public static final int MAX_ENERGY_TRANSFER = 512;
public static final int DEFAULT_ENERGY_CONSUMPTION = 0;
private static FluidStack milk_fluid_ = new FluidStack(FluidRegistry.WATER, 0);
private static HashMap<ItemStack, ItemStack> milk_containers_ = new HashMap<>();
private static int energy_consumption = DEFAULT_ENERGY_CONSUMPTION;
public static void on_config(int energy_consumption_per_tick)
{
energy_consumption = MathHelper.clamp(energy_consumption_per_tick, 0, 128);
{
Fluid milk = FluidRegistry.getFluid("milk");
if(milk != null) milk_fluid_ = new FluidStack(milk, BUCKET_SIZE);
}
{
milk_containers_.put(new ItemStack(Items.BUCKET), new ItemStack(Items.MILK_BUCKET));
if(ExtItems.BOTTLED_MILK_BOTTLE_DRINKLABLE!=null) milk_containers_.put(new ItemStack(Items.GLASS_BOTTLE), new ItemStack(ExtItems.BOTTLED_MILK_BOTTLE_DRINKLABLE));
}
ModEngineersDecor.logger.info(
"Config milker energy consumption:" + energy_consumption + "rf/t"
+ ((milk_fluid_==null)?"":" [milk fluid available]")
+ ((ExtItems.BOTTLED_MILK_BOTTLE_DRINKLABLE==null)?"":" [bottledmilk mod available]")
);
}
//--------------------------------------------------------------------------------------------------------------------
// Block
//--------------------------------------------------------------------------------------------------------------------
public static final PropertyBool FILLED = PropertyBool.create("filled");
public static final PropertyBool ACTIVE = PropertyBool.create("active");
public BlockDecorMilker(@Nonnull String registryName, long config, @Nullable Material material, float hardness, float resistance, @Nullable SoundType sound, @Nonnull AxisAlignedBB unrotatedAABB)
{
super(registryName, config, material, hardness, resistance, sound, unrotatedAABB);
setLightOpacity(0);
}
@Override
protected BlockStateContainer createBlockState()
{ return new BlockStateContainer(this, FACING, FILLED, ACTIVE); }
@Override
public IBlockState getStateFromMeta(int meta)
{ return super.getStateFromMeta(meta).withProperty(FILLED, ((meta & 0x4)!=0)).withProperty(ACTIVE, ((meta & 0x8)!=0)) ; }
@Override
public int getMetaFromState(IBlockState state)
{ return super.getMetaFromState(state) | (state.getValue(FILLED)?0x4:0x00) | (state.getValue(ACTIVE)?0x8:0x00); }
@Override
public IBlockState getStateForPlacement(World world, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer, EnumHand hand)
{ return super.getStateForPlacement(world, pos, facing, hitX, hitY, hitZ, meta, placer, hand).withProperty(FILLED, false).withProperty(ACTIVE, false); }
@Override
public BlockFaceShape getBlockFaceShape(IBlockAccess world, IBlockState state, BlockPos pos, EnumFacing face)
{ return BlockFaceShape.UNDEFINED; }
@Override
public boolean isPassable(IBlockAccess worldIn, BlockPos pos)
{ return false; }
@Override
@SuppressWarnings("deprecation")
public boolean hasComparatorInputOverride(IBlockState state)
{ return true; }
@Override
@SuppressWarnings("deprecation")
public int getComparatorInputOverride(IBlockState state, World world, BlockPos pos)
{
BTileEntity te = getTe(world, pos);
return (te==null) ? 0 : MathHelper.clamp((16 * te.fluid_level())/TANK_CAPACITY, 0, 15);
}
@Override
public boolean hasTileEntity(IBlockState state)
{ return true; }
@Nullable
public TileEntity createTileEntity(World world, IBlockState state)
{ return new BlockDecorMilker.BTileEntity(); }
@Override
public boolean removedByPlayer(IBlockState state, World world, BlockPos pos, EntityPlayer player, boolean willHarvest)
{
if(world.isRemote) return true;
BTileEntity te = getTe(world, pos);
if(te==null) return super.removedByPlayer(state, world, pos, player, willHarvest);
final NBTTagCompound te_nbt = te.destroy_getnbt();
ItemStack stack = new ItemStack(this, 1);
if((te_nbt!=null) && !te_nbt.isEmpty()) {
NBTTagCompound nbt = stack.getTagCompound();
if(nbt == null) nbt = new NBTTagCompound();
nbt.setTag("tedata", te_nbt);
stack.setTagCompound(nbt);
}
world.spawnEntity(new EntityItem(world, pos.getX()+0.5, pos.getY()+0.5, pos.getZ()+0.5, stack));
world.setBlockToAir(pos);
world.removeTileEntity(pos);
return false;
}
@Override
public void onBlockExploded(World world, BlockPos pos, Explosion explosion)
{ super.onBlockExploded(world, pos, explosion); } // currently nothing to do here
@Override
public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
{
if(world.isRemote) return true;
BTileEntity te = getTe(world, pos);
if(te==null) return true;
final ItemStack in_stack = player.getHeldItem(hand);
final ItemStack out_stack = BTileEntity.milk_filled_container_item(in_stack);
if(out_stack.isEmpty()) return FluidUtil.interactWithFluidHandler(player, hand, te.fluid_handler());
boolean drained = false;
IItemHandler player_inventory = new PlayerMainInvWrapper(player.inventory);
if(te.fluid_level() >= BUCKET_SIZE) {
final ItemStack insert_stack = out_stack.copy();
ItemStack remainder = ItemHandlerHelper.insertItemStacked(player_inventory, insert_stack, false);
if(remainder.getCount() < insert_stack.getCount()) {
te.drain(BUCKET_SIZE);
in_stack.shrink(1);
drained = true;
if(remainder.getCount() > 0) {
final EntityItem ei = new EntityItem(world, player.posX, player.posY + 0.5, player.posZ, remainder);
ei.setPickupDelay(40);
ei.motionX = 0;
ei.motionZ = 0;
world.spawnEntity(ei);
}
}
}
if(drained) {
world.playSound(null, pos, SoundEvents.ITEM_BUCKET_FILL, SoundCategory.BLOCKS, 0.8f, 1f);
}
return true;
}
@Nullable
private BTileEntity getTe(World world, BlockPos pos)
{ final TileEntity te=world.getTileEntity(pos); return (!(te instanceof BTileEntity)) ? (null) : ((BTileEntity)te); }
//--------------------------------------------------------------------------------------------------------------------
// Tile entity
//--------------------------------------------------------------------------------------------------------------------
public static class BTileEntity extends TileEntity implements ITickable, ICapabilityProvider, IEnergyStorage
{
private static final EnumFacing FLUID_TRANSFER_DIRECTRIONS[] = {EnumFacing.DOWN,EnumFacing.EAST,EnumFacing.SOUTH,EnumFacing.WEST,EnumFacing.NORTH};
private enum MilkingState { IDLE, PICKED, COMING, POSITIONING, MILKING, LEAVING, WAITING }
private int tick_timer_;
private int energy_stored_;
private int tank_level_ = 0;
private UUID tracked_cow_ = null;
private MilkingState state_ = MilkingState.IDLE;
private int state_timeout_ = 0;
private int state_timer_ = 0;
private BlockPos tracked_cow_original_position_ = null;
public BTileEntity()
{ reset(); }
public void reset()
{
tank_level_ = 0;
energy_stored_ = 0;
tick_timer_ = 0;
tracked_cow_ = null;
state_ = MilkingState.IDLE;
state_timeout_ = 0;
}
public NBTTagCompound destroy_getnbt()
{
final UUID cowuid = tracked_cow_;
NBTTagCompound nbt = new NBTTagCompound();
writenbt(nbt, false); reset();
if(cowuid == null) return nbt;
world.getEntitiesWithinAABB(EntityCow.class, new AxisAlignedBB(pos).grow(16, 16, 16), e->e.getPersistentID().equals(cowuid)).forEach(e->e.setNoAI(false));
return nbt;
}
public void readnbt(NBTTagCompound nbt, boolean update_packet)
{
tank_level_ = nbt.getInteger("tank");
energy_stored_ = nbt.getInteger("energy");
}
protected void writenbt(NBTTagCompound nbt, boolean update_packet)
{
if(tank_level_ > 0) nbt.setInteger("tank", tank_level_);
if(energy_stored_ > 0) nbt.setInteger("energy", energy_stored_ );
}
private IFluidHandler fluid_handler()
{ return fluid_handler_; }
private int fluid_level()
{ return MathHelper.clamp(tank_level_, 0, TANK_CAPACITY); }
private void drain(int amount)
{ tank_level_ = MathHelper.clamp(tank_level_-BUCKET_SIZE, 0, TANK_CAPACITY); markDirty(); }
// TileEntity ------------------------------------------------------------------------------
@Override
public boolean shouldRefresh(World world, BlockPos pos, IBlockState os, IBlockState ns)
{ return (os.getBlock() != ns.getBlock()) || (!(ns.getBlock() instanceof BlockDecorMilker)); }
@Override
public void readFromNBT(NBTTagCompound nbt)
{ super.readFromNBT(nbt); readnbt(nbt, false); }
@Override
public NBTTagCompound writeToNBT(NBTTagCompound nbt)
{ super.writeToNBT(nbt); writenbt(nbt, false); return nbt; }
// IEnergyStorage ----------------------------------------------------------------------------
@Override
public boolean canExtract()
{ return false; }
@Override
public boolean canReceive()
{ return true; }
@Override
public int getMaxEnergyStored()
{ return MAX_ENERGY_BUFFER; }
@Override
public int getEnergyStored()
{ return energy_stored_; }
@Override
public int extractEnergy(int maxExtract, boolean simulate)
{ return 0; }
@Override
public int receiveEnergy(int maxReceive, boolean simulate)
{
if(energy_stored_ >= MAX_ENERGY_BUFFER) return 0;
int n = Math.min(maxReceive, (MAX_ENERGY_BUFFER - energy_stored_));
if(n > MAX_ENERGY_TRANSFER) n = MAX_ENERGY_TRANSFER;
if(!simulate) {energy_stored_ += n; markDirty(); }
return n;
}
// IFluidHandler / IFluidTankProperties ---------------------------------------------------------------------
private static class BFluidHandler implements IFluidHandler, IFluidTankProperties
{
private final BTileEntity te;
private final IFluidTankProperties[] props_ = {this};
BFluidHandler(BTileEntity te) { this.te=te; }
@Override @Nullable public FluidStack getContents() { return new FluidStack(milk_fluid_, te.fluid_level()); }
@Override public IFluidTankProperties[] getTankProperties() { return props_; }
@Override public int fill(FluidStack resource, boolean doFill) { return 0; }
@Override public int getCapacity() { return TANK_CAPACITY; }
@Override public boolean canFill() { return false; }
@Override public boolean canDrain() { return (milk_fluid_.amount > 0); }
@Override public boolean canFillFluidType(FluidStack fs) { return false; }
@Override public boolean canDrainFluidType(FluidStack fs) { return fs.isFluidEqual(milk_fluid_); }
@Override @Nullable public FluidStack drain(FluidStack resource, boolean doDrain)
{ return (!resource.isFluidEqual(milk_fluid_)) ? (null) : drain(resource.amount, doDrain); }
@Override @Nullable public FluidStack drain(int maxDrain, boolean doDrain)
{
if(te.fluid_level() <= 0) return null;
FluidStack fs = milk_fluid_.copy();
fs.amount = Math.min(fs.amount, te.fluid_level());
if(doDrain) te.tank_level_ -= fs.amount;
return fs;
}
}
private final BFluidHandler fluid_handler_ = new BFluidHandler(this);
// ICapabilityProvider ---------------------------------------------------------------------------
@Override
public boolean hasCapability(Capability<?> cap, EnumFacing facing)
{
if((cap==CapabilityEnergy.ENERGY) && (energy_consumption>0)) return true;
if((cap==CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) && (milk_fluid_.amount>0)) return true;
return super.hasCapability(cap, facing);
}
@Override
@SuppressWarnings("unchecked")
@Nullable
public <T> T getCapability(Capability<T> capability, @Nullable EnumFacing facing)
{
if(capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) {
return (T)fluid_handler_;
} else if(capability == CapabilityEnergy.ENERGY) {
return (T)this;
} else {
return super.getCapability(capability, facing);
}
}
// ITickable ------------------------------------------------------------------------------------
private void log(String s)
{} // may be enabled with config, for dev was println
private static ItemStack milk_filled_container_item(ItemStack stack)
{ return milk_containers_.entrySet().stream().filter(e->e.getKey().isItemEqual(stack)).map(Map.Entry::getValue).findFirst().orElse(ItemStack.EMPTY); }
private void fill_adjacent_inventory_item_containers(EnumFacing block_facing)
{
// Check inventory existence, back to down is preferred, otherwise sort back into same inventory.
IItemHandler src = ItemHandling.itemhandler(world, pos.offset(block_facing), block_facing.getOpposite());
IItemHandler dst = ItemHandling.itemhandler(world, pos.down(), EnumFacing.UP);
if(src==null) { src = dst; } else if(dst==null) { dst = src; }
if((src==null) || (dst==null)) return;
while((tank_level_ >= BUCKET_SIZE)) {
boolean inserted = false;
for(Entry<ItemStack,ItemStack> e:milk_containers_.entrySet()) {
if(ItemHandling.extract(src, e.getKey(), 1, true).isEmpty()) continue;
if(!ItemHandling.insert(dst, e.getValue().copy(), false).isEmpty()) continue;
ItemHandling.extract(src, e.getKey(), 1, false);
tank_level_ -= BUCKET_SIZE;
inserted = true;
}
if(!inserted) break;
}
}
private boolean milking_process()
{
if((tracked_cow_ == null) && (fluid_level() >= MAX_MILKING_TANK_LEVEL)) return false; // nothing to do
final EnumFacing facing = world.getBlockState(getPos()).getValue(FACING).getOpposite();
EntityCow cow = null;
{
AxisAlignedBB aabb = new AxisAlignedBB(pos.offset(facing, 3)).grow(4, 2, 4);
final List<EntityCow> cows = world.getEntitiesWithinAABB(EntityCow.class, aabb,
e->(((tracked_cow_==null) && (!e.isChild() && !e.isInLove()))||(e.getPersistentID().equals(tracked_cow_)))
);
if(cows.size() == 1) {
cow = cows.get(0); // tracked or only one
} else if(cows.size() > 1) {
cow = cows.get(world.rand.nextInt(cows.size()-1)); // pick one
}
}
if((state_ != MilkingState.IDLE) && ((state_timeout_ -= PROCESSING_TICK_INTERVAL) <= 0)) { log("Cow motion timeout"); cow = null; }
if((cow == null) || (cow.isDead) || ((tracked_cow_ != null) && (!tracked_cow_.equals(cow.getPersistentID())))) { tracked_cow_ = null; cow = null; }
if(tracked_cow_ == null) state_ = MilkingState.IDLE;
if(cow == null) return false; // retry next cycle
tick_timer_ = PROCESSING_TICK_INTERVAL;
state_timer_ -= PROCESSING_TICK_INTERVAL;
if(state_timer_ > 0) return false;
switch(state_) { // Let's do this the old school FSA sequencing way ...
case IDLE: {
final List<EntityLivingBase> blocking_entities = world.getEntitiesWithinAABB(EntityLivingBase.class, new AxisAlignedBB(pos.offset(facing)).grow(0.5, 0.5, 0.5));
if(blocking_entities.size() > 0) { tick_timer_ = TICK_INTERVAL; return false; } // an entity is blocking the way
if(cow.getLeashed() || cow.isChild() || cow.isInLove() || (!cow.onGround) || cow.isBeingRidden() || cow.isSprinting()) return false;
tracked_cow_ = cow.getPersistentID();
state_ = MilkingState.PICKED;
state_timeout_ = 200;
tracked_cow_original_position_ = cow.getPosition();
log("Idle: Picked cow" + tracked_cow_);
return false;
}
case PICKED: {
if(cow.hasPath()) return false;
BlockPos p = getPos().offset(facing).offset(facing.rotateY());
if(!cow.getNavigator().tryMoveToXYZ(p.getX(), p.getY(), p.getZ(),1.0)) {
log("Picked: No path");
tracked_cow_ = null;
tick_timer_ = TICK_INTERVAL;
return false;
}
state_ = MilkingState.COMING;
state_timeout_ = 300; // 15s should be enough
log("Picked: coming");
return false;
}
case COMING: {
BlockPos p = getPos().offset(facing).offset(facing.rotateY());
if(cow.getPosition().distanceSq(p) > 1) {
if(cow.hasPath()) return false;
if(!cow.getNavigator().tryMoveToXYZ(p.getX(), p.getY(), p.getZ(),1.0)) {
log("Coming: lost path");
tracked_cow_ = null;
tick_timer_ = TICK_INTERVAL;
return false;
} else {
state_timeout_ -= 100;
}
} else {
BlockPos next_p = getPos().offset(facing);
if(!cow.getNavigator().tryMoveToXYZ(next_p.getX(), next_p.getY(), next_p.getZ(), 1.0)) {
log("Coming: No path");
tracked_cow_ = null;
tick_timer_ = TICK_INTERVAL;
return false;
}
log("Coming: position reached");
state_ = MilkingState.POSITIONING;
state_timeout_ = 100; // 5s
}
return false;
}
case POSITIONING: {
BlockPos p = getPos().offset(facing);
if(p.distanceSqToCenter(cow.posX, cow.posY, cow.posZ) > 0.45) {
if(cow.hasPath()) return false;
if(!cow.getNavigator().tryMoveToXYZ(p.getX(), p.getY(), p.getZ(), 1.0)) {
log("Positioning: lost path");
tick_timer_ = TICK_INTERVAL;
} else {
state_timeout_ -= 25;
}
tracked_cow_ = null;
return false;
}
cow.setNoAI(true);
cow.move(MoverType.SELF, p.getX()+0.5-cow.posX, 0,p.getZ()+0.5-cow.posZ);
world.playSound(null, pos, SoundEvents.ENTITY_COW_MILK, SoundCategory.BLOCKS, 0.5f, 1f);
state_timeout_ = 600;
state_ = MilkingState.MILKING;
state_timer_ = 30;
log("Positioning: start milking");
return false;
}
case MILKING: {
tank_level_ = MathHelper.clamp(tank_level_+BUCKET_SIZE, 0, TANK_CAPACITY);
state_timeout_ = 600;
state_ = MilkingState.LEAVING;
state_timer_ = 20;
BlockPos p = (tracked_cow_original_position_ != null) ? (tracked_cow_original_position_) : getPos().offset(facing.rotateYCCW(),2);
cow.setNoAI(false);
cow.getNavigator().tryMoveToXYZ(p.getX(), p.getY(), p.getZ(), 1.0);
log("Milking: done, leave");
return true;
}
case LEAVING: {
BlockPos p = (tracked_cow_original_position_ != null) ? (tracked_cow_original_position_) : getPos().offset(facing.rotateYCCW(),2);
cow.getNavigator().tryMoveToXYZ(p.getX(), p.getY(), p.getZ(), 1.0);
state_timeout_ = 600;
state_timer_ = 500;
tick_timer_ = TICK_INTERVAL;
state_ = MilkingState.WAITING;
log("Leaving: process done");
return true;
}
case WAITING: {
tick_timer_ = TICK_INTERVAL;
return true; // wait for the timeout to kick in until starting with the next.
}
default: {
tracked_cow_ = null;
}
}
return (tracked_cow_ != null);
}
@Override
public void update()
{
if((world.isRemote) || ((--tick_timer_ > 0))) return;
tick_timer_ = TICK_INTERVAL;
final IBlockState block_state = world.getBlockState(pos);
if(!(block_state.getBlock() instanceof BlockDecorMilker)) return;
boolean dirty = false;
if(energy_consumption > 0) {
if(energy_stored_ <= 0) return;
energy_stored_ = MathHelper.clamp(energy_stored_-energy_consumption, 0, MAX_ENERGY_BUFFER);
}
// Track and milk cows
if(milking_process()) dirty = true;
// Fluid transfer
if((milk_fluid_.amount > 0) && (fluid_level() >= BUCKET_SIZE)) {
for(EnumFacing facing: FLUID_TRANSFER_DIRECTRIONS) {
IFluidHandler fh = FluidUtil.getFluidHandler(world, pos.offset(facing), facing.getOpposite());
if(fh == null) continue;
FluidStack fs = milk_fluid_.copy();
fs.amount = BUCKET_SIZE;
int nfilled = MathHelper.clamp(fh.fill(fs, true), 0, BUCKET_SIZE);
if(nfilled <= 0) continue;
tank_level_ -= nfilled;
if(tank_level_ < 0) tank_level_ = 0;
dirty = true;
break;
}
}
// Adjacent inventory update, only done just after milking to prevent waste of server cpu.
if(dirty && (fluid_level() >= BUCKET_SIZE)) {
fill_adjacent_inventory_item_containers(block_state.getValue(FACING));
}
// State update
IBlockState new_state = block_state.withProperty(FILLED, fluid_level()>=FILLED_INDICATION_THRESHOLD).withProperty(ACTIVE, state_==MilkingState.MILKING);
if(block_state != new_state) world.setBlockState(pos, new_state,1|2|16);
if(dirty) markDirty();
}
}
}

View file

@ -1,717 +0,0 @@
/*
* @file BlockDecorMineralSmelter.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Small highly insulated stone liquification furnace
* (magmatic phase).
*/
package wile.engineersdecor.blocks;
import wile.engineersdecor.ModEngineersDecor;
import net.minecraft.block.state.BlockFaceShape;
import net.minecraft.block.properties.PropertyInteger;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.Block;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.world.World;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.Explosion;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.init.SoundEvents;
import net.minecraft.item.*;
import net.minecraft.inventory.*;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentTranslation;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.*;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.energy.CapabilityEnergy;
import net.minecraftforge.energy.IEnergyStorage;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.fluids.FluidRegistry;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.fluids.capability.IFluidTankProperties;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
public class BlockDecorMineralSmelter extends BlockDecorDirectedHorizontal
{
public static final int PHASE_MAX = 3;
public static final PropertyInteger PHASE = PropertyInteger.create("phase", 0, PHASE_MAX);
public BlockDecorMineralSmelter(@Nonnull String registryName, long config, @Nullable Material material, float hardness, float resistance, @Nullable SoundType sound, @Nonnull AxisAlignedBB unrotatedAABB)
{
super(registryName, config, material, hardness, resistance, sound, unrotatedAABB);
setLightOpacity(0);
}
@Override
protected BlockStateContainer createBlockState()
{ return new BlockStateContainer(this, FACING, PHASE); }
@Override
public IBlockState getStateFromMeta(int meta)
{ return super.getStateFromMeta(meta).withProperty(PHASE, (meta>>2) & 0x3); }
@Override
public int getMetaFromState(IBlockState state)
{ return super.getMetaFromState(state) | (state.getValue(PHASE)<<2); }
@Override
public IBlockState getStateForPlacement(World world, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer, EnumHand hand)
{ return super.getStateForPlacement(world, pos, facing, hitX, hitY, hitZ, meta, placer, hand).withProperty(PHASE, 0); }
@Override
public BlockFaceShape getBlockFaceShape(IBlockAccess world, IBlockState state, BlockPos pos, EnumFacing face)
{ return BlockFaceShape.SOLID; }
@Override
@SuppressWarnings("deprecation")
public boolean hasComparatorInputOverride(IBlockState state)
{ return true; }
@Override
@SuppressWarnings("deprecation")
public int getComparatorInputOverride(IBlockState state, World world, BlockPos pos)
{ return MathHelper.clamp((state.getValue(PHASE)*5), 0, 15); }
@Override
public boolean hasTileEntity(IBlockState state)
{ return true; }
@Nullable
public TileEntity createTileEntity(World world, IBlockState state)
{ return new BlockDecorMineralSmelter.BTileEntity(); }
@Override
public void onBlockPlacedBy(World world, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack)
{}
@Override
public boolean removedByPlayer(IBlockState state, World world, BlockPos pos, EntityPlayer player, boolean willHarvest)
{
if(world.isRemote) return true;
BTileEntity te = getTe(world, pos);
if(te==null) return super.removedByPlayer(state, world, pos, player, willHarvest);
ItemStack st = ItemStack.EMPTY;
if(!te.getStackInSlot(1).isEmpty()) {
st = te.getStackInSlot(1).copy();
} else if(!te.getStackInSlot(0).isEmpty()) {
st = te.getStackInSlot(0).copy();
}
te.reset_process();
ItemStack stack = new ItemStack(this, 1);
world.spawnEntity(new EntityItem(world, pos.getX()+0.5, pos.getY()+0.5, pos.getZ()+0.5, stack));
world.setBlockToAir(pos);
world.removeTileEntity(pos);
if(!st.isEmpty()) {
st.setCount(1);
world.spawnEntity(new EntityItem(world, pos.getX()+0.5, pos.getY()+0.5, pos.getZ()+0.5, st));
}
return false;
}
@Override
public void onBlockExploded(World world, BlockPos pos, Explosion explosion)
{
if(world.isRemote) return;
BTileEntity te = getTe(world, pos);
if(te==null) return;
te.reset_process();
super.onBlockExploded(world, pos, explosion);
}
@Override
public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
{
if(world.isRemote) return true;
if(player.isSneaking()) return false;
BTileEntity te = getTe(world, pos);
if(te==null) return true;
final ItemStack stack = player.getHeldItem(hand);
boolean dirty = false;
if(te.accepts_lava_container(stack)) {
if(stack.isItemEqualIgnoreDurability(BTileEntity.BUCKET_STACK)) { // check how this works with item capabilities or so
if(te.fluid_level() >= BTileEntity.MAX_BUCKET_EXTRACT_FLUID_LEVEL) {
if(stack.getCount() > 1) {
int target_stack_index = -1;
for(int i=0; i<player.inventory.getSizeInventory(); ++i) {
if(player.inventory.getStackInSlot(i).isEmpty()) {
target_stack_index = i;
break;
}
}
if(target_stack_index >= 0) {
te.reset_process();
stack.shrink(1);
player.setHeldItem(hand, stack);
player.inventory.setInventorySlotContents(target_stack_index, BTileEntity.LAVA_BUCKET_STACK.copy());
world.playSound(null, pos, SoundEvents.ITEM_BUCKET_FILL_LAVA, SoundCategory.BLOCKS, 1f, 1f);
dirty = true;
}
} else {
te.reset_process();
player.setHeldItem(hand, BTileEntity.LAVA_BUCKET_STACK.copy());
world.playSound(null, pos, SoundEvents.ITEM_BUCKET_FILL_LAVA, SoundCategory.BLOCKS, 1f, 1f);
dirty = true;
}
}
}
} else if(stack.getItem() == Items.AIR) {
final ItemStack istack = te.getStackInSlot(1).copy();
if(te.phase() > BTileEntity.PHASE_WARMUP) player.setFire(1);
if(!istack.isEmpty()) {
istack.setCount(1);
player.setHeldItem(hand, istack);
te.reset_process();
dirty = true;
}
} else if(te.insert(stack.copy(),false)) {
stack.shrink(1);
dirty = true;
}
if(dirty) player.inventory.markDirty();
return true;
}
@Override
@SideOnly(Side.CLIENT)
public void randomDisplayTick(IBlockState state, World world, BlockPos pos, Random rnd)
{
if(state.getBlock()!=this) return;
EnumParticleTypes particle = EnumParticleTypes.SMOKE_NORMAL;
switch(state.getValue(PHASE)) {
case BTileEntity.PHASE_WARMUP:
return;
case BTileEntity.PHASE_HOT:
if(rnd.nextInt(10) > 4) return;
break;
case BTileEntity.PHASE_MAGMABLOCK:
if(rnd.nextInt(10) > 7) return;
particle = EnumParticleTypes.SMOKE_LARGE;
break;
case BTileEntity.PHASE_LAVA:
if(rnd.nextInt(10) > 2) return;
particle = EnumParticleTypes.LAVA;
break;
default:
return;
}
final double x=0.5+pos.getX(), y=0.5+pos.getY(), z=0.5+pos.getZ();
final double xr=rnd.nextDouble()*0.4-0.2, yr=rnd.nextDouble()*0.5, zr=rnd.nextDouble()*0.4-0.2;
world.spawnParticle(particle, x+xr, y+yr, z+zr, 0.0, 0.0, 0.0);
}
@Nullable
private BTileEntity getTe(World world, BlockPos pos)
{ final TileEntity te=world.getTileEntity(pos); return (!(te instanceof BTileEntity)) ? (null) : ((BTileEntity)te); }
//--------------------------------------------------------------------------------------------------------------------
// Tile entity
//--------------------------------------------------------------------------------------------------------------------
public static class BTileEntity extends TileEntity implements ITickable, ISidedInventory, IEnergyStorage
{
public static final int TICK_INTERVAL = 20;
public static final int MAX_FLUID_LEVEL = 1000;
public static final int MAX_BUCKET_EXTRACT_FLUID_LEVEL = 900;
public static final int MAX_ENERGY_BUFFER = 32000;
public static final int MAX_ENERGY_TRANSFER = 8192;
public static final int DEFAULT_ENERGY_CONSUMPTION = 92;
public static final int DEFAULT_HEATUP_RATE = 2; // -> 50s for one smelting process
public static final int PHASE_WARMUP = 0;
public static final int PHASE_HOT = 1;
public static final int PHASE_MAGMABLOCK = 2;
public static final int PHASE_LAVA = 3;
private static final ItemStack MAGMA_STACK = new ItemStack(Blocks.MAGMA);
private static final ItemStack BUCKET_STACK = new ItemStack(Items.BUCKET);
private static final ItemStack LAVA_BUCKET_STACK = new ItemStack(Items.LAVA_BUCKET);
private static int energy_consumption = DEFAULT_ENERGY_CONSUMPTION;
private static int heatup_rate = DEFAULT_HEATUP_RATE;
private static int cooldown_rate = 1;
private static Set<Item> accepted_minerals = new HashSet<Item>();
private static Set<Item> accepted_lava_contrainers = new HashSet<Item>();
private int tick_timer_;
private int energy_stored_;
private int progress_;
private int fluid_level_;
private boolean force_block_update_;
private NonNullList<ItemStack> stacks_ = NonNullList.<ItemStack>withSize(2, ItemStack.EMPTY);
static {
// Mineals: No Nether brick (made of Netherrack),
// no glazed terracotta, no obsidian, no stairs, slabs etc.
accepted_minerals.add(Item.getItemFromBlock(Blocks.COBBLESTONE));
accepted_minerals.add(Item.getItemFromBlock(Blocks.STONE));
accepted_minerals.add(Item.getItemFromBlock(Blocks.SANDSTONE));
accepted_minerals.add(Item.getItemFromBlock(Blocks.PRISMARINE));
accepted_minerals.add(Item.getItemFromBlock(Blocks.END_STONE));
accepted_minerals.add(Item.getItemFromBlock(Blocks.MOSSY_COBBLESTONE));
accepted_minerals.add(Item.getItemFromBlock(Blocks.RED_SANDSTONE));
accepted_minerals.add(Item.getItemFromBlock(Blocks.QUARTZ_BLOCK));
accepted_minerals.add(Item.getItemFromBlock(Blocks.BRICK_BLOCK));
accepted_minerals.add(Item.getItemFromBlock(Blocks.END_BRICKS));
accepted_minerals.add(Item.getItemFromBlock(Blocks.HARDENED_CLAY));
accepted_minerals.add(Item.getItemFromBlock(Blocks.STAINED_HARDENED_CLAY));
accepted_minerals.add(Item.getItemFromBlock(Blocks.STONEBRICK));
// Lava containers
accepted_lava_contrainers.add(Items.BUCKET);
}
public static void on_config(int energy_consumption, int heatup_per_second)
{
energy_consumption = MathHelper.clamp(energy_consumption, 32, 4096);
heatup_rate = MathHelper.clamp(heatup_per_second, 1, 5);
cooldown_rate = MathHelper.clamp(heatup_per_second/2, 1, 5);
ModEngineersDecor.logger.info("Config mineal smelter energy consumption:" + energy_consumption + "rf/t, heat-up rate: " + heatup_rate + "%/s.");
}
public BTileEntity()
{ reset_process(); }
public int progress()
{ return progress_; }
public int phase()
{
if(progress_ >= 100) return PHASE_LAVA;
if(progress_ >= 90) return PHASE_MAGMABLOCK;
if(progress_ >= 5) return PHASE_HOT;
return PHASE_WARMUP;
}
public int fluid_level()
{ return fluid_level_; }
public int fluid_level_drain(int amount)
{ amount = MathHelper.clamp(amount, 0, fluid_level_); fluid_level_ -= amount; return amount; }
public int comparator_signal()
{ return phase() * 5; } // -> 0..15
private boolean accepts_lava_container(ItemStack stack)
{ return accepted_lava_contrainers.contains(stack.getItem()); }
private boolean accepts_input(ItemStack stack)
{
if(!stacks_.get(0).isEmpty()) return false;
if(fluid_level() > MAX_BUCKET_EXTRACT_FLUID_LEVEL) {
return accepts_lava_container(stack);
} else {
return accepted_minerals.contains(stack.getItem());
}
}
public boolean insert(final ItemStack stack, boolean simulate)
{
if(stack.isEmpty() || (!accepts_input(stack))) return false;
if(!simulate) {
ItemStack st = stack.copy();
st.setCount(st.getMaxStackSize());
stacks_.set(0, st);
if(!accepts_lava_container(stack)) progress_ = 0;
force_block_update_ = true;
}
return true;
}
public ItemStack extract(boolean simulate)
{
ItemStack stack = stacks_.get(1).copy();
if(stack.isEmpty()) return ItemStack.EMPTY;
if(!simulate) reset_process();
return stack;
}
protected void reset_process()
{
stacks_ = NonNullList.<ItemStack>withSize(2, ItemStack.EMPTY);
force_block_update_ = true;
fluid_level_ = 0;
tick_timer_ = 0;
progress_ = 0;
}
public void readnbt(NBTTagCompound nbt)
{
energy_stored_ = nbt.getInteger("energy");
progress_ = nbt.getInteger("progress");
fluid_level_ = nbt.getInteger("fluidlevel");
ItemStackHelper.loadAllItems(nbt, stacks_);
if(stacks_.size() != 1) reset_process();
}
protected void writenbt(NBTTagCompound nbt)
{
nbt.setInteger("energy", MathHelper.clamp(energy_stored_,0 , MAX_ENERGY_BUFFER));
nbt.setInteger("progress", MathHelper.clamp(progress_,0 , 100));
nbt.setInteger("fluidlevel", MathHelper.clamp(fluid_level_,0 , MAX_FLUID_LEVEL));
ItemStackHelper.saveAllItems(nbt, stacks_);
}
// TileEntity ------------------------------------------------------------------------------
@Override
public boolean shouldRefresh(World world, BlockPos pos, IBlockState os, IBlockState ns)
{ return (os.getBlock() != ns.getBlock()) || (!(ns.getBlock() instanceof BlockDecorMineralSmelter)); }
@Override
public void readFromNBT(NBTTagCompound compound)
{ super.readFromNBT(compound); readnbt(compound); }
@Override
public NBTTagCompound writeToNBT(NBTTagCompound compound)
{ super.writeToNBT(compound); writenbt(compound); return compound; }
// IWorldNamable ---------------------------------------------------------------------------
@Override
public String getName()
{ final Block block=getBlockType(); return (block!=null) ? (block.getTranslationKey() + ".name") : (""); }
@Override
public boolean hasCustomName()
{ return false; }
@Override
public ITextComponent getDisplayName()
{ return new TextComponentTranslation(getName(), new Object[0]); }
// IInventory ------------------------------------------------------------------------------
@Override
public int getSizeInventory()
{ return stacks_.size(); }
@Override
public boolean isEmpty()
{ for(ItemStack stack: stacks_) { if(!stack.isEmpty()) return false; } return true; }
@Override
public ItemStack getStackInSlot(int index)
{ return ((index >= 0) && (index < getSizeInventory())) ? stacks_.get(index) : ItemStack.EMPTY; }
@Override
public ItemStack decrStackSize(int index, int count)
{ return ItemStackHelper.getAndSplit(stacks_, index, count); }
@Override
public ItemStack removeStackFromSlot(int index)
{ return ItemStackHelper.getAndRemove(stacks_, index); }
@Override
public void setInventorySlotContents(int index, ItemStack stack)
{ if(stack.getCount()>getInventoryStackLimit()){stack.setCount(getInventoryStackLimit());} stacks_.set(index, stack); markDirty(); }
@Override
public int getInventoryStackLimit()
{ return 1; }
@Override
public void markDirty()
{ super.markDirty(); }
@Override
public boolean isUsableByPlayer(EntityPlayer player)
{ return ((world.getTileEntity(pos) == this) && (player.getDistanceSq(pos.getX()+0.5d, pos.getY()+0.5d, pos.getZ()+0.5d) <= 64.0d)); }
@Override
public void openInventory(EntityPlayer player)
{}
@Override
public void closeInventory(EntityPlayer player)
{ markDirty(); }
@Override
public boolean isItemValidForSlot(int index, ItemStack stack)
{ return ((index==0) && accepts_input(stack)) || (index==1); }
@Override
public int getField(int id)
{ return 0; }
@Override
public void setField(int id, int value)
{}
@Override
public int getFieldCount()
{ return 0; }
@Override
public void clear()
{ reset_process(); }
// ISidedInventory ----------------------------------------------------------------------------
private static final int[] SIDED_INV_SLOTS = new int[] {0,1};
@Override
public int[] getSlotsForFace(EnumFacing side)
{ return SIDED_INV_SLOTS; }
@Override
public boolean canInsertItem(int index, ItemStack stack, EnumFacing direction)
{ return (index==0) && isItemValidForSlot(index, stack); }
@Override
public boolean canExtractItem(int index, ItemStack stack, EnumFacing direction)
{ return (index==1) && (!stacks_.get(1).isEmpty()); }
// IEnergyStorage ----------------------------------------------------------------------------
@Override
public boolean canExtract()
{ return false; }
@Override
public boolean canReceive()
{ return true; }
@Override
public int getMaxEnergyStored()
{ return MAX_ENERGY_BUFFER; }
@Override
public int getEnergyStored()
{ return energy_stored_; }
@Override
public int extractEnergy(int maxExtract, boolean simulate)
{ return 0; }
@Override
public int receiveEnergy(int maxReceive, boolean simulate)
{
if(energy_stored_ >= MAX_ENERGY_BUFFER) return 0;
int n = Math.min(maxReceive, (MAX_ENERGY_BUFFER - energy_stored_));
if(n > MAX_ENERGY_TRANSFER) n = MAX_ENERGY_TRANSFER;
if(!simulate) {energy_stored_ += n; markDirty(); }
return n;
}
// IItemHandler --------------------------------------------------------------------------------
protected static class BItemHandler implements IItemHandler
{
private BTileEntity te;
BItemHandler(BTileEntity te)
{ this.te = te; }
@Override
public int getSlots()
{ return 2; }
@Override
public int getSlotLimit(int index)
{ return te.getInventoryStackLimit(); }
@Override
public boolean isItemValid(int slot, @Nonnull ItemStack stack)
{ return te.isItemValidForSlot(slot, stack); }
@Override
@Nonnull
public ItemStack insertItem(int index, @Nonnull ItemStack stack, boolean simulate)
{
ItemStack rstack = stack.copy();
if((index!=0) || (!te.insert(stack.copy(), simulate))) return rstack;
rstack.shrink(1);
return rstack;
}
@Override
@Nonnull
public ItemStack extractItem(int index, int amount, boolean simulate)
{ return (index!=1) ? ItemStack.EMPTY : te.extract(simulate); }
@Override
@Nonnull
public ItemStack getStackInSlot(int index)
{ return te.getStackInSlot(index); }
}
private BItemHandler item_handler_ = new BItemHandler(this);
// IFluidHandler --------------------------------------------------------------------------------
private static class BFluidHandler implements IFluidHandler, IFluidTankProperties
{
private final FluidStack lava;
private final BTileEntity te;
private final IFluidTankProperties[] props_ = {this};
BFluidHandler(BTileEntity te) { this.te=te; lava = new FluidStack(FluidRegistry.LAVA, 1); }
@Override @Nullable public FluidStack getContents() { return new FluidStack(lava, te.fluid_level()); }
@Override public IFluidTankProperties[] getTankProperties() { return props_; }
@Override public int fill(FluidStack resource, boolean doFill) { return 0; }
@Override public int getCapacity() { return 1000; }
@Override public boolean canFill() { return false; }
@Override public boolean canDrain() { return true; }
@Override public boolean canFillFluidType(FluidStack fluidStack) { return false; }
@Override public boolean canDrainFluidType(FluidStack fluidStack) { return fluidStack.isFluidEqual(lava); }
@Override @Nullable public FluidStack drain(FluidStack resource, boolean doDrain)
{
if((te.fluid_level() <= 0) || (!resource.isFluidEqual(lava))) return null;
FluidStack fs = getContents();
if(doDrain) te.fluid_level_drain(fs.amount);
return fs;
}
@Override @Nullable public FluidStack drain(int maxDrain, boolean doDrain)
{
if(te.fluid_level() <= 0) return null;
maxDrain = (doDrain) ? (te.fluid_level_drain(maxDrain)) : (Math.min(maxDrain, te.fluid_level()));
return new FluidStack(FluidRegistry.LAVA, maxDrain);
}
}
private final BFluidHandler fluid_handler_ = new BFluidHandler(this);
// Capability export ----------------------------------------------------------------------------
@Override
public boolean hasCapability(Capability<?> cap, EnumFacing facing)
{ return ((cap==CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
|| (cap==CapabilityEnergy.ENERGY)
|| (cap==CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY)
|| (super.hasCapability(cap, facing))
);
}
@Override
@SuppressWarnings("unchecked")
@Nullable
public <T> T getCapability(Capability<T> capability, @Nullable EnumFacing facing)
{
if(capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
return (T)item_handler_;
} else if(capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) {
return (T)fluid_handler_;
} else if(capability == CapabilityEnergy.ENERGY) {
return (T)this;
} else {
return super.getCapability(capability, facing);
}
}
// ITickable ------------------------------------------------------------------------------------
@Override
public void update()
{
if(world.isRemote) return;
if(--tick_timer_ > 0) return;
tick_timer_ = TICK_INTERVAL;
IBlockState state = world.getBlockState(pos);
if(!(state.getBlock() instanceof BlockDecorMineralSmelter)) return;
boolean dirty = false;
final int last_phase = phase();
final ItemStack istack = stacks_.get(0);
if(istack.isEmpty() && (fluid_level()==0)) {
progress_ = 0;
} else if((energy_stored_ <= 0) || (world.isBlockPowered(pos))) {
progress_ = MathHelper.clamp(progress_-cooldown_rate, 0,100);
} else if(progress_ >= 100) {
progress_ = 100;
energy_stored_ = MathHelper.clamp(energy_stored_-((energy_consumption*TICK_INTERVAL)/20), 0, MAX_ENERGY_BUFFER);
} else {
energy_stored_ = MathHelper.clamp(energy_stored_-(energy_consumption*TICK_INTERVAL), 0, MAX_ENERGY_BUFFER);
progress_ = MathHelper.clamp(progress_+heatup_rate, 0, 100);
}
int new_phase = phase();
boolean is_lava_container = accepts_lava_container(istack);
if(is_lava_container || (new_phase != last_phase)) {
if(is_lava_container) {
// That stays in the slot until its extracted or somone takes it out.
if(istack.isItemEqual(BUCKET_STACK)) {
if(!stacks_.get(1).isItemEqual(LAVA_BUCKET_STACK)) {
if(fluid_level() >= MAX_BUCKET_EXTRACT_FLUID_LEVEL) {
stacks_.set(1, LAVA_BUCKET_STACK);
world.playSound(null, pos, SoundEvents.ITEM_BUCKET_FILL_LAVA, SoundCategory.BLOCKS, 0.2f, 1.3f);
} else {
stacks_.set(1, istack.copy());
}
dirty = true;
}
} else {
stacks_.set(1, istack.copy());
// Out stack -> Somehow the filled container or container with fluid+fluid_level().
}
} else if(new_phase > last_phase) {
switch(new_phase) {
case PHASE_LAVA:
fluid_level_ = MAX_FLUID_LEVEL;
stacks_.set(1, ItemStack.EMPTY);
stacks_.set(0, ItemStack.EMPTY);
world.playSound(null, pos, SoundEvents.BLOCK_LAVA_AMBIENT, SoundCategory.BLOCKS, 0.2f, 1.0f);
dirty = true;
break;
case PHASE_MAGMABLOCK:
stacks_.set(1, MAGMA_STACK.copy());
world.playSound(null, pos, SoundEvents.BLOCK_FIRE_AMBIENT, SoundCategory.BLOCKS, 0.2f, 0.8f);
dirty = true;
break;
case PHASE_HOT:
world.playSound(null, pos, SoundEvents.BLOCK_FIRE_AMBIENT, SoundCategory.BLOCKS, 0.2f, 0.8f);
break;
}
} else {
switch(new_phase) {
case PHASE_MAGMABLOCK:
stacks_.set(0, (fluid_level_ >= MAX_BUCKET_EXTRACT_FLUID_LEVEL) ? (MAGMA_STACK.copy()) : (ItemStack.EMPTY));
stacks_.set(1, stacks_.get(0).copy());
fluid_level_ = 0;
world.playSound(null, pos, SoundEvents.BLOCK_LAVA_EXTINGUISH, SoundCategory.BLOCKS, 0.5f, 1.1f);
dirty = true;
break;
case PHASE_HOT:
if(istack.isItemEqual(MAGMA_STACK)) {
stacks_.set(1, new ItemStack(Blocks.OBSIDIAN));
} else {
stacks_.set(1, new ItemStack(Blocks.COBBLESTONE));
}
world.playSound(null, pos, SoundEvents.BLOCK_LAVA_EXTINGUISH, SoundCategory.BLOCKS, 0.3f, 0.9f);
dirty = true;
break;
case PHASE_WARMUP:
world.playSound(null, pos, SoundEvents.BLOCK_LAVA_EXTINGUISH, SoundCategory.BLOCKS, 0.3f, 0.7f);
break;
}
}
}
if(force_block_update_ || (state.getValue(PHASE) != new_phase)) {
state = state.withProperty(PHASE, new_phase);
world.setBlockState(pos, state,3|16);
world.notifyNeighborsOfStateChange(pos, state.getBlock(),false);
force_block_update_ = false;
}
if(dirty) markDirty();
}
}
}

View file

@ -1,266 +0,0 @@
/*
* @file BlockDecorPassiveFluidAccumulator.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* A device that collects fluids from adjacent tank outputs
* when a pump drains on the (only) output side. Shall support
* high flow rates, and a vavuum suction delay. Shall not drain
* high amounts of fluid from the adjacent tanks when no fluid
* is requested at the output port. Shall drain balanced from
* the adjacent input sides.
*/
package wile.engineersdecor.blocks;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EnumHand;
import wile.engineersdecor.detail.ModAuxiliaries;
import net.minecraft.block.Block;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
import net.minecraft.util.ITickable;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.fluids.capability.IFluidTankProperties;
import net.minecraftforge.fluids.FluidStack;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class BlockDecorPassiveFluidAccumulator extends BlockDecorDirected
{
public BlockDecorPassiveFluidAccumulator(@Nonnull String registryName, long config, @Nullable Material material, float hardness, float resistance, @Nullable SoundType sound, @Nonnull AxisAlignedBB unrotatedAABB)
{ super(registryName, config, material, hardness, resistance, sound, unrotatedAABB); }
@Override
public boolean hasTileEntity(IBlockState state)
{ return true; }
@Override
@Nullable
public TileEntity createTileEntity(World world, IBlockState state)
{ return new BlockDecorPassiveFluidAccumulator.BTileEntity(); }
@Override
public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
{
if(world.isRemote) return true;
TileEntity te = world.getTileEntity(pos);
if(!(te instanceof BTileEntity)) return true;
((BTileEntity)te).send_device_stats(player);
return true;
}
@Override
public void neighborChanged(IBlockState state, World world, BlockPos pos, Block block, BlockPos fromPos)
{ TileEntity te = world.getTileEntity(pos); if(te instanceof BlockDecorPipeValve.BTileEntity) ((BTileEntity)te).block_changed(); }
//--------------------------------------------------------------------------------------------------------------------
// Tile entity
//--------------------------------------------------------------------------------------------------------------------
public static class BTileEntity extends TileEntity implements IFluidHandler, IFluidTankProperties, ICapabilityProvider, ITickable
{
protected static int tick_idle_interval = 20; // ca 1000ms, simulates suction delay and saves CPU when not drained.
protected static int max_flowrate = 1000;
private final IFluidTankProperties[] fluid_props_ = {this};
private final InputFillHandler fill_handler_ = new InputFillHandler(this);
private EnumFacing block_facing_ = EnumFacing.NORTH;
private FluidStack tank_ = null;
private int last_drain_request_amount_ = 0;
private int vacuum_ = 0;
private int tick_timer_ = 0;
private int round_robin_ = 0;
private boolean initialized_ = false;
private int total_volume_filled_ = 0;
private int total_volume_drained_ = 0;
public void send_device_stats(EntityPlayer player)
{
int t_vol = (tank_==null) ? 0 : (tank_.amount);
ModAuxiliaries.playerChatMessage(player,"" + t_vol + "mB");
}
public void block_changed()
{ initialized_ = false; tick_timer_ = MathHelper.clamp(tick_timer_ , 0, tick_idle_interval); }
// Output flow handler ---------------------------------------------------------------------
private static class InputFillHandler implements IFluidHandler, IFluidTankProperties
{
private final BTileEntity parent_;
private final IFluidTankProperties[] props_ = {this};
InputFillHandler(BTileEntity parent) { parent_ = parent; }
@Override public int fill(FluidStack resource, boolean doFill) { return 0; }
@Override @Nullable public FluidStack drain(FluidStack resource, boolean doDrain) { return null; }
@Override @Nullable public FluidStack drain(int maxDrain, boolean doDrain) { return null; }
@Override @Nullable public FluidStack getContents() { return null; }
@Override public IFluidTankProperties[] getTankProperties() { return props_; }
@Override public int getCapacity() { return max_flowrate; }
@Override public boolean canFill() { return true; }
@Override public boolean canDrain() { return false; }
@Override public boolean canFillFluidType(FluidStack fluidStack) { return true; }
@Override public boolean canDrainFluidType(FluidStack fluidStack) { return false; }
}
// TileEntity ------------------------------------------------------------------------------
public BTileEntity()
{}
@Override
public boolean shouldRefresh(World world, BlockPos pos, IBlockState os, IBlockState ns)
{
block_changed();
return (os.getBlock() != ns.getBlock()) || (!(ns.getBlock() instanceof BlockDecorPassiveFluidAccumulator));
}
@Override
public void readFromNBT(NBTTagCompound nbt)
{
super.readFromNBT(nbt);
tank_ = (!nbt.hasKey("tank")) ? (null) : (FluidStack.loadFluidStackFromNBT(nbt.getCompoundTag("tank")));
}
@Override
public NBTTagCompound writeToNBT(NBTTagCompound nbt)
{
super.writeToNBT(nbt);
if(tank_ != null) nbt.setTag("tank", tank_.writeToNBT(new NBTTagCompound()));
return nbt;
}
// ICapabilityProvider --------------------------------------------------------------------
@Override
public boolean hasCapability(@Nonnull Capability<?> capability, @Nullable EnumFacing facing)
{ return (initialized_ && (capability==CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY)) || super.hasCapability(capability, facing); }
@Override
@Nullable
@SuppressWarnings("unchecked")
public <T> T getCapability(@Nonnull Capability<T> capability, @Nullable EnumFacing facing)
{
if(capability != CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) return super.getCapability(capability, facing);
return (facing==block_facing_) ? (((T)this)) : ((T)fill_handler_);
}
// IFluidHandler of the output port --------------------------------------------------------
@Override
public IFluidTankProperties[] getTankProperties()
{ return fluid_props_; }
@Override
public int fill(FluidStack resource, boolean doFill)
{ return 0; }
@Override
@Nullable
public FluidStack drain(FluidStack resource, boolean doDrain)
{
if((resource==null) || (tank_==null)) return null;
return (!(tank_.isFluidEqual(resource))) ? (null) : drain(resource.amount, doDrain);
}
@Override
@Nullable
public FluidStack drain(int maxDrain, boolean doDrain)
{
if(!initialized_) return null;
if(doDrain && (maxDrain > 0)) last_drain_request_amount_ = maxDrain;
if(tank_==null) return null;
maxDrain = MathHelper.clamp(maxDrain ,0 , tank_.amount);
if(!doDrain) return tank_.copy();
FluidStack res = tank_.copy();
res.amount = maxDrain;
tank_.amount -= maxDrain;
if(tank_.amount <= 0) tank_= null;
total_volume_drained_ += res.amount;
return res;
}
// IFluidTankProperties --------------------------------------------------------------------
@Override @Nullable public FluidStack getContents() { return (tank_==null) ? (null) : (tank_.copy()); }
@Override public int getCapacity() { return max_flowrate; }
@Override public boolean canFill() { return false; }
@Override public boolean canDrain() { return true; }
@Override public boolean canFillFluidType(FluidStack fluidStack) { return false; }
@Override public boolean canDrainFluidType(FluidStack fluidStack) { return true; }
// ITickable--------------------------------------------------------------------------------
public void update()
{
if((world.isRemote) || (--tick_timer_ > 0)) return;
tick_timer_ = tick_idle_interval;
final IBlockState state = world.getBlockState(pos);
if(!(state.getBlock() instanceof BlockDecorPassiveFluidAccumulator)) return;
if(!initialized_) {
initialized_ = true;
block_facing_ = state.getValue(FACING);
}
int n_requested = last_drain_request_amount_;
last_drain_request_amount_ = 0;
if(n_requested > 0) {
vacuum_ += 2;
if(vacuum_ > 5) vacuum_ = 5;
} else {
if((--vacuum_) <= 0) {
vacuum_ = 0;
if(tank_!=null) {
return; // nothing to do, noone's draining.
} else {
n_requested = 10; // drip in
}
}
}
boolean has_refilled = false;
n_requested += (vacuum_ * 50);
int tank_buffer_needed = n_requested;
if(tank_buffer_needed > max_flowrate) tank_buffer_needed = max_flowrate;
for(int i=0; i<6; ++i) {
if(++round_robin_ > 5) round_robin_ = 0;
if(n_requested <= 0) break;
if(((tank_!=null) && (tank_.amount >= tank_buffer_needed))) break;
final EnumFacing f = EnumFacing.byIndex(round_robin_);
if(f == block_facing_) continue;
final TileEntity te = world.getTileEntity(pos.offset(f));
if((te==null) || (te instanceof BTileEntity) || (!te.hasCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, f.getOpposite()))) continue;
final IFluidHandler fh = te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, f.getOpposite());
if(fh==null) continue;
if(tank_==null) {
FluidStack res = fh.drain(n_requested, true);
if((res == null) || (res.amount==0)) continue;
total_volume_filled_ += res.amount;
tank_ = res.copy();
has_refilled = true;
} else {
if((tank_.amount + n_requested) > max_flowrate) n_requested = (max_flowrate - tank_.amount);
FluidStack rq = tank_.copy();
rq.amount = n_requested;
FluidStack res = fh.drain(rq, true);
if(res == null) continue;
tank_.amount += res.amount;
total_volume_filled_ += res.amount;
has_refilled = true;
if(tank_.amount >= max_flowrate) break;
}
}
if(has_refilled) tick_timer_ = 0;
}
}
}

View file

@ -1,334 +0,0 @@
/*
* @file BlockDecorPipeValve.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Basically a piece of pipe that does not connect to
* pipes on the side, and conducts fluids only in one way.
*/
package wile.engineersdecor.blocks;
import wile.engineersdecor.ModEngineersDecor;
import blusunrize.immersiveengineering.api.fluid.IFluidPipe;
import net.minecraft.block.state.BlockFaceShape;
import net.minecraft.block.properties.PropertyInteger;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.Block;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.item.ItemStack;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.EnumHand;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.fluids.capability.IFluidTankProperties;
import net.minecraftforge.fluids.FluidStack;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class BlockDecorPipeValve extends BlockDecorDirected
{
//--------------------------------------------------------------------------------------------------------------------
// Config
//--------------------------------------------------------------------------------------------------------------------
private static int fluid_maxflow_mb = 1000;
private static int redstone_flow_slope_mb = 1000/15;
public static void on_config(int container_size_decl, int redstone_slope)
{
fluid_maxflow_mb = MathHelper.clamp(container_size_decl, 1, 10000);
redstone_flow_slope_mb = MathHelper.clamp(redstone_slope, 1, 10000);
ModEngineersDecor.logger.info("Config pipe valve: maxflow:" + fluid_maxflow_mb + "mb, redstone amp:" + redstone_flow_slope_mb + "mb/sig");
}
//--------------------------------------------------------------------------------------------------------------------
// Block
//--------------------------------------------------------------------------------------------------------------------
public static final PropertyInteger RS_CONNECTION_DIR = PropertyInteger.create("rsdir", 0,4);
public BlockDecorPipeValve(@Nonnull String registryName, long config, @Nullable Material material, float hardness, float resistance, @Nullable SoundType sound, @Nonnull AxisAlignedBB unrotatedAABB)
{ super(registryName, config, material, hardness, resistance, sound, unrotatedAABB); }
@Override
protected BlockStateContainer createBlockState()
{ return new BlockStateContainer(this, FACING, RS_CONNECTION_DIR); }
@Override
public IBlockState getStateForPlacement(World world, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer, EnumHand hand)
{ return super.getStateForPlacement(world, pos, facing, hitX, hitY, hitZ, meta, placer, hand).withProperty(RS_CONNECTION_DIR, 0); }
// world to model index transformations. [Facing block][Facing neighbour] -> int 0=nothing, 1=top, 2=right, 3=down, 4=left.
private static final int rsconnectors[][] = {
//D U N S W E
{0, 0, 1, 3, 4, 2}, // D
{0, 0, 3, 1, 4, 2}, // U
{3, 1, 0, 0, 4, 2}, // N
{3, 1, 0, 0, 2, 4}, // S
{3, 1, 2, 4, 0, 0}, // W
{3, 1, 4, 2, 0, 0}, // E
};
@Override
public IBlockState getActualState(IBlockState state, IBlockAccess world, BlockPos pos)
{
if((config & (CFG_REDSTONE_CONTROLLED))==0) return state;
EnumFacing.Axis bfa = state.getValue(FACING).getAxis();
int bfi = state.getValue(FACING).getIndex();
for(EnumFacing f:EnumFacing.VALUES) {
if(f.getAxis() == bfa) continue;
BlockPos nbp = pos.offset(f);
IBlockState nbs = world.getBlockState(nbp);
if(nbs.canProvidePower()) return state.withProperty(RS_CONNECTION_DIR, rsconnectors[state.getValue(FACING).getIndex()][f.getIndex()]);
}
return state.withProperty(RS_CONNECTION_DIR, 0);
}
@Override
public void neighborChanged(IBlockState state, World world, BlockPos pos, Block block, BlockPos fromPos)
{
EnumFacing fc = state.getValue(FACING);
if(fromPos.equals(pos.offset(fc)) || fromPos.equals(pos.offset(fc.getOpposite()))) update_te(world, state, pos);
}
@Override
public void onBlockPlacedBy(World world, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack)
{
update_te(world, state, pos);
world.notifyNeighborsOfStateChange(pos, this, true);
}
@Override
public BlockFaceShape getBlockFaceShape(IBlockAccess worldIn, IBlockState state, BlockPos pos, EnumFacing face)
{ return BlockFaceShape.SOLID; }
@Override
public boolean canConnectRedstone(IBlockState state, IBlockAccess world, BlockPos pos, @Nullable EnumFacing side)
{ return (side!=null) && (side!=state.getValue(FACING)) && (side!=state.getValue(FACING).getOpposite()); }
@Override
public boolean hasTileEntity(IBlockState state)
{ return true; }
@Nullable
public TileEntity createTileEntity(World world, IBlockState state)
{ return new BlockDecorPipeValve.BTileEntity(); }
private void update_te(World world, IBlockState state, BlockPos pos)
{
TileEntity te = world.getTileEntity(pos);
if(te instanceof BlockDecorPipeValve.BTileEntity) ((BlockDecorPipeValve.BTileEntity)te).block_reconfigure(state.getValue(FACING), config);
}
//--------------------------------------------------------------------------------------------------------------------
// Tile entity
//--------------------------------------------------------------------------------------------------------------------
public static class BTileEntity extends TileEntity implements IFluidHandler, IFluidTankProperties, ICapabilityProvider, IFluidPipe
{
private static final BackFlowHandler back_flow_handler_ = new BackFlowHandler();
private final IFluidTankProperties[] fluid_props_ = {this};
private EnumFacing block_facing_ = EnumFacing.NORTH;
private boolean filling_ = false;
private boolean getlocked_ = false;
private boolean filling_enabled_ = true;
private long block_config_ = 0;
public BTileEntity()
{}
public void block_reconfigure(EnumFacing facing, long block_config)
{
block_facing_ = facing;
block_config_ = block_config;
filling_enabled_ = false;
IFluidHandler fh = forward_fluid_handler();
if(fh!=null) {
if(fh.getTankProperties().length==0) {
filling_enabled_ = true; // we don't know, so in doubt try filling.
} else {
for(IFluidTankProperties fp:fh.getTankProperties()) {
if((fp!=null) && (fp.canFill())) { filling_enabled_ = true; break; }
}
}
}
}
// TileEntity ------------------------------------------------------------------------------
@Override
public boolean shouldRefresh(World world, BlockPos pos, IBlockState os, IBlockState ns)
{ return (os.getBlock() != ns.getBlock()) || (!(ns.getBlock() instanceof BlockDecorPipeValve)); }
@Override
public void onLoad()
{
if(!hasWorld()) return;
final IBlockState state = world.getBlockState(pos);
if((!(state.getBlock() instanceof BlockDecorPipeValve))) return;
block_reconfigure(state.getValue(FACING), block_config_);
world.notifyNeighborsOfStateChange(pos, state.getBlock(), false);
}
@Override
public void readFromNBT(NBTTagCompound nbt)
{
super.readFromNBT(nbt);
int i = nbt.getInteger("facing");
if((i>=0) || (i<6)) block_facing_ = EnumFacing.byIndex(i);
block_config_ = nbt.getLong("conf");
}
@Override
public NBTTagCompound writeToNBT(NBTTagCompound nbt)
{
super.writeToNBT(nbt);
nbt.setInteger("facing", block_facing_.getIndex());
nbt.setLong("conf", block_config_);
return nbt;
}
// ICapabilityProvider --------------------------------------------------------------------
@Override
public boolean hasCapability(@Nonnull Capability<?> capability, @Nullable EnumFacing facing)
{ return ((capability==CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) && ((facing==block_facing_) || (facing==block_facing_.getOpposite()))); }
@Override
@SuppressWarnings("unchecked")
@Nullable
public <T> T getCapability(@Nonnull Capability<T> capability, @Nullable EnumFacing facing)
{
if(capability!=CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) return super.getCapability(capability, facing);
return (facing==block_facing_) ? ((T)back_flow_handler_) : (((T)this));
}
// IFluidHandler/IFluidTankProperties ---------------------------------------------------------------
@Nullable
private IFluidHandler forward_fluid_handler()
{
final TileEntity te = world.getTileEntity(pos.offset(block_facing_));
if(te == null) return null;
return te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, block_facing_.getOpposite());
}
@Override
public int fill(FluidStack resource, boolean doFill)
{
if((filling_) || (!filling_enabled_)) return 0;
if((block_config_ & CFG_REDSTONE_CONTROLLED) != 0) {
int rs = world.getRedstonePowerFromNeighbors(pos);
if(rs <= 0) return 0;
if(((block_config_ & CFG_ANALOG) != 0) && (rs < 15)) resource.amount = MathHelper.clamp(rs * redstone_flow_slope_mb, 1, resource.amount);
}
FluidStack res = resource.copy();
if(res.amount > fluid_maxflow_mb) res.amount = fluid_maxflow_mb;
final IFluidHandler fh = forward_fluid_handler();
if(fh==null) return 0;
filling_ = true; // in case someone does not check the cap, but just "forwards back" what is beeing filled right now.
if(res.amount > 50) {
final TileEntity te = world.getTileEntity(pos.offset(block_facing_));
if(te instanceof IFluidPipe) {
// forward pressureized tag
if(res.tag == null) res.tag = new NBTTagCompound();
res.tag.setBoolean("pressurized", true);
}
}
int n_filled = forward_fluid_handler().fill(res, doFill);
filling_ = false;
return n_filled;
}
@Override
@Nullable
public FluidStack drain(FluidStack resource, boolean doDrain)
{ return null; }
@Override
@Nullable
public FluidStack drain(int maxDrain, boolean doDrain)
{ return null; }
@Override
public IFluidTankProperties[] getTankProperties()
{ return fluid_props_; }
// IFluidTankProperties --
@Override
@Nullable
public FluidStack getContents()
{ return null; }
public int getCapacity()
{ return 1000; }
@Override
public boolean canFill()
{ return true; }
@Override
public boolean canDrain()
{ return false; }
@Override
public boolean canFillFluidType(FluidStack fluidStack)
{ return true; }
@Override
public boolean canDrainFluidType(FluidStack fluidStack)
{ return false; }
// Back flow prevention handler --
private static class BackFlowHandler implements IFluidHandler, IFluidTankProperties
{
private final IFluidTankProperties[] props_ = {this};
@Override public IFluidTankProperties[] getTankProperties() { return props_; }
@Override public int fill(FluidStack resource, boolean doFill) { return 0; }
@Override @Nullable public FluidStack drain(FluidStack resource, boolean doDrain) { return null; }
@Override @Nullable public FluidStack drain(int maxDrain, boolean doDrain) { return null; }
@Override @Nullable public FluidStack getContents() { return null; }
@Override public int getCapacity() { return 0; }
@Override public boolean canFill() { return false; }
@Override public boolean canDrain() { return false; }
@Override public boolean canFillFluidType(FluidStack fluidStack) { return false; }
@Override public boolean canDrainFluidType(FluidStack fluidStack) { return false; }
}
// IFluidPipe
@Override
public boolean hasOutputConnection(EnumFacing side)
{ return (side == block_facing_); }
@Override
public boolean canOutputPressurized(boolean consumePower)
{
if(getlocked_ || (!filling_enabled_)) return false;
final TileEntity te = world.getTileEntity(pos.offset(block_facing_));
if(!(te instanceof IFluidPipe)) return false;
getlocked_ = true; // not sure if IE explicitly pre-detects loops, so let's lock recurion here, too.
boolean r = ((IFluidPipe)te).canOutputPressurized(consumePower);
getlocked_ = false;
return r;
}
}
}

View file

@ -1,777 +0,0 @@
/*
* @file BlockDecorPlacer.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Block placer and planter, factory automation suitable.
*/
package wile.engineersdecor.blocks;
import wile.engineersdecor.ModEngineersDecor;
import wile.engineersdecor.detail.Networking;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.init.SoundEvents;
import net.minecraft.world.IBlockAccess;
import net.minecraft.block.*;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.block.state.BlockFaceShape;
import net.minecraft.world.World;
import net.minecraft.world.Explosion;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.entity.Entity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.item.*;
import net.minecraft.inventory.*;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.util.math.*;
import net.minecraft.util.*;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentTranslation;
import net.minecraftforge.common.IPlantable;
import net.minecraftforge.common.util.FakePlayer;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.items.wrapper.SidedInvWrapper;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map.Entry;
public class BlockDecorPlacer extends BlockDecorDirected
{
public BlockDecorPlacer(@Nonnull String registryName, long config, @Nullable Material material, float hardness, float resistance, @Nullable SoundType sound, @Nonnull AxisAlignedBB unrotatedAABB)
{ super(registryName, config, material, hardness, resistance, sound, unrotatedAABB); }
@Override
public BlockFaceShape getBlockFaceShape(IBlockAccess world, IBlockState state, BlockPos pos, EnumFacing face)
{ return BlockFaceShape.SOLID; }
@Override
@SuppressWarnings("deprecation")
public boolean hasComparatorInputOverride(IBlockState state)
{ return true; }
@Override
@SuppressWarnings("deprecation")
public int getComparatorInputOverride(IBlockState blockState, World world, BlockPos pos)
{ return Container.calcRedstone(world.getTileEntity(pos)); }
@Override
public boolean hasTileEntity(IBlockState state)
{ return true; }
@Override
@Nullable
public TileEntity createTileEntity(World world, IBlockState state)
{ return new BTileEntity(); }
@Override
public void onBlockPlacedBy(World world, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack)
{
if(world.isRemote) return;
if((!stack.hasTagCompound()) || (!stack.getTagCompound().hasKey("tedata"))) return;
NBTTagCompound te_nbt = stack.getTagCompound().getCompoundTag("tedata");
if(te_nbt.isEmpty()) return;
final TileEntity te = world.getTileEntity(pos);
if(!(te instanceof BTileEntity)) return;
((BTileEntity)te).readnbt(te_nbt, false);
((BTileEntity)te).reset_rtstate();
((BTileEntity)te).markDirty();
}
@Override
public boolean removedByPlayer(IBlockState state, World world, BlockPos pos, EntityPlayer player, boolean willHarvest)
{
if(world.isRemote) return true;
TileEntity te = world.getTileEntity(pos);
if(!(te instanceof BTileEntity)) return super.removedByPlayer(state, world, pos, player, willHarvest);
ItemStack stack = new ItemStack(this, 1);
NBTTagCompound te_nbt = new NBTTagCompound();
((BTileEntity) te).writenbt(te_nbt, false);
if(!te_nbt.isEmpty()) {
NBTTagCompound nbt = new NBTTagCompound();
nbt.setTag("tedata", te_nbt);
stack.setTagCompound(nbt);
}
world.spawnEntity(new EntityItem(world, pos.getX()+0.5, pos.getY()+0.5, pos.getZ()+0.5, stack));
world.setBlockToAir(pos);
world.removeTileEntity(pos);
return false;
}
@Override
public void onBlockExploded(World world, BlockPos pos, Explosion explosion)
{
if(world.isRemote) return;
TileEntity te = world.getTileEntity(pos);
if(!(te instanceof BTileEntity)) return;
for(ItemStack stack: ((BTileEntity)te).stacks_) {
if(!stack.isEmpty()) world.spawnEntity(new EntityItem(world, pos.getX(), pos.getY(), pos.getZ(), stack));
}
((BTileEntity)te).reset_rtstate();
super.onBlockExploded(world, pos, explosion);
}
@Override
public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
{
if(world.isRemote) return true;
player.openGui(ModEngineersDecor.instance, ModEngineersDecor.GuiHandler.GUIID_FACTORY_PLACER, world, pos.getX(), pos.getY(), pos.getZ());
return true;
}
@Override
public void neighborChanged(IBlockState state, World world, BlockPos pos, Block block, BlockPos neighborPos)
{
if(!(world instanceof World) || (((World) world).isRemote)) return;
TileEntity te = world.getTileEntity(pos);
if(!(te instanceof BTileEntity)) return;
((BTileEntity)te).block_updated();
}
//--------------------------------------------------------------------------------------------------------------------
// ModEngineersDecor.GuiHandler connectors
//--------------------------------------------------------------------------------------------------------------------
public static Object getServerGuiElement(final EntityPlayer player, final World world, final BlockPos pos, final TileEntity te)
{ return (te instanceof BTileEntity) ? (new BContainer(player.inventory, world, pos, (BTileEntity)te)) : null; }
public static Object getClientGuiElement(final EntityPlayer player, final World world, final BlockPos pos, final TileEntity te)
{ return (te instanceof BTileEntity) ? (new BGui(player.inventory, world, pos, (BTileEntity)te)) : null; }
//--------------------------------------------------------------------------------------------------------------------
// GUI
//--------------------------------------------------------------------------------------------------------------------
@SideOnly(Side.CLIENT)
private static class BGui extends GuiContainer
{
private final BTileEntity te;
public BGui(InventoryPlayer playerInventory, World world, BlockPos pos, BTileEntity te)
{ super(new BContainer(playerInventory, world, pos, te)); this.te = te; }
@Override
public void initGui()
{ super.initGui(); }
@Override
public void drawScreen(int mouseX, int mouseY, float partialTicks)
{
drawDefaultBackground();
super.drawScreen(mouseX, mouseY, partialTicks);
renderHoveredToolTip(mouseX, mouseY);
}
@Override
protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException
{
super.mouseClicked(mouseX, mouseY, mouseButton);
BContainer container = (BContainer)inventorySlots;
if(container.fields_.length != 3) return;
int mx = mouseX - getGuiLeft(), my = mouseY - getGuiTop();
if(!isPointInRegion(126, 1, 49, 60, mouseX, mouseY)) {
return;
} else if(isPointInRegion(133, 49, 9, 9, mouseX, mouseY)) {
NBTTagCompound nbt = new NBTTagCompound();
nbt.setInteger("manual_trigger", 1);
Networking.PacketTileNotify.sendToServer(te, nbt);
} else if(isPointInRegion(145, 49, 9, 9, mouseX, mouseY)) {
NBTTagCompound nbt = new NBTTagCompound();
nbt.setInteger("logic", container.fields_[0] ^ BTileEntity.LOGIC_INVERTED);
Networking.PacketTileNotify.sendToServer(te, nbt);
} else if(isPointInRegion(159, 49, 7, 9, mouseX, mouseY)) {
NBTTagCompound nbt = new NBTTagCompound();
nbt.setInteger("logic", container.fields_[0] ^ BTileEntity.LOGIC_CONTINUOUS);
Networking.PacketTileNotify.sendToServer(te, nbt);
}
}
@Override
protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY)
{
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
mc.getTextureManager().bindTexture(new ResourceLocation(ModEngineersDecor.MODID, "textures/gui/factory_placer_gui.png"));
final int x0=getGuiLeft(), y0=getGuiTop(), w=getXSize(), h=getYSize();
drawTexturedModalRect(x0, y0, 0, 0, w, h);
BContainer container = (BContainer)inventorySlots;
if(container.fields_.length != 3) return; // no init, no cake.
// active slot
{
int slot_index = container.fields_[2];
if((slot_index < 0) || (slot_index >= BTileEntity.NUM_OF_SLOTS)) slot_index = 0;
int x = (x0+10+((slot_index % 6) * 18));
int y = (y0+8+((slot_index / 6) * 17));
drawTexturedModalRect(x, y, 200, 8, 18, 18);
}
// redstone input
{
if(container.fields_[1] != 0) {
drawTexturedModalRect(x0+133, y0+49, 217, 49, 9, 9);
}
}
// trigger logic
{
int inverter_offset = ((container.fields_[0] & BTileEntity.LOGIC_INVERTED) != 0) ? 11 : 0;
drawTexturedModalRect(x0+145, y0+49, 177+inverter_offset, 49, 9, 9);
int pulse_mode_offset = ((container.fields_[0] & BTileEntity.LOGIC_CONTINUOUS ) != 0) ? 9 : 0;
drawTexturedModalRect(x0+159, y0+49, 199+pulse_mode_offset, 49, 9, 9);
}
}
}
//--------------------------------------------------------------------------------------------------------------------
// container
//--------------------------------------------------------------------------------------------------------------------
public static class BContainer extends Container
{
private static final int PLAYER_INV_START_SLOTNO = BTileEntity.NUM_OF_SLOTS;
private final World world;
private final BlockPos pos;
private final EntityPlayer player;
private final BTileEntity te;
private int fields_[] = new int[3];
public BContainer(InventoryPlayer playerInventory, World world, BlockPos pos, BTileEntity te)
{
this.player = playerInventory.player;
this.world = world;
this.pos = pos;
this.te = te;
int i=-1;
// device slots (stacks 0 to 17)
for(int y=0; y<3; ++y) {
for(int x=0; x<6; ++x) {
int xpos = 11+x*18, ypos = 9+y*17;
addSlotToContainer(new Slot(te, ++i, xpos, ypos));
}
}
// player slots
for(int x=0; x<9; ++x) {
addSlotToContainer(new Slot(playerInventory, x, 9+x*18, 129)); // player slots: 0..8
}
for(int y=0; y<3; ++y) {
for(int x=0; x<9; ++x) {
addSlotToContainer(new Slot(playerInventory, x+y*9+9, 9+x*18, 71+y*18)); // player slots: 9..35
}
}
}
public BlockPos getPos()
{ return pos; }
@Override
public void addListener(IContainerListener listener)
{ super.addListener(listener); listener.sendAllWindowProperties(this, te); }
@Override
public void detectAndSendChanges()
{
super.detectAndSendChanges();
for(int il=0; il<listeners.size(); ++il) {
IContainerListener lis = listeners.get(il);
for(int k=0; k<fields_.length; ++k) {
int f = te.getField(k);
if(fields_[k] != f) {
fields_[k] = f;
lis.sendWindowProperty(this, k, f);
}
}
}
}
@Override
@SideOnly(Side.CLIENT)
public void updateProgressBar(int id, int value)
{
if((id < 0) || (id >= fields_.length)) return;
fields_[id] = value;
te.setField(id, value);
}
@Override
public boolean canInteractWith(EntityPlayer player)
{ return (world.getBlockState(pos).getBlock() instanceof BlockDecorPlacer) && (player.getDistanceSq(pos) <= 64); }
@Override
public ItemStack transferStackInSlot(EntityPlayer player, int index)
{
Slot slot = inventorySlots.get(index);
if((slot==null) || (!slot.getHasStack())) return ItemStack.EMPTY;
ItemStack slot_stack = slot.getStack();
ItemStack transferred = slot_stack.copy();
if((index>=0) && (index<PLAYER_INV_START_SLOTNO)) {
// Device slots
if(!mergeItemStack(slot_stack, PLAYER_INV_START_SLOTNO, PLAYER_INV_START_SLOTNO+36, false)) return ItemStack.EMPTY;
} else if((index >= PLAYER_INV_START_SLOTNO) && (index <= PLAYER_INV_START_SLOTNO+36)) {
// Player slot
if(!mergeItemStack(slot_stack, 0, BTileEntity.NUM_OF_SLOTS, false)) return ItemStack.EMPTY;
} else {
// invalid slot
return ItemStack.EMPTY;
}
if(slot_stack.isEmpty()) {
slot.putStack(ItemStack.EMPTY);
} else {
slot.onSlotChanged();
}
if(slot_stack.getCount() == transferred.getCount()) return ItemStack.EMPTY;
slot.onTake(player, slot_stack);
return transferred;
}
}
//--------------------------------------------------------------------------------------------------------------------
// Tile entity
//--------------------------------------------------------------------------------------------------------------------
public static class BTileEntity extends TileEntity implements ITickable, ISidedInventory, Networking.IPacketReceiver
{
@FunctionalInterface private interface SpecialPlacementFunction{ EnumActionResult apply(ItemStack stack, World world, BlockPos pos);}
public static final int TICK_INTERVAL = 40;
public static final int NUM_OF_SLOTS = 18;
///
public static final int LOGIC_INVERTED = 0x01;
public static final int LOGIC_CONTINUOUS = 0x02;
public static final int DEFAULT_LOGIC = LOGIC_INVERTED|LOGIC_CONTINUOUS;
public static HashMap<ItemStack, SpecialPlacementFunction> special_placement_conversions = new HashMap<>();
///
private boolean block_power_signal_ = false;
private boolean block_power_updated_ = false;
private int logic_ = DEFAULT_LOGIC;
private int current_slot_index_ = 0;
private int tick_timer_ = 0;
protected NonNullList<ItemStack> stacks_;
public static void on_config()
{
special_placement_conversions.put(new ItemStack(Items.DYE, 1, 3), (stack,world,pos)->{ // cocoa
if(world.getBlockState(pos).getBlock() instanceof BlockCocoa) return EnumActionResult.PASS;
if(!Blocks.COCOA.canPlaceBlockAt(world, pos)) return EnumActionResult.FAIL;
for(EnumFacing facing:EnumFacing.HORIZONTALS) {
IBlockState st = world.getBlockState(pos.offset(facing));
if(!(st.getBlock() instanceof BlockLog)) continue;
if(st.getBlock().getMetaFromState(st) != 3) continue;
IBlockState state = Blocks.COCOA.getDefaultState().withProperty(BlockCocoa.FACING, facing);
return world.setBlockState(pos, state, 1|2) ? EnumActionResult.SUCCESS : EnumActionResult.FAIL;
}
return EnumActionResult.FAIL;
});
ModEngineersDecor.logger.info("Config placer: " + special_placement_conversions.size() + " special placement handling entries.");
}
public BTileEntity()
{
stacks_ = NonNullList.<ItemStack>withSize(NUM_OF_SLOTS, ItemStack.EMPTY);
reset_rtstate();
}
public void reset_rtstate()
{
block_power_signal_ = false;
block_power_updated_ = false;
}
public void readnbt(NBTTagCompound nbt, boolean update_packet)
{
stacks_ = NonNullList.<ItemStack>withSize(NUM_OF_SLOTS, ItemStack.EMPTY);
ItemStackHelper.loadAllItems(nbt, stacks_);
while(stacks_.size() < NUM_OF_SLOTS) stacks_.add(ItemStack.EMPTY);
block_power_signal_ = nbt.getBoolean("powered");
current_slot_index_ = nbt.getInteger("act_slot_index");
logic_ = nbt.hasKey("logic") ? nbt.getInteger("logic") : DEFAULT_LOGIC;
}
protected void writenbt(NBTTagCompound nbt, boolean update_packet)
{
boolean stacks_not_empty = stacks_.stream().anyMatch(s->!s.isEmpty());
if(stacks_not_empty) ItemStackHelper.saveAllItems(nbt, stacks_);
if(block_power_signal_) nbt.setBoolean("powered", block_power_signal_);
if(stacks_not_empty) nbt.setInteger("act_slot_index", current_slot_index_);
if(logic_ != DEFAULT_LOGIC) nbt.setInteger("logic", logic_);
}
public void block_updated()
{
boolean powered = world.isBlockPowered(pos);
if(block_power_signal_ != powered) block_power_updated_ = true;
block_power_signal_ = powered;
if(block_power_updated_) {
tick_timer_ = 1;
} else if(tick_timer_ > 4) {
tick_timer_ = 4;
}
}
public boolean is_input_slot(int index)
{ return (index >= 0) && (index < NUM_OF_SLOTS); }
// TileEntity ------------------------------------------------------------------------------
@Override
public boolean shouldRefresh(World world, BlockPos pos, IBlockState os, IBlockState ns)
{ return (os.getBlock() != ns.getBlock()) || (!(ns.getBlock() instanceof BlockDecorPlacer)); }
@Override
public void readFromNBT(NBTTagCompound nbt)
{ super.readFromNBT(nbt); readnbt(nbt, false); }
@Override
public NBTTagCompound writeToNBT(NBTTagCompound nbt)
{ super.writeToNBT(nbt); writenbt(nbt, false); return nbt; }
// IWorldNamable ---------------------------------------------------------------------------
@Override
public String getName()
{ final Block block=getBlockType(); return (block!=null) ? (block.getTranslationKey() + ".name") : (""); }
@Override
public boolean hasCustomName()
{ return false; }
@Override
public ITextComponent getDisplayName()
{ return new TextComponentTranslation(getName(), new Object[0]); }
// IInventory ------------------------------------------------------------------------------
@Override
public int getSizeInventory()
{ return stacks_.size(); }
@Override
public boolean isEmpty()
{ for(ItemStack stack: stacks_) { if(!stack.isEmpty()) return false; } return true; }
@Override
public ItemStack getStackInSlot(int index)
{ return (index < getSizeInventory()) ? stacks_.get(index) : ItemStack.EMPTY; }
@Override
public ItemStack decrStackSize(int index, int count)
{ return ItemStackHelper.getAndSplit(stacks_, index, count); }
@Override
public ItemStack removeStackFromSlot(int index)
{ return ItemStackHelper.getAndRemove(stacks_, index); }
@Override
public void setInventorySlotContents(int index, ItemStack stack)
{
stacks_.set(index, stack);
if(stack.getCount() > getInventoryStackLimit()) stack.setCount(getInventoryStackLimit());
if(tick_timer_ > 8) tick_timer_ = 8;
markDirty();
}
@Override
public int getInventoryStackLimit()
{ return 64; }
@Override
public void markDirty()
{ super.markDirty(); }
@Override
public boolean isUsableByPlayer(EntityPlayer player)
{ return ((world.getTileEntity(pos) == this) && (player.getDistanceSq(pos.getX()+0.5d, pos.getY()+0.5d, pos.getZ()+0.5d) <= 64.0d)); }
@Override
public void openInventory(EntityPlayer player)
{}
@Override
public void closeInventory(EntityPlayer player)
{ markDirty(); }
@Override
public boolean isItemValidForSlot(int index, ItemStack stack)
{ return true; }
@Override
public int getField(int id)
{
switch(id) {
case 0: return logic_;
case 1: return block_power_signal_ ? 1 : 0;
case 2: return current_slot_index_;
default: return 0;
}
}
@Override
public void setField(int id, int value)
{
switch(id) {
case 0: logic_ = value; return;
case 1: block_power_signal_ = (value != 0); return;
case 2: current_slot_index_ = MathHelper.clamp(value, 0, NUM_OF_SLOTS-1); return;
default: return;
}
}
@Override
public int getFieldCount()
{ return 3; }
@Override
public void clear()
{ stacks_.clear(); }
// ISidedInventory ----------------------------------------------------------------------------
private final IItemHandler item_handler_ = new SidedInvWrapper(this, EnumFacing.UP);
private static final int[] SIDED_INV_SLOTS;
static {
SIDED_INV_SLOTS = new int[NUM_OF_SLOTS];
for(int i=0; i<NUM_OF_SLOTS; ++i) SIDED_INV_SLOTS[i] = i;
}
@Override
public int[] getSlotsForFace(EnumFacing side)
{ return SIDED_INV_SLOTS; }
@Override
public boolean canInsertItem(int index, ItemStack stack, EnumFacing direction)
{ return is_input_slot(index) && isItemValidForSlot(index, stack); }
@Override
public boolean canExtractItem(int index, ItemStack stack, EnumFacing direction)
{ return false; }
// Capability export ----------------------------------------------------------------------------
@Override
public boolean hasCapability(Capability<?> cap, EnumFacing facing)
{ return (cap==CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) || super.hasCapability(cap, facing); }
@Override
@SuppressWarnings("unchecked")
@Nullable
public <T> T getCapability(Capability<T> capability, @Nullable EnumFacing facing)
{
if(capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) return (T)item_handler_;
return super.getCapability(capability, facing);
}
// IPacketReceiver -------------------------------------------------------------------------------
@Override
public void onServerPacketReceived(NBTTagCompound nbt)
{}
@Override
public void onClientPacketReceived(EntityPlayer player, NBTTagCompound nbt)
{
if(nbt.hasKey("logic")) logic_ = nbt.getInteger("logic");
if(nbt.hasKey("manual_trigger") && (nbt.getInteger("manual_trigger")!=0)) { block_power_signal_=true; block_power_updated_=true; tick_timer_=1; }
markDirty();
}
// ITickable and aux methods ---------------------------------------------------------------------
private static int next_slot(int i)
{ return (i<NUM_OF_SLOTS-1) ? (i+1) : 0; }
private boolean spit_out(EnumFacing facing)
{
ItemStack drop = stacks_.get(current_slot_index_).copy();
stacks_.set(current_slot_index_, ItemStack.EMPTY);
for(int i=0; i<8; ++i) {
BlockPos p = pos.offset(facing, i);
if(!world.isAirBlock(p)) continue;
world.spawnEntity(new EntityItem(world, (p.getX()+0.5), (p.getY()+0.5), (p.getZ()+0.5), drop));
world.playSound(null, p, SoundEvents.ENTITY_ITEM_PICKUP, SoundCategory.BLOCKS, 0.7f, 0.8f);
break;
}
return true;
}
private static boolean place_item(ItemStack stack, EntityPlayer placer, World world, BlockPos pos, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
{
final Item place_item = stack.getItem();
Block place_block = (place_item instanceof IPlantable) ? (((IPlantable)place_item).getPlant(world, pos)).getBlock() : Block.getBlockFromItem(place_item);
if(((place_block==Blocks.AIR) || (place_block==null)) && ((place_item instanceof ItemBlockSpecial) && (((ItemBlockSpecial)place_item).getBlock()!=null))) place_block = ((ItemBlockSpecial)place_item).getBlock(); // Covers e.g. REEDS
if((place_block==null) || (place_block==Blocks.AIR)) return false;
Block block = world.getBlockState(pos).getBlock();
if(!block.isReplaceable(world, pos)) pos = pos.offset(facing);
if(!world.mayPlace(place_block, pos, true, facing, (Entity)null)) return false;
if(place_item instanceof ItemBlock) {
ItemBlock item = (ItemBlock)place_item;
int meta = item.getMetadata(stack.getMetadata());
final IBlockState state = item.getBlock().getStateForPlacement(world, pos, facing, hitX, hitY, hitZ, meta, placer, hand);
if(!item.placeBlockAt(stack, placer, world, pos, facing, hitX, hitY, hitZ, state)) return false;
} else if(place_item instanceof IPlantable) {
IPlantable item = (IPlantable)place_item;
final IBlockState state = item.getPlant(world, pos);
if(!world.setBlockState(pos, state, 1|2)) return false;
} else {
final IBlockState state = place_block.getDefaultState();
if(!world.setBlockState(pos, state, 1|2)) return false;
}
final IBlockState soundstate = world.getBlockState(pos);
final SoundType stype = soundstate.getBlock().getSoundType(soundstate, world, pos, placer);
world.playSound(placer, pos, stype.getPlaceSound(), SoundCategory.BLOCKS, (stype.getVolume()+1f)/8, stype.getPitch()*1.1f);
return true;
}
private boolean try_plant(BlockPos pos, final EnumFacing facing, final ItemStack stack, final Block plant_block)
{
final Item item = stack.getItem();
if((!(item instanceof ItemBlock)) && (!(item instanceof IPlantable)) && (!(plant_block instanceof IPlantable))) return spit_out(facing);
Block block = (plant_block instanceof IPlantable) ? plant_block : ((item instanceof IPlantable) ? (((IPlantable)item).getPlant(world, pos)).getBlock() : Block.getBlockFromItem(item));
if(item instanceof IPlantable) {
IBlockState st = ((IPlantable)item).getPlant(world, pos); // prefer block from getPlant
if(st!=null) block = st.getBlock();
}
if(world.isAirBlock(pos)) {
// plant here, block below has to be valid soil.
final IBlockState soilstate = world.getBlockState(pos.down());
if((block instanceof IPlantable) && (!soilstate.getBlock().canSustainPlant(soilstate, world, pos.down(), EnumFacing.UP, (IPlantable)block))) {
// Not the right soil for this plant.
return false;
}
} else {
// adjacent block is the soil, plant above if the soil is valid.
final IBlockState soilstate = world.getBlockState(pos);
if(soilstate.getBlock() == block) {
// The plant is already planted from the case above, it's not the assumed soil but the planted plant.
return false;
} else if(!world.isAirBlock(pos.up())) {
// If this is the soil an air block is needed above, if that is blocked we can't plant.
return false;
} else if((block instanceof IPlantable) && (!soilstate.getBlock().canSustainPlant(soilstate, world, pos, EnumFacing.UP, (IPlantable)block))) {
// Would be space above, but it's not the right soil for the plant.
return false;
} else {
// Ok, plant above.
pos = pos.up();
}
}
try {
//println("PLANT " + stack + " --> " + block + " at " + pos.subtract(getPos()) + "( item=" + item + ")");
final FakePlayer placer = net.minecraftforge.common.util.FakePlayerFactory.getMinecraft((net.minecraft.world.WorldServer)world);
if((placer==null) || (!place_item(stack, placer, world, pos, EnumHand.MAIN_HAND, EnumFacing.DOWN, 0.5f, 0f, 0.5f))) return spit_out(facing);
stack.shrink(1);
stacks_.set(current_slot_index_, stack);
return true;
} catch(Throwable e) {
ModEngineersDecor.logger.error("Exception while trying to plant " + e);
world.setBlockToAir(pos);
return spit_out(facing);
}
}
private boolean try_place(EnumFacing facing)
{
if(world.isRemote) return false;
BlockPos placement_pos = pos.offset(facing);
if(world.getTileEntity(placement_pos) != null) return false;
ItemStack current_stack = ItemStack.EMPTY;
for(int i=0; i<NUM_OF_SLOTS; ++i) {
if(current_slot_index_ >= NUM_OF_SLOTS) current_slot_index_ = 0;
current_stack = stacks_.get(current_slot_index_);
if(!current_stack.isEmpty()) break;
current_slot_index_ = next_slot(current_slot_index_);
}
if(current_stack.isEmpty()) { current_slot_index_ = 0; return false; }
final Item item = current_stack.getItem();
Block block = Block.getBlockFromItem(item);
if(((block==Blocks.AIR) || (block==null)) && ((item instanceof ItemBlockSpecial) && (((ItemBlockSpecial)item).getBlock()!=null))) block = ((ItemBlockSpecial)item).getBlock(); // e.g. reeds
if(item == null) return false;
if((item instanceof IPlantable) || (block instanceof IPlantable)) return try_plant(placement_pos, facing, current_stack, block);
if(block == Blocks.AIR) {
// Check special stuff that is not detected otherwise (like coco, which is technically dye)
try {
for(Entry<ItemStack,SpecialPlacementFunction> e:special_placement_conversions.entrySet()) {
if(e.getKey().isItemEqual(current_stack)) {
ItemStack placement_stack = current_stack.copy();
placement_stack.setCount(1);
switch(e.getValue().apply(current_stack, world, placement_pos)) {
case PASS:
return false;
case SUCCESS:
current_stack.shrink(1);
stacks_.set(current_slot_index_, current_stack);
return true;
default:
return false;
}
}
}
} catch(Throwable e) {
ModEngineersDecor.logger.error("Exception while trying to place " + e);
world.setBlockToAir(placement_pos);
}
return spit_out(facing);
}
if(world.getEntitiesWithinAABB(Entity.class, new AxisAlignedBB(placement_pos), Entity::canBeCollidedWith).size() > 0) return false;
if(!world.getBlockState(placement_pos).getBlock().isReplaceable(world, placement_pos)) return false;
try {
final FakePlayer placer = net.minecraftforge.common.util.FakePlayerFactory.getMinecraft((net.minecraft.world.WorldServer)world);
//println("PLACE ITEMBLOCK" + current_stack + " --> " + block + " at " + placement_pos.subtract(pos) + "( item=" + item + ")");
ItemStack placement_stack = current_stack.copy();
placement_stack.setCount(1);
if((placer==null) || (!place_item(placement_stack, placer, world, placement_pos, EnumHand.MAIN_HAND, EnumFacing.DOWN, 0.6f, 0f, 0.5f))) return false;
current_stack.shrink(1);
stacks_.set(current_slot_index_, current_stack);
} catch(Throwable e) {
// The block really needs a player or other issues happened during placement.
// A hard crash should not be fired here, instead spit out the item to indicated that this
// block is not compatible.
ModEngineersDecor.logger.error("Exception while trying to place " + e);
world.setBlockToAir(placement_pos);
return spit_out(facing);
}
return true;
}
@Override
public void update()
{
// Tick cycle pre-conditions
if(world.isRemote) return;
if(--tick_timer_ > 0) return;
tick_timer_ = TICK_INTERVAL;
final IBlockState state = world.getBlockState(pos);
if(!(state.getBlock() instanceof BlockDecorPlacer)) { block_power_signal_= false; return; }
// Cycle init
boolean dirty = block_power_updated_;
boolean rssignal = ((logic_ & LOGIC_INVERTED)!=0)==(!block_power_signal_);
boolean trigger = (rssignal && ((block_power_updated_) || ((logic_ & LOGIC_CONTINUOUS)!=0)));
final EnumFacing placer_facing = state.getValue(FACING);
// Trigger edge detection for next cycle
{
boolean tr = world.isBlockPowered(pos);
block_power_updated_ = (block_power_signal_ != tr);
block_power_signal_ = tr;
if(block_power_updated_) dirty = true;
}
// Placing
if(trigger) {
if(try_place(placer_facing)) {
dirty = true;
} else {
current_slot_index_ = next_slot(current_slot_index_);
}
}
if(dirty) markDirty();
if(trigger && (tick_timer_ > TICK_INTERVAL)) tick_timer_ = TICK_INTERVAL;
}
}
}

View file

@ -1,201 +0,0 @@
/*
* @file BlockDecorSlab.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Standard half block horizontal slab characteristics class.
*/
package wile.engineersdecor.blocks;
import wile.engineersdecor.detail.ModAuxiliaries;
import wile.engineersdecor.detail.ModConfig;
import net.minecraft.block.Block;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraft.block.properties.PropertyInteger;
import net.minecraft.block.state.BlockFaceShape;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.BlockRenderLayer;
import net.minecraft.util.EnumHand;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.IBlockAccess;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
public class BlockDecorSlab extends BlockDecor
{
public static final PropertyInteger PARTS = PropertyInteger.create("parts", 0, 2);
public static final PropertyInteger TEXTURE_VARIANT = PropertyInteger.create("tvariant", 0, 7);
protected static final AxisAlignedBB AABBs[] = {
new AxisAlignedBB(0, 0./16, 0, 1, 8./16, 1), // bottom slab
new AxisAlignedBB(0, 8./16, 0, 1, 16./16, 1), // top slab
new AxisAlignedBB(0, 0./16, 0, 1, 16./16, 1), // both slabs
new AxisAlignedBB(0, 0./16, 0, 1, 16./16, 1) // << 2bit fill
};
protected static final int num_slabs_contained_in_parts_[] = { 1,1,2,2 };
public BlockDecorSlab(@Nonnull String registryName, long config, @Nullable Material material, float hardness, float resistance, @Nullable SoundType sound)
{ super(registryName, config, material, hardness, resistance, sound); }
protected boolean is_cube(IBlockState state)
{ return state.getValue(PARTS) >= 2; }
@Override
@SideOnly(Side.CLIENT)
public void addInformation(ItemStack stack, @Nullable World world, List<String> tooltip, ITooltipFlag flag)
{
if(!ModAuxiliaries.Tooltip.addInformation(stack, world, tooltip, flag, true)) return;
if(!ModConfig.optout.without_direct_slab_pickup) {
ModAuxiliaries.Tooltip.addInformation("engineersdecor.tooltip.slabpickup", "engineersdecor.tooltip.slabpickup", tooltip, flag, true);
}
}
@Override
@SideOnly(Side.CLIENT)
public BlockRenderLayer getRenderLayer()
{ return (((config & CFG_TRANSLUCENT)!=0) ? (BlockRenderLayer.TRANSLUCENT) : (BlockRenderLayer.CUTOUT)); }
@Override
@SuppressWarnings("deprecation")
public IBlockState getStateFromMeta(int meta)
{ return getDefaultState().withProperty(PARTS, MathHelper.clamp(meta, 0, 2)); }
@Override
public int getMetaFromState(IBlockState state)
{ return state.getValue(PARTS); }
@Override
public IBlockState getActualState(IBlockState state, IBlockAccess world, BlockPos pos)
{
long prnd = pos.toLong(); prnd = (prnd>>29) ^ (prnd>>17) ^ (prnd>>9) ^ (prnd>>4) ^ pos.getX() ^ pos.getY() ^ pos.getZ();
return state.withProperty(TEXTURE_VARIANT, ((int)prnd) & 0x7);
}
@Override
protected BlockStateContainer createBlockState()
{ return new BlockStateContainer(this, PARTS, TEXTURE_VARIANT); }
@Override
@SuppressWarnings("deprecation")
public boolean isOpaqueCube(IBlockState state)
{ return ((config & CFG_TRANSLUCENT)==0) && is_cube(state); }
@Override
@SuppressWarnings("deprecation")
public BlockFaceShape getBlockFaceShape(IBlockAccess world, IBlockState state, BlockPos pos, EnumFacing face)
{ return (state.getValue(PARTS) >= 2) ? BlockFaceShape.SOLID : BlockFaceShape.UNDEFINED; }
@Override
@SuppressWarnings("deprecation")
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos)
{ return AABBs[state.getValue(PARTS) & 0x3]; }
@Override
@Nullable
public AxisAlignedBB getCollisionBoundingBox(IBlockState state, IBlockAccess world, BlockPos pos)
{ return getBoundingBox(state, world, pos); }
@Override
@SuppressWarnings("deprecation")
public boolean isFullCube(IBlockState state)
{ return is_cube(state); }
@Override
@SuppressWarnings("deprecation")
public boolean isNormalCube(IBlockState state)
{ return is_cube(state); }
@Override
@SuppressWarnings("deprecation")
public boolean canEntitySpawn(IBlockState state, Entity entity)
{ return false; }
@Override
public void harvestBlock(World world, EntityPlayer player, BlockPos pos, IBlockState state, @Nullable TileEntity te, ItemStack stack)
{ spawnAsEntity(world, pos, new ItemStack(Item.getItemFromBlock(this), num_slabs_contained_in_parts_[state.getValue(PARTS) & 0x3])); }
@Override
public boolean canPlaceBlockOnSide(World world, BlockPos pos, EnumFacing side)
{ return world.getBlockState(pos).getBlock() != this; }
@Override
@SuppressWarnings("deprecation")
public IBlockState getStateForPlacement(World world, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer)
{ return getDefaultState().withProperty(PARTS, ((facing==EnumFacing.UP) || ((facing!=EnumFacing.DOWN) && (hitY < 0.6))) ? 0 : 1); }
@Override
public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
{
final ItemStack stack = player.getHeldItem(hand);
if(stack.isEmpty() || (Block.getBlockFromItem(stack.getItem()) != this)) return false;
int parts = state.getValue(PARTS);
if(((facing == EnumFacing.UP) && (parts == 0)) || ((facing == EnumFacing.DOWN) && (parts == 1))) {
world.setBlockState(pos, state.withProperty(PARTS, 2), 3);
} else {
return false; // "not handled" -> let parent decide if a new slab has to be placed on top/bottom.
}
if(world.isRemote) return true;
if(!player.isCreative()) {
stack.shrink(1);
if(player.inventory != null) player.inventory.markDirty();
}
SoundType st = this.getSoundType(state, world, pos, null);
world.playSound(null, pos, st.getPlaceSound(), SoundCategory.BLOCKS, (st.getVolume()+1f)/2.5f, 0.9f*st.getPitch());
return true;
}
@Override
public void onBlockClicked(World world, BlockPos pos, EntityPlayer player)
{
if((world.isRemote) || (ModConfig.optout.without_direct_slab_pickup)) return;
final ItemStack stack = player.getHeldItemMainhand();
if(stack.isEmpty() || (Block.getBlockFromItem(stack.getItem()) != this)) return;
if(stack.getCount() >= stack.getMaxStackSize()) return;
Vec3d lv = player.getLookVec();
EnumFacing facing = EnumFacing.getFacingFromVector((float)lv.x, (float)lv.y, (float)lv.z);
if((facing != EnumFacing.UP) && (facing != EnumFacing.DOWN)) return;
IBlockState state = world.getBlockState(pos);
if(state.getBlock() != this) return;
int parts = state.getValue(PARTS);
if(facing == EnumFacing.DOWN) {
if(parts == 2) {
world.setBlockState(pos, state.withProperty(PARTS, 0), 3);
} else {
world.setBlockToAir(pos);
}
} else if(facing == EnumFacing.UP) {
if(parts == 2) {
world.setBlockState(pos, state.withProperty(PARTS, 1), 3);
} else {
world.setBlockToAir(pos);
}
}
if(!player.isCreative()) {
stack.grow(1);
if(player.inventory != null) player.inventory.markDirty(); // @todo: check if inventory can actually be null
}
SoundType st = this.getSoundType(state, world, pos, null);
world.playSound(player, pos, st.getPlaceSound(), SoundCategory.BLOCKS, (st.getVolume()+1f)/2.5f, 0.9f*st.getPitch());
}
}

View file

@ -1,220 +0,0 @@
/*
* @file BlockDecorDirected.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Smaller (cutout) block with a defined facing.
*/
package wile.engineersdecor.blocks;
import wile.engineersdecor.ModEngineersDecor;
import wile.engineersdecor.detail.ModAuxiliaries;
import net.minecraft.block.properties.PropertyInteger;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.BlockFaceShape;
import net.minecraft.block.state.IBlockState;
import net.minecraft.block.SoundType;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ITickable;
import net.minecraft.world.World;
import net.minecraft.world.IBlockAccess;
import net.minecraft.util.EnumHand;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraftforge.energy.CapabilityEnergy;
import net.minecraftforge.energy.IEnergyStorage;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class BlockDecorSolarPanel extends BlockDecor
{
//--------------------------------------------------------------------------------------------------------------------
// Config
//--------------------------------------------------------------------------------------------------------------------
private static int peak_power_per_tick_ = BTileEntity.DEFAULT_PEAK_POWER;
private static int max_power_storage_ = 10000;
private static int max_feed_power = 128;
public static void on_config(int peak_power_per_tick, int max_feed_power_per_tick)
{
peak_power_per_tick_ = peak_power_per_tick;
max_feed_power = max_feed_power_per_tick;
ModEngineersDecor.logger.info("Config small solar panel: Peak production:" + peak_power_per_tick_ + "/tick");
}
//--------------------------------------------------------------------------------------------------------------------
// Block
//--------------------------------------------------------------------------------------------------------------------
public static final PropertyInteger EXPOSITION = PropertyInteger.create("exposition", 0, 4);
public BlockDecorSolarPanel(@Nonnull String registryName, long config, @Nullable Material material, float hardness, float resistance, @Nullable SoundType sound, @Nonnull AxisAlignedBB unrotatedAABB)
{ super(registryName, config, material, hardness, resistance, sound, unrotatedAABB); }
@Override
public boolean isOpaqueCube(IBlockState state)
{ return false; }
@Override
public boolean isFullCube(IBlockState state)
{ return false; }
@Override
public boolean isNormalCube(IBlockState state)
{ return false; }
@Override
public boolean canCreatureSpawn(IBlockState state, IBlockAccess world, BlockPos pos, net.minecraft.entity.EntityLiving.SpawnPlacementType type)
{ return false; }
@Override
public int getLightValue(IBlockState state, IBlockAccess world, BlockPos pos)
{ return 0; }
@Override
public BlockFaceShape getBlockFaceShape(IBlockAccess world, IBlockState state, BlockPos pos, EnumFacing face)
{ return BlockFaceShape.UNDEFINED; }
@Override
public IBlockState getStateFromMeta(int meta)
{ return this.getDefaultState().withProperty(EXPOSITION, (meta & 0x7)); }
@Override
public int getMetaFromState(IBlockState state)
{ return state.getValue(EXPOSITION); }
@Override
protected BlockStateContainer createBlockState()
{ return new BlockStateContainer(this, EXPOSITION); }
@Override
public boolean canPlaceBlockOnSide(World world, BlockPos pos, EnumFacing side)
{ return super.canPlaceBlockOnSide(world, pos, side); }
@Override
public IBlockState getStateForPlacement(World world, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer, EnumHand hand)
{ return getDefaultState().withProperty(EXPOSITION, 0); }
@Override
public boolean hasTileEntity(IBlockState state)
{ return true; }
@Override
@Nullable
public TileEntity createTileEntity(World world, IBlockState state)
{ return new BlockDecorSolarPanel.BTileEntity(); }
@Override
public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
{
if(world.isRemote) return true;
TileEntity te = world.getTileEntity(pos);
if(!(te instanceof BTileEntity)) return true;
((BTileEntity)te).state_message(player);
return true;
}
//--------------------------------------------------------------------------------------------------------------------
// Tile entity
//--------------------------------------------------------------------------------------------------------------------
public static class BTileEntity extends TileEntity implements ITickable
{
public static final int DEFAULT_PEAK_POWER = 32;
public static final int TICK_INTERVAL = 8;
public static final int ACCUMULATION_INTERVAL = 4;
private static final EnumFacing transfer_directions_[] = {EnumFacing.DOWN, EnumFacing.EAST, EnumFacing.SOUTH, EnumFacing.WEST, EnumFacing.NORTH };
private int current_production_ = 0;
private int tick_timer_ = 0;
private int recalc_timer_ = 0;
private int accumulated_power_ = 0;
private int current_feedin_ = 0;
//------------------------------------------------------------------------------------------------------------------
public BTileEntity()
{}
public void readnbt(NBTTagCompound nbt, boolean update_packet)
{ accumulated_power_ = nbt.getInteger("energy"); }
protected void writenbt(NBTTagCompound nbt, boolean update_packet)
{ nbt.setInteger("energy", accumulated_power_); }
public void state_message(EntityPlayer player)
{
String soc = Integer.toString(MathHelper.clamp((accumulated_power_*100/max_power_storage_),0,100));
ModAuxiliaries.playerChatMessage(player, soc + "%%/" + max_power_storage_ + "RF | +" + + current_production_ + "RF/t | -" + current_feedin_ + "RF/t");
}
// TileEntity ------------------------------------------------------------------------------
@Override
public boolean shouldRefresh(World world, BlockPos pos, IBlockState os, IBlockState ns)
{ return (os.getBlock() != ns.getBlock()) || (!(ns.getBlock() instanceof BlockDecorSolarPanel)); }
@Override
public void readFromNBT(NBTTagCompound nbt)
{ super.readFromNBT(nbt); readnbt(nbt, false); }
@Override
public NBTTagCompound writeToNBT(NBTTagCompound nbt)
{ super.writeToNBT(nbt); writenbt(nbt, false); return nbt; }
@Override
public void update()
{
if((world.isRemote) || (--tick_timer_ > 0)) return;
tick_timer_ = TICK_INTERVAL;
final IBlockState state = world.getBlockState(pos);
if(!(state.getBlock() instanceof BlockDecorSolarPanel)) return;
current_feedin_ = 0;
if(accumulated_power_ > 0) {
for(int i=0; (i<transfer_directions_.length) && (accumulated_power_>0); ++i) {
final EnumFacing f = transfer_directions_[i];
TileEntity te = world.getTileEntity(pos.offset(f));
if((te==null) || (!(te.hasCapability(CapabilityEnergy.ENERGY, f.getOpposite())))) continue;
IEnergyStorage es = te.getCapability(CapabilityEnergy.ENERGY, f.getOpposite());
if(!es.canReceive()) continue;
int fed = es.receiveEnergy(max_feed_power * TICK_INTERVAL, false);
accumulated_power_ = MathHelper.clamp(accumulated_power_-fed,0, accumulated_power_);
current_feedin_ += fed;
}
}
current_feedin_ /= TICK_INTERVAL;
if(!world.canSeeSky(pos)) {
tick_timer_ = TICK_INTERVAL * 5;
current_production_ = 0;
if(state.getValue((EXPOSITION))!=2) world.setBlockState(pos, state.withProperty(EXPOSITION, 2));
return;
}
if(--recalc_timer_ > 0) return;
recalc_timer_ = ACCUMULATION_INTERVAL + ((int)(Math.random()+.5));
int theta = ((((int)(world.getCelestialAngleRadians(1f) * (180.0/Math.PI)))+90) % 360);
int e = 2;
if(theta > 340) e = 2;
else if(theta < 45) e = 0;
else if(theta < 80) e = 1;
else if(theta < 100) e = 2;
else if(theta < 135) e = 3;
else if(theta < 190) e = 4;
final IBlockState nstate = state.withProperty(EXPOSITION, e);
if(nstate != state) world.setBlockState(pos, nstate, 1|2);
final double eff = (1.0-((world.getRainStrength(1f)*0.6)+(world.getThunderStrength(1f)*0.3)));
final double rf = Math.sin((Math.PI/2) * Math.sqrt(((double)(((theta<0)||(theta>180))?(0):((theta>90)?(180-theta):(theta))))/90));
current_production_ = ((int)(Math.min(rf*rf*eff, 1) * peak_power_per_tick_));
accumulated_power_ = Math.min(accumulated_power_ + (current_production_*(TICK_INTERVAL*ACCUMULATION_INTERVAL)), max_power_storage_);
}
}
}

View file

@ -1,74 +0,0 @@
/*
* @file BlockDecorStairs.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Stairs and roof blocks, almost entirely based on vanilla stairs.
*/
package wile.engineersdecor.blocks;
import net.minecraft.block.material.EnumPushReaction;
import net.minecraft.block.state.IBlockState;
import net.minecraft.block.BlockStairs;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.item.ItemStack;
import net.minecraft.util.BlockRenderLayer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import wile.engineersdecor.ModEngineersDecor;
import wile.engineersdecor.detail.ModAuxiliaries;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
public class BlockDecorStairs extends BlockStairs
{
public BlockDecorStairs(@Nonnull String registryName, IBlockState modelState)
{
super(modelState);
setCreativeTab(ModEngineersDecor.CREATIVE_TAB_ENGINEERSDECOR);
setRegistryName(ModEngineersDecor.MODID, registryName);
setTranslationKey(ModEngineersDecor.MODID + "." + registryName);
setLightOpacity(0);
}
@Override
@SideOnly(Side.CLIENT)
public void addInformation(ItemStack stack, @Nullable World world, List<String> tooltip, ITooltipFlag flag)
{ ModAuxiliaries.Tooltip.addInformation(stack, world, tooltip, flag, true); }
@Override
@SuppressWarnings("deprecation")
public boolean isOpaqueCube(IBlockState state)
{ return false; }
@Override
@SuppressWarnings("deprecation")
public boolean isFullCube(IBlockState state)
{ return false; }
@Override
@SuppressWarnings("deprecation")
public boolean isNormalCube(IBlockState state)
{ return false; }
@Override
public boolean canSpawnInBlock()
{ return false; }
@Override
public boolean canCreatureSpawn(IBlockState state, IBlockAccess world, BlockPos pos, net.minecraft.entity.EntityLiving.SpawnPlacementType type)
{ return false; }
@Override
@SuppressWarnings("deprecation")
public EnumPushReaction getPushReaction(IBlockState state)
{ return EnumPushReaction.NORMAL; }
}

View file

@ -1,40 +0,0 @@
/*
* @file BlockDecorStraightPole.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Smaller (cutout) block with a defined facing.
*/
package wile.engineersdecor.blocks;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.util.EnumHand;
import net.minecraft.world.World;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class BlockDecorStraightPole extends BlockDecorDirected
{
public BlockDecorStraightPole(@Nonnull String registryName, long config, @Nullable Material material, float hardness, float resistance, @Nullable SoundType sound, @Nonnull AxisAlignedBB unrotatedAABB)
{ super(registryName, config, material, hardness, resistance, sound, unrotatedAABB); }
@Override
public IBlockState getStateForPlacement(World world, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer, EnumHand hand)
{
IBlockState state = super.getStateForPlacement(world, pos, facing, hitX, hitY, hitZ, meta, placer, hand);
if((config & CFG_FLIP_PLACEMENT_IF_SAME) != 0) {
if(world.getBlockState(pos.offset(facing.getOpposite())).getBlock() instanceof BlockDecorStraightPole) {
state = state.withProperty(FACING, state.getValue(FACING).getOpposite());
}
}
return state;
}
}

View file

@ -1,113 +0,0 @@
/*
* @file BlockDecorTest.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Smaller (cutout) block with a defined facing.
*/
package wile.engineersdecor.blocks;
import wile.engineersdecor.detail.ModAuxiliaries;
import net.minecraft.world.World;
import net.minecraft.block.state.IBlockState;
import net.minecraft.block.material.Material;
import net.minecraft.block.SoundType;
import net.minecraft.entity.passive.EntityCow;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.ITickable;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.AxisAlignedBB;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
import java.util.UUID;
public class BlockDecorTest extends BlockDecorDirected implements ModAuxiliaries.IExperimentalFeature
{
public BlockDecorTest(@Nonnull String registryName, long config, @Nullable Material material, float hardness, float resistance, @Nullable SoundType sound, @Nonnull AxisAlignedBB unrotatedAABB)
{ super(registryName, config, material, hardness, resistance, sound, unrotatedAABB); }
@Override
public boolean hasTileEntity(IBlockState state)
{ return true; }
@Override
public TileEntity createTileEntity(World world, IBlockState state)
{ return new BTileEntity(); }
@Override
public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
{ return clicked(world, pos, player, false); }
@Override
public void onBlockClicked(World world, BlockPos pos, EntityPlayer player)
{ clicked(world, pos, player, true); }
private boolean clicked(World world, BlockPos pos, EntityPlayer player, boolean lclick)
{ TileEntity te = world.getTileEntity(pos); return (te instanceof BTileEntity) && ((BTileEntity)te).clicked(player, lclick); }
//--------------------------------------------------------------------------------------------------------------------
// Tile entity
//--------------------------------------------------------------------------------------------------------------------
public static class BTileEntity extends TileEntity implements ITickable
{
private static int tick_interval_ = 40;
private int tick_timer_ = 0;
public BTileEntity()
{}
@Override
public boolean shouldRefresh(World world, BlockPos pos, IBlockState os, IBlockState ns)
{ return (os.getBlock() != ns.getBlock()) || (!(ns.getBlock() instanceof BlockDecorTest)); }
//------------------------------------------------------------------------------------------------------------------
public static double increment = 0.008;
private boolean TESR_TEST = false;
private double progress_ = -1;
private double incr_ = increment;
public double progress() { return progress_; }
private void tesr_basic_test(boolean reset)
{
if(!TESR_TEST || !world.isRemote) return;
if(reset) {
progress_ = 0; incr_ = increment;
} else {
progress_ += incr_;
if(progress_ < 0) {
incr_ = increment;
progress_ = 0;
} else if(progress_ > 1.0) {
progress_ = 1.0;
incr_ = -increment;
}
}
}
//------------------------------------------------------------------------------------------------------------------
public boolean clicked(EntityPlayer player, boolean lclicked)
{
tesr_basic_test(true);
return true;
}
@Override
public void update()
{
tesr_basic_test(false);
if(++tick_timer_ < tick_interval_) return;
tick_timer_ = tick_interval_;
}
}
}

View file

@ -1,273 +0,0 @@
/*
* @file BlockDecorTreeCutter.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Small Tree Cutter
*/
package wile.engineersdecor.blocks;
import wile.engineersdecor.ModEngineersDecor;
import wile.engineersdecor.detail.ModAuxiliaries;
import wile.engineersdecor.detail.TreeCutting;
import net.minecraft.block.properties.PropertyBool;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.world.World;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.init.SoundEvents;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.*;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.energy.CapabilityEnergy;
import net.minecraftforge.energy.IEnergyStorage;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Random;
public class BlockDecorTreeCutter extends BlockDecorDirectedHorizontal
{
//--------------------------------------------------------------------------------------------------------------------
// Config
//--------------------------------------------------------------------------------------------------------------------
public static final int IDLE_TICK_INTERVAL = 40;
public static final int TICK_INTERVAL = 5;
public static final int BOOST_FACTOR = 6;
public static final int DEFAULT_BOOST_ENERGY = 64;
public static final int DEFAULT_CUTTING_TIME_NEEDED = 60; // 60 secs, so that people don't come to the bright idea to carry one with them.
private static int energy_max = DEFAULT_BOOST_ENERGY * 20;
private static int boost_energy_consumption = DEFAULT_BOOST_ENERGY;
private static int cutting_time_needed = 20 * DEFAULT_CUTTING_TIME_NEEDED;
private static boolean requires_power = false;
public static void on_config(int boost_energy_per_tick, int cutting_time_seconds, boolean power_required)
{
boost_energy_consumption = TICK_INTERVAL * MathHelper.clamp(boost_energy_per_tick, 16, 512);
energy_max = Math.max(boost_energy_consumption * 10, 10000);
cutting_time_needed = 20 * MathHelper.clamp(cutting_time_seconds, 10, 240);
requires_power = power_required;
ModEngineersDecor.logger.info("Config tree cutter: Boost energy consumption:" + boost_energy_consumption + "rf/t" + (requires_power?" (power required for operation) ":"") + ", cutting time " + cutting_time_needed + "t." );
}
//--------------------------------------------------------------------------------------------------------------------
// Block
//--------------------------------------------------------------------------------------------------------------------
public static final PropertyBool ACTIVE = PropertyBool.create("active");
public BlockDecorTreeCutter(@Nonnull String registryName, long config, @Nullable Material material, float hardness, float resistance, @Nullable SoundType sound, @Nonnull AxisAlignedBB unrotatedAABB)
{
super(registryName, config, material, hardness, resistance, sound, unrotatedAABB);
setLightOpacity(0);
}
@Override
protected BlockStateContainer createBlockState()
{ return new BlockStateContainer(this, FACING, ACTIVE); }
@Override
public IBlockState getStateFromMeta(int meta)
{ return getDefaultState().withProperty(FACING, EnumFacing.byHorizontalIndex(meta & 0x3)).withProperty(ACTIVE, (meta & 0x4)!=0); }
@Override
public int getMetaFromState(IBlockState state)
{ return (state.getValue(FACING).getHorizontalIndex() & 0x3) | (state.getValue(ACTIVE) ? 4 : 0); }
@Override
public IBlockState getStateForPlacement(World world, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer, EnumHand hand)
{ return super.getStateForPlacement(world, pos, facing, hitX, hitY, hitZ, meta, placer, hand).withProperty(ACTIVE, false); }
@Override
public boolean hasTileEntity(IBlockState state)
{ return true; }
@Override
@Nullable
public TileEntity createTileEntity(World world, IBlockState state)
{ return new BlockDecorTreeCutter.BTileEntity(); }
@Override
@SideOnly(Side.CLIENT)
public void randomDisplayTick(IBlockState state, World world, BlockPos pos, Random rnd)
{
if((state.getBlock()!=this) || (!state.getValue(ACTIVE))) return;
final double rv = rnd.nextDouble();
if(rv > 0.8) return;
final double x=0.5+pos.getX(), y=0.5+pos.getY(), z=0.5+pos.getZ();
final double xc=0.52, xr=rnd.nextDouble()*0.4-0.2, yr=(y-0.3+rnd.nextDouble()*0.2);
switch(state.getValue(FACING)) {
case WEST: world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, x-xc, yr, z+xr, 0.0, 0.0, 0.0); break;
case EAST: world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, x+xc, yr, z+xr, 0.0, 0.0, 0.0); break;
case NORTH: world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, x+xr, yr, z-xc, 0.0, 0.0, 0.0); break;
default: world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, x+xr, yr, z+xc, 0.0, 0.0, 0.0); break;
}
}
@Override
public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
{
if(world.isRemote) return true;
TileEntity te = world.getTileEntity(pos);
if(!(te instanceof BTileEntity)) return true;
((BTileEntity)te).state_message(player);
return true;
}
//--------------------------------------------------------------------------------------------------------------------
// Tile entity
//--------------------------------------------------------------------------------------------------------------------
public static class BTileEntity extends TileEntity implements ITickable, IEnergyStorage
{
private int tick_timer_;
private int active_timer_;
private int proc_time_elapsed_; // small, not saved in nbt.
private int energy_; // small, not saved in nbt.
public BTileEntity()
{}
public void state_message(EntityPlayer player)
{
String soc = Integer.toString(MathHelper.clamp((energy_*100/energy_max),0,100));
String progress = "";
if((active_timer_ > 0) && (cutting_time_needed > 0)) {
progress = " | " + Integer.toString((int)MathHelper.clamp((((double)proc_time_elapsed_) / ((double)cutting_time_needed) * 100), 0, 100)) + "%%";
}
ModAuxiliaries.playerChatMessage(player, soc + "%%/" + energy_max + "RF" + progress);
}
public void readnbt(NBTTagCompound nbt)
{ energy_ = nbt.getInteger("energy"); }
private void writenbt(NBTTagCompound nbt)
{ nbt.setInteger("energy", energy_); }
// TileEntity ------------------------------------------------------------------------------
@Override
public boolean shouldRefresh(World world, BlockPos pos, IBlockState os, IBlockState ns)
{ return (os.getBlock() != ns.getBlock()) || (!(ns.getBlock() instanceof BlockDecorTreeCutter)); }
@Override
public void readFromNBT(NBTTagCompound nbt)
{ super.readFromNBT(nbt); readnbt(nbt); }
@Override
public NBTTagCompound writeToNBT(NBTTagCompound nbt)
{ super.writeToNBT(nbt); writenbt(nbt); return nbt; }
// IEnergyStorage ----------------------------------------------------------------------------
@Override
public boolean canExtract()
{ return false; }
@Override
public boolean canReceive()
{ return true; }
@Override
public int getMaxEnergyStored()
{ return boost_energy_consumption*2; }
@Override
public int getEnergyStored()
{ return energy_; }
@Override
public int extractEnergy(int maxExtract, boolean simulate)
{ return 0; }
@Override
public int receiveEnergy(int maxReceive, boolean simulate)
{
maxReceive = MathHelper.clamp(maxReceive, 0, Math.max((energy_max) - energy_, 0));
if(!simulate) energy_ += maxReceive;
return maxReceive;
}
// Capability export ----------------------------------------------------------------------------
@Override
public boolean hasCapability(Capability<?> cap, EnumFacing facing)
{ return ((cap==CapabilityEnergy.ENERGY)) || super.hasCapability(cap, facing); }
@Override
@SuppressWarnings("unchecked")
@Nullable
public <T> T getCapability(Capability<T> capability, @Nullable EnumFacing facing)
{
if(capability == CapabilityEnergy.ENERGY) {
return (T)this;
} else {
return super.getCapability(capability, facing);
}
}
// ITickable ------------------------------------------------------------------------------------
@Override
public void update()
{
if(--tick_timer_ > 0) return;
final IBlockState device_state = world.getBlockState(pos);
if(!(device_state.getBlock() instanceof BlockDecorTreeCutter)) { tick_timer_ = TICK_INTERVAL; return; }
if(world.isRemote) {
if(!device_state.getValue(ACTIVE)) {
tick_timer_ = TICK_INTERVAL;
} else {
tick_timer_ = 1;
world.playSound(pos.getX(), pos.getY(), pos.getZ(), SoundEvents.BLOCK_WOOD_HIT, SoundCategory.BLOCKS, 0.1f, 1.0f, false);
}
} else {
tick_timer_ = TICK_INTERVAL;
final BlockPos tree_pos = pos.offset(device_state.getValue(FACING));
final IBlockState tree_state = world.getBlockState(tree_pos);
if(!TreeCutting.canChop(tree_state) || (world.isBlockPowered(pos))) {
if(device_state.getValue(ACTIVE)) world.setBlockState(pos, device_state.withProperty(ACTIVE, false), 1|2);
proc_time_elapsed_ = 0;
active_timer_ = 0;
tick_timer_ = IDLE_TICK_INTERVAL;
return;
}
proc_time_elapsed_ += TICK_INTERVAL;
if(energy_ >= boost_energy_consumption) {
energy_ -= boost_energy_consumption;
proc_time_elapsed_ += TICK_INTERVAL*BOOST_FACTOR;
active_timer_ = 2;
} else if(!requires_power) {
active_timer_ = 1024;
} else if(active_timer_ > 0) {
--active_timer_;
}
boolean active = (active_timer_ > 0);
if(requires_power && !active) {
proc_time_elapsed_ = Math.max(0, proc_time_elapsed_ - 2*TICK_INTERVAL);
}
if(proc_time_elapsed_ >= cutting_time_needed) {
proc_time_elapsed_ = 0;
TreeCutting.chopTree(world, tree_state, tree_pos, 2048, false);
world.playSound(null, pos.getX(), pos.getY(), pos.getZ(), SoundEvents.BLOCK_WOOD_BREAK, SoundCategory.BLOCKS, 1.0f, 1.0f);
active = false;
}
if(device_state.getValue(ACTIVE) != active) {
world.setBlockState(pos, device_state.withProperty(ACTIVE, active), 1|2);
}
}
}
}
}

View file

@ -1,239 +0,0 @@
/*
* @file BlockDecorWall.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Wall blocks. This block is derived from vanilla BlockWall
*/
package wile.engineersdecor.blocks;
import wile.engineersdecor.detail.ModAuxiliaries;
import net.minecraft.block.*;
import net.minecraft.block.material.Material;
import net.minecraft.block.properties.IProperty;
import net.minecraft.block.properties.PropertyBool;
import net.minecraft.block.properties.PropertyInteger;
import net.minecraft.block.state.BlockFaceShape;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.Entity;
import net.minecraft.init.Blocks;
import net.minecraft.pathfinding.PathNodeType;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
/**
* As strange as it is, I could not properly get a block derived from BlockWall working,
* either the VARIANT made issues, or the item model was duplicated (using state mapper),
* so, this is now basically a BlockWall without the VARIANT propery. Anyway a solved issue
* in mc1.13+. Deriving from BlockDecor to have the tooltip, creativetab etc already set up.
*/
public class BlockDecorWall extends BlockDecor
{
public static final PropertyBool UP = BlockWall.UP;
public static final PropertyBool NORTH = BlockWall.NORTH;
public static final PropertyBool EAST = BlockWall.EAST;
public static final PropertyBool SOUTH = BlockWall.SOUTH;
public static final PropertyBool WEST = BlockWall.WEST;
public static final PropertyInteger TEXTURE_VARIANT = PropertyInteger.create("tvariant", 0, 7);
protected static final AxisAlignedBB[] mkAABBs(double pole_thickness_px, double wall_thickness_px, double height_px)
{
final double d_0 = 0.0d;
final double d_1 = 16.0d;
final double d_a = (8d-pole_thickness_px);
final double d_b = 16.0d-d_a;
final double d_k = (8d-wall_thickness_px);
final double d_l = 16.0d-d_k;
return new AxisAlignedBB[] { // ENWS P
ModAuxiliaries.getPixeledAABB(d_a, d_0, d_a, d_b, height_px, d_b), // 0000 1
ModAuxiliaries.getPixeledAABB(d_a, d_0, d_a, d_b, height_px, d_1), // 0001 1
ModAuxiliaries.getPixeledAABB(d_0, d_0, d_a, d_b, height_px, d_b), // 0010 1
ModAuxiliaries.getPixeledAABB(d_0, d_0, d_a, d_b, height_px, d_1), // 0011 1
ModAuxiliaries.getPixeledAABB(d_a, d_0, d_0, d_b, height_px, d_b), // 0100 1
ModAuxiliaries.getPixeledAABB(d_k, d_0, d_0, d_l, height_px, d_1), // 0101 0
ModAuxiliaries.getPixeledAABB(d_0, d_0, d_0, d_b, height_px, d_b), // 0110 1
ModAuxiliaries.getPixeledAABB(d_0, d_0, d_0, d_b, height_px, d_1), // 0111 1
ModAuxiliaries.getPixeledAABB(d_a, d_0, d_a, d_1, height_px, d_b), // 1000 1
ModAuxiliaries.getPixeledAABB(d_a, d_0, d_a, d_1, height_px, d_1), // 1001 1
ModAuxiliaries.getPixeledAABB(d_0, d_0, d_k, d_1, height_px, d_l), // 1010 0
ModAuxiliaries.getPixeledAABB(d_0, d_0, d_a, d_1, height_px, d_1), // 1011 1
ModAuxiliaries.getPixeledAABB(d_a, d_0, d_0, d_1, height_px, d_b), // 1100 1
ModAuxiliaries.getPixeledAABB(d_a, d_0, d_0, d_1, height_px, d_1), // 1101 1
ModAuxiliaries.getPixeledAABB(d_0, d_0, d_0, d_1, height_px, d_b), // 1110 1
ModAuxiliaries.getPixeledAABB(d_0, d_0, d_0, d_1, height_px, d_1) // 1111 1
};
}
protected static final AxisAlignedBB[][] mkCAABBs(double pole_thickness_px, double wall_thickness_px, double height_px)
{
final double d_0 = 0.0d;
final double d_1 = 16.0d;
final double d_a = (8d-pole_thickness_px);
final double d_b = 16.0d-d_a;
final double d_k = (8d-wall_thickness_px);
final double d_l = 16.0d-d_k;
final AxisAlignedBB bb_p = ModAuxiliaries.getPixeledAABB(d_a, d_0, d_a, d_b, height_px, d_b); // 0000
final AxisAlignedBB bb_s = ModAuxiliaries.getPixeledAABB(d_k, d_0, d_k, d_l, height_px, d_1); // 0001
final AxisAlignedBB bb_w = ModAuxiliaries.getPixeledAABB(d_0, d_0, d_k, d_l, height_px, d_l); // 0010
final AxisAlignedBB bb_n = ModAuxiliaries.getPixeledAABB(d_k, d_0, d_0, d_l, height_px, d_l); // 0100
final AxisAlignedBB bb_e = ModAuxiliaries.getPixeledAABB(d_k, d_0, d_k, d_1, height_px, d_l); // 1000
return new AxisAlignedBB[][] { // ENWS P
new AxisAlignedBB[]{ bb_p }, // 0000 1
new AxisAlignedBB[]{ bb_s }, // 0001 1
new AxisAlignedBB[]{ bb_w }, // 0010 1
new AxisAlignedBB[]{ bb_s,bb_w }, // 0011 1
new AxisAlignedBB[]{ bb_n }, // 0100 1
new AxisAlignedBB[]{ bb_n,bb_s }, // 0101 0
new AxisAlignedBB[]{ bb_n,bb_w }, // 0110 1
new AxisAlignedBB[]{ bb_n,bb_w,bb_s }, // 0111 1
new AxisAlignedBB[]{ bb_e }, // 1000 1
new AxisAlignedBB[]{ bb_e,bb_s }, // 1001 1
new AxisAlignedBB[]{ bb_e,bb_w }, // 1010 0
new AxisAlignedBB[]{ bb_e,bb_w,bb_s }, // 1011 1
new AxisAlignedBB[]{ bb_e,bb_n }, // 1100 1
new AxisAlignedBB[]{ bb_e,bb_n,bb_s }, // 1101 1
new AxisAlignedBB[]{ bb_e,bb_n,bb_w }, // 1110 1
new AxisAlignedBB[]{ bb_e,bb_n,bb_w,bb_s } // 1111 1
};
}
protected static final AxisAlignedBB[] AABB_BY_INDEX = mkAABBs(4d, 3.84, 16d);
protected static final AxisAlignedBB[] CLIP_AABB_BY_INDEX = mkAABBs(4d, 3.84, 24d);
protected static final AxisAlignedBB[][] AABB_LIST_BY_INDEX = mkCAABBs(4d, 3.84, 16d);
protected static final AxisAlignedBB[][] CLIP_AABB_LIST_BY_INDEX = mkCAABBs(4d, 3.84, 24d);
protected static final AxisAlignedBB SELECTION_AABB = ModAuxiliaries.getPixeledAABB(0, 0, 0, 0.01, 0.01, 0.01);
public BlockDecorWall(@Nonnull String registryName, long config, @Nullable Material material, float hardness, float resistance, @Nullable SoundType sound)
{
super(registryName, config, material, hardness, resistance, sound);
setDefaultState(blockState.getBaseState().withProperty(UP, false).withProperty(NORTH, false).withProperty(EAST, false).withProperty(SOUTH, false).withProperty(WEST, false));
}
@Override
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos)
{ return AABB_BY_INDEX[getAABBIndex(getActualState(state, source, pos))]; }
@Override
@SuppressWarnings("deprecation")
public void addCollisionBoxToList(IBlockState state, World world, BlockPos pos, AxisAlignedBB entityBox, List<AxisAlignedBB> collidingBoxes, @Nullable Entity entityIn, boolean isActualState)
{
final AxisAlignedBB[] bbs = CLIP_AABB_LIST_BY_INDEX[getAABBIndex(isActualState ? state : getActualState(state, world, pos))];
for(int i=0; i<bbs.length;++i) addCollisionBoxToList(pos, entityBox, collidingBoxes, bbs[i]);
}
@Nullable
@Override
public AxisAlignedBB getCollisionBoundingBox(IBlockState state, IBlockAccess world, BlockPos pos)
{ return CLIP_AABB_BY_INDEX[getAABBIndex(getActualState(state, world, pos))]; }
@Override
@SideOnly(Side.CLIENT)
@SuppressWarnings("deprecation")
public AxisAlignedBB getSelectedBoundingBox(IBlockState state, World world, BlockPos pos)
{ return SELECTION_AABB; }
protected static int getAABBIndex(IBlockState state)
{ return ((!(state.getValue(SOUTH))) ? 0 : (1<<EnumFacing.SOUTH.getHorizontalIndex())) // 0
| ((!(state.getValue( WEST))) ? 0 : (1<<EnumFacing.WEST.getHorizontalIndex())) // 1
| ((!(state.getValue(NORTH))) ? 0 : (1<<EnumFacing.NORTH.getHorizontalIndex())) // 2
| ((!(state.getValue( EAST))) ? 0 : (1<<EnumFacing.EAST.getHorizontalIndex())); // 3
}
@Override
public boolean isFullCube(IBlockState state)
{ return false; }
@Override
public boolean isPassable(IBlockAccess world, BlockPos pos)
{ return false; }
@Override
public boolean isOpaqueCube(IBlockState state)
{ return false; }
@Override
public boolean isNormalCube(IBlockState state)
{ return false; }
@Override
public boolean canCreatureSpawn(IBlockState state, IBlockAccess world, BlockPos pos, net.minecraft.entity.EntityLiving.SpawnPlacementType type)
{ return false; }
@Override
public boolean canSpawnInBlock()
{ return false; }
protected boolean canConnectTo(IBlockAccess world, BlockPos pos, BlockPos other, EnumFacing facing)
{
final IBlockState state = world.getBlockState(other);
final Block block = state.getBlock();
if((block instanceof BlockDecorWall) || (block instanceof BlockFenceGate) || (block instanceof BlockDecorFence) || (block instanceof BlockDecorDoubleGate)) return true;
if(world.getBlockState(pos.offset(facing)).getBlock()!=this) return false;
if(block instanceof BlockFence) return true;
final BlockFaceShape shp = state.getBlockFaceShape(world, other, facing);
return (shp == BlockFaceShape.SOLID) && (!isExcepBlockForAttachWithPiston(block));
}
protected static boolean isExcepBlockForAttachWithPiston(Block b)
{ return Block.isExceptBlockForAttachWithPiston(b) || (b==Blocks.BARRIER) || (b==Blocks.MELON_BLOCK) || (b==Blocks.PUMPKIN) || (b==Blocks.LIT_PUMPKIN); }
@Override
@SideOnly(Side.CLIENT)
public boolean shouldSideBeRendered(IBlockState blockState, IBlockAccess blockAccess, BlockPos pos, EnumFacing side)
{ return (side!=EnumFacing.DOWN) || (super.shouldSideBeRendered(blockState, blockAccess, pos, side)); }
@Override
public IBlockState getStateFromMeta(int meta)
{ return getDefaultState(); }
@Override
public int getMetaFromState(IBlockState state)
{ return 0; }
@Override
public IBlockState getActualState(IBlockState state, IBlockAccess world, BlockPos pos)
{
boolean n = canWallConnectTo(world, pos, EnumFacing.NORTH);
boolean e = canWallConnectTo(world, pos, EnumFacing.EAST);
boolean s = canWallConnectTo(world, pos, EnumFacing.SOUTH);
boolean w = canWallConnectTo(world, pos, EnumFacing.WEST);
boolean nopole = (n && s && !e && !w) || (!n && !s && e && w);
long prnd = pos.toLong(); prnd = (prnd>>29) ^ (prnd>>17) ^ (prnd>>9) ^ (prnd>>4) ^ pos.getX() ^ pos.getY() ^ pos.getZ();
return state.withProperty(UP,!nopole).withProperty(NORTH, n).withProperty(EAST, e).withProperty(SOUTH, s).withProperty(WEST, w).withProperty(TEXTURE_VARIANT, ((int)prnd) & 0x7);
}
@Override
protected BlockStateContainer createBlockState()
{ return new BlockStateContainer(this, new IProperty[] {UP, NORTH, EAST, WEST, SOUTH, TEXTURE_VARIANT}); }
@Override
public BlockFaceShape getBlockFaceShape(IBlockAccess world, IBlockState state, BlockPos pos, EnumFacing face)
{ return (face==EnumFacing.UP) ? (BlockFaceShape.CENTER) : ((face!=EnumFacing.DOWN) ? (BlockFaceShape.MIDDLE_POLE_THICK) : (BlockFaceShape.CENTER_BIG)); }
@Override
public boolean canBeConnectedTo(IBlockAccess world, BlockPos pos, EnumFacing facing)
{ return canConnectTo(world, pos, pos.offset(facing), facing.getOpposite()); }
protected boolean canWallConnectTo(IBlockAccess world, BlockPos pos, EnumFacing facing)
{ return canConnectTo(world, pos, pos.offset(facing), facing.getOpposite()); }
@Override
public boolean canPlaceTorchOnTop(IBlockState state, IBlockAccess world, BlockPos pos)
{ return true; }
@Override
public net.minecraft.pathfinding.PathNodeType getAiPathNodeType(IBlockState state, IBlockAccess world, BlockPos pos)
{ return PathNodeType.FENCE; }
}

View file

@ -1,705 +0,0 @@
/*
* @file BlockDecorWasteIncinerator.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Trash/void/nullifier device with internal fifos.
*/
package wile.engineersdecor.blocks;
import wile.engineersdecor.ModEngineersDecor;
import net.minecraft.block.properties.PropertyBool;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.Block;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.world.World;
import net.minecraft.world.Explosion;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.init.SoundEvents;
import net.minecraft.item.*;
import net.minecraft.inventory.*;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentTranslation;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.*;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.energy.CapabilityEnergy;
import net.minecraftforge.energy.IEnergyStorage;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Random;
public class BlockDecorWasteIncinerator extends BlockDecor
{
public static final PropertyBool LIT = BlockDecorFurnace.LIT;
public BlockDecorWasteIncinerator(@Nonnull String registryName, long config, @Nullable Material material, float hardness, float resistance, @Nullable SoundType sound, @Nonnull AxisAlignedBB unrotatedAABB)
{
super(registryName, config, material, hardness, resistance, sound, unrotatedAABB);
setLightOpacity(0);
}
@Override
protected BlockStateContainer createBlockState()
{ return new BlockStateContainer(this, LIT); }
@Override
public IBlockState getStateFromMeta(int meta)
{ return getDefaultState().withProperty(LIT, (meta & 0x4)!=0); }
@Override
public int getMetaFromState(IBlockState state)
{ return (state.getValue(LIT) ? 4 : 0); }
@Override
public IBlockState getStateForPlacement(World world, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer, EnumHand hand)
{ return getDefaultState().withProperty(LIT, false); }
@Override
@SuppressWarnings("deprecation")
public boolean hasComparatorInputOverride(IBlockState state)
{ return true; }
@Override
@SuppressWarnings("deprecation")
public int getComparatorInputOverride(IBlockState blockState, World world, BlockPos pos)
{ return Container.calcRedstone(world.getTileEntity(pos)); }
@Override
public boolean hasTileEntity(IBlockState state)
{ return true; }
@Nullable
public TileEntity createTileEntity(World world, IBlockState state)
{ return new BlockDecorWasteIncinerator.BTileEntity(); }
@Override
public void onBlockPlacedBy(World world, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack)
{
if(world.isRemote) return;
if((!stack.hasTagCompound()) || (!stack.getTagCompound().hasKey("inventory"))) return;
NBTTagCompound inventory_nbt = stack.getTagCompound().getCompoundTag("inventory");
if(inventory_nbt.isEmpty()) return;
final TileEntity te = world.getTileEntity(pos);
if(!(te instanceof BlockDecorWasteIncinerator.BTileEntity)) return;
((BlockDecorWasteIncinerator.BTileEntity)te).readnbt(inventory_nbt);
((BlockDecorWasteIncinerator.BTileEntity)te).markDirty();
}
@Override
public boolean removedByPlayer(IBlockState state, World world, BlockPos pos, EntityPlayer player, boolean willHarvest)
{
if(world.isRemote) return true;
TileEntity te = world.getTileEntity(pos);
if(!(te instanceof BTileEntity)) return super.removedByPlayer(state, world, pos, player, willHarvest);
ItemStack stack = new ItemStack(this, 1);
NBTTagCompound inventory_nbt = new NBTTagCompound();
ItemStackHelper.saveAllItems(inventory_nbt, ((BTileEntity)te).stacks_, false);
if(!inventory_nbt.isEmpty()) {
NBTTagCompound nbt = new NBTTagCompound();
nbt.setTag("inventory", inventory_nbt);
stack.setTagCompound(nbt);
}
world.spawnEntity(new EntityItem(world, pos.getX()+0.5, pos.getY()+0.5, pos.getZ()+0.5, stack));
world.setBlockToAir(pos);
world.removeTileEntity(pos);
return false;
}
@Override
public void onBlockExploded(World world, BlockPos pos, Explosion explosion)
{
if(world.isRemote) return;
TileEntity te = world.getTileEntity(pos);
if(!(te instanceof BTileEntity)) return;
for(ItemStack stack: ((BTileEntity)te).stacks_) {
if(!stack.isEmpty()) world.spawnEntity(new EntityItem(world, pos.getX(), pos.getY(), pos.getZ(), stack));
}
((BTileEntity)te).reset();
super.onBlockExploded(world, pos, explosion);
}
@Override
public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
{
if(world.isRemote) return true;
player.openGui(ModEngineersDecor.instance, ModEngineersDecor.GuiHandler.GUIID_SMALL_WASTE_INCINERATOR, world, pos.getX(), pos.getY(), pos.getZ());
return true;
}
@Override
@SideOnly(Side.CLIENT)
public void randomDisplayTick(IBlockState state, World world, BlockPos pos, Random rnd)
{
if((state.getBlock()!=this) || (!state.getValue(LIT))) return;
final double rv = rnd.nextDouble();
if(rv > 0.5) return;
final double x=0.5+pos.getX(), y=0.5+pos.getY(), z=0.5+pos.getZ();
final double xr=rnd.nextDouble()*0.4-0.2, yr=rnd.nextDouble()*0.5, zr=rnd.nextDouble()*0.4-0.2;
world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, x+xr, y+yr, z+zr, 0.0, 0.0, 0.0);
}
//--------------------------------------------------------------------------------------------------------------------
// ModEngineersDecor.GuiHandler connectors
//--------------------------------------------------------------------------------------------------------------------
public static Object getServerGuiElement(final EntityPlayer player, final World world, final BlockPos pos, final TileEntity te)
{ return (te instanceof BTileEntity) ? (new BContainer(player.inventory, world, pos, (BTileEntity)te)) : null; }
public static Object getClientGuiElement(final EntityPlayer player, final World world, final BlockPos pos, final TileEntity te)
{ return (te instanceof BTileEntity) ? (new BGui(player.inventory, world, pos, (BTileEntity)te)) : null; }
//--------------------------------------------------------------------------------------------------------------------
// GUI
//--------------------------------------------------------------------------------------------------------------------
@SideOnly(Side.CLIENT)
private static class BGui extends GuiContainer
{
private final BTileEntity te;
public BGui(InventoryPlayer playerInventory, World world, BlockPos pos, BTileEntity te)
{ super(new BContainer(playerInventory, world, pos, te)); this.te = te; }
@Override
public void initGui()
{ super.initGui(); }
@Override
public void drawScreen(int mouseX, int mouseY, float partialTicks)
{
drawDefaultBackground();
super.drawScreen(mouseX, mouseY, partialTicks);
renderHoveredToolTip(mouseX, mouseY);
}
@Override
protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY)
{
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
mc.getTextureManager().bindTexture(new ResourceLocation(ModEngineersDecor.MODID, "textures/gui/small_waste_incinerator_gui.png"));
final int x0=(width-xSize)/2, y0=(height-ySize)/2, w=xSize, h=ySize;
drawTexturedModalRect(x0, y0, 0, 0, w, h);
}
}
//--------------------------------------------------------------------------------------------------------------------
// container
//--------------------------------------------------------------------------------------------------------------------
public static class BContainer extends Container
{
private static final int PLAYER_INV_START_SLOTNO = BTileEntity.NUM_OF_SLOTS;
private final World world;
private final BlockPos pos;
private final EntityPlayer player;
private final BTileEntity te;
private int proc_time_needed_;
public BContainer(InventoryPlayer playerInventory, World world, BlockPos pos, BTileEntity te)
{
this.player = playerInventory.player;
this.world = world;
this.pos = pos;
this.te = te;
int i=-1;
addSlotToContainer(new Slot(te, ++i, 13, 9));
addSlotToContainer(new Slot(te, ++i, 37, 12));
addSlotToContainer(new Slot(te, ++i, 54, 13));
addSlotToContainer(new Slot(te, ++i, 71, 14));
addSlotToContainer(new Slot(te, ++i, 88, 15));
addSlotToContainer(new Slot(te, ++i, 105, 16));
addSlotToContainer(new Slot(te, ++i, 122, 17));
addSlotToContainer(new Slot(te, ++i, 139, 18));
addSlotToContainer(new Slot(te, ++i, 144, 38));
addSlotToContainer(new Slot(te, ++i, 127, 39));
addSlotToContainer(new Slot(te, ++i, 110, 40));
addSlotToContainer(new Slot(te, ++i, 93, 41));
addSlotToContainer(new Slot(te, ++i, 76, 42));
addSlotToContainer(new Slot(te, ++i, 59, 43));
addSlotToContainer(new Slot(te, ++i, 42, 44));
addSlotToContainer(new Slot(te, ++i, 17, 58));
for(int x=0; x<9; ++x) {
addSlotToContainer(new Slot(playerInventory, x, 8+x*18, 144)); // player slots: 0..8
}
for(int y=0; y<3; ++y) {
for(int x=0; x<9; ++x) {
addSlotToContainer(new Slot(playerInventory, x+y*9+9, 8+x*18, 86+y*18)); // player slots: 9..35
}
}
}
@Override
public void addListener(IContainerListener listener)
{ super.addListener(listener); listener.sendAllWindowProperties(this, te); }
@Override
public void detectAndSendChanges()
{
super.detectAndSendChanges();
for(int i=0; i<listeners.size(); ++i) {
IContainerListener lis = listeners.get(i);
if(proc_time_needed_ != te.getField(3)) lis.sendWindowProperty(this, 3, te.getField(3));
}
proc_time_needed_ = te.getField(3);
}
@Override
@SideOnly(Side.CLIENT)
public void updateProgressBar(int id, int data)
{ te.setField(id, data); }
@Override
public boolean canInteractWith(EntityPlayer player)
{ return (world.getBlockState(pos).getBlock() instanceof BlockDecorWasteIncinerator) && (player.getDistanceSq(pos) <= 64); }
@Override
public ItemStack transferStackInSlot(EntityPlayer player, int index)
{
Slot slot = inventorySlots.get(index);
if((slot==null) || (!slot.getHasStack())) return ItemStack.EMPTY;
ItemStack slot_stack = slot.getStack();
ItemStack transferred = slot_stack.copy();
if((index>=0) && (index<PLAYER_INV_START_SLOTNO)) {
// Device slots
if(!mergeItemStack(slot_stack, PLAYER_INV_START_SLOTNO, PLAYER_INV_START_SLOTNO+36, true)) return ItemStack.EMPTY;
} else if((index >= PLAYER_INV_START_SLOTNO) && (index <= PLAYER_INV_START_SLOTNO+36)) {
// Player slot
if(!mergeItemStack(slot_stack, 0, PLAYER_INV_START_SLOTNO-1, true)) return ItemStack.EMPTY;
} else {
// invalid slot
return ItemStack.EMPTY;
}
if(slot_stack.isEmpty()) {
slot.putStack(ItemStack.EMPTY);
} else {
slot.onSlotChanged();
}
if(slot_stack.getCount() == transferred.getCount()) return ItemStack.EMPTY;
slot.onTake(player, slot_stack);
return transferred;
}
}
//--------------------------------------------------------------------------------------------------------------------
// Tile entity
//--------------------------------------------------------------------------------------------------------------------
public static class BTileEntity extends TileEntity implements ITickable, ISidedInventory, IEnergyStorage
{
public static final int TICK_INTERVAL = 20;
public static final int ENERGIZED_TICK_INTERVAL = 5;
public static final int MAX_ENERGY_BUFFER = 16000;
public static final int MAX_ENERGY_TRANSFER = 256;
public static final int DEFAULT_ENERGY_CONSUMPTION = 16;
public static final int NUM_OF_SLOTS = 16;
public static final int INPUT_SLOT_NO = 0;
public static final int BURN_SLOT_NO = NUM_OF_SLOTS-1;
private static int energy_consumption = DEFAULT_ENERGY_CONSUMPTION;
private int tick_timer_;
private int check_timer_;
private int energy_stored_;
protected NonNullList<ItemStack> stacks_ = NonNullList.<ItemStack>withSize(NUM_OF_SLOTS, ItemStack.EMPTY);
public static void on_config(int speed_percent, int fuel_efficiency_percent, int boost_energy_per_tick)
{
energy_consumption = MathHelper.clamp(boost_energy_per_tick, 16, 512);
ModEngineersDecor.logger.info("Config waste incinerator boost energy consumption:" + energy_consumption);
}
public BTileEntity()
{ reset(); }
protected void reset()
{
stacks_ = NonNullList.<ItemStack>withSize(NUM_OF_SLOTS, ItemStack.EMPTY);
check_timer_ = 0;
tick_timer_ = 0;
}
public void readnbt(NBTTagCompound compound)
{
NonNullList<ItemStack> stacks = NonNullList.<ItemStack>withSize(NUM_OF_SLOTS, ItemStack.EMPTY);
ItemStackHelper.loadAllItems(compound, stacks);
while(stacks.size() < NUM_OF_SLOTS) stacks.add(ItemStack.EMPTY);
stacks_ = stacks;
energy_stored_ = compound.getInteger("Energy");
}
protected void writenbt(NBTTagCompound compound)
{
compound.setInteger("Energy", MathHelper.clamp(energy_stored_,0 , MAX_ENERGY_BUFFER));
ItemStackHelper.saveAllItems(compound, stacks_);
}
private ItemStack shiftStacks(final int index_from, final int index_to)
{
if(index_from >= index_to) return ItemStack.EMPTY;
ItemStack out_stack = ItemStack.EMPTY;
ItemStack stack = stacks_.get(index_from);
for(int i=index_from+1; i<=index_to; ++i) {
out_stack = stacks_.get(i);
stacks_.set(i, stack);
stack = out_stack;
}
stacks_.set(index_from, ItemStack.EMPTY);
return out_stack;
}
private boolean transferItems(final int index_from, final int index_to, int count)
{
ItemStack from = stacks_.get(index_from);
if(from.isEmpty()) return false;
ItemStack to = stacks_.get(index_to);
if(from.getCount() < count) count = from.getCount();
if(count <= 0) return false;
boolean changed = true;
if(to.isEmpty()) {
stacks_.set(index_to, from.splitStack(count));
} else if(to.getCount() >= to.getMaxStackSize()) {
changed = false;
} else if((!from.isItemEqual(to)) || (!ItemStack.areItemStackTagsEqual(from, to))) {
changed = false;
} else {
if((to.getCount()+count) >= to.getMaxStackSize()) {
from.shrink(to.getMaxStackSize()-to.getCount());
to.setCount(to.getMaxStackSize());
} else {
from.shrink(count);
to.grow(count);
}
}
if(from.isEmpty() && from!=ItemStack.EMPTY) {
stacks_.set(index_from, ItemStack.EMPTY);
changed = true;
}
return changed;
}
// TileEntity ------------------------------------------------------------------------------
@Override
public boolean shouldRefresh(World world, BlockPos pos, IBlockState os, IBlockState ns)
{ return (os.getBlock() != ns.getBlock()) || (!(ns.getBlock() instanceof BlockDecorWasteIncinerator)); }
@Override
public void readFromNBT(NBTTagCompound compound)
{ super.readFromNBT(compound); readnbt(compound); }
@Override
public NBTTagCompound writeToNBT(NBTTagCompound compound)
{ super.writeToNBT(compound); writenbt(compound); return compound; }
// IWorldNamable ---------------------------------------------------------------------------
@Override
public String getName()
{ final Block block=getBlockType(); return (block!=null) ? (block.getTranslationKey() + ".name") : (""); }
@Override
public boolean hasCustomName()
{ return false; }
@Override
public ITextComponent getDisplayName()
{ return new TextComponentTranslation(getName(), new Object[0]); }
// IInventory ------------------------------------------------------------------------------
@Override
public int getSizeInventory()
{ return stacks_.size(); }
@Override
public boolean isEmpty()
{ for(ItemStack stack: stacks_) { if(!stack.isEmpty()) return false; } return true; }
@Override
public ItemStack getStackInSlot(int index)
{ return ((index >= 0) && (index < getSizeInventory())) ? stacks_.get(index) : ItemStack.EMPTY; }
@Override
public ItemStack decrStackSize(int index, int count)
{ return ItemStackHelper.getAndSplit(stacks_, index, count); }
@Override
public ItemStack removeStackFromSlot(int index)
{ return ItemStackHelper.getAndRemove(stacks_, index); }
@Override
public void setInventorySlotContents(int index, ItemStack stack)
{
if(stack.getCount() > getInventoryStackLimit()) stack.setCount(getInventoryStackLimit());
stacks_.set(index, stack);
markDirty();
}
@Override
public int getInventoryStackLimit()
{ return 64; }
@Override
public void markDirty()
{ super.markDirty(); }
@Override
public boolean isUsableByPlayer(EntityPlayer player)
{ return ((world.getTileEntity(pos) == this) && (player.getDistanceSq(pos.getX()+0.5d, pos.getY()+0.5d, pos.getZ()+0.5d) <= 64.0d)); }
@Override
public void openInventory(EntityPlayer player)
{}
@Override
public void closeInventory(EntityPlayer player)
{ markDirty(); }
@Override
public boolean isItemValidForSlot(int index, ItemStack stack)
{ return (index==0); }
@Override
public int getField(int id)
{ return 0; }
@Override
public void setField(int id, int value)
{}
@Override
public int getFieldCount()
{ return 4; }
@Override
public void clear()
{ stacks_.clear(); }
// ISidedInventory ----------------------------------------------------------------------------
private static final int[] SIDED_INV_SLOTS = new int[] { INPUT_SLOT_NO };
@Override
public int[] getSlotsForFace(EnumFacing side)
{ return SIDED_INV_SLOTS; }
@Override
public boolean canInsertItem(int index, ItemStack itemStackIn, EnumFacing direction)
{ return isItemValidForSlot(index, itemStackIn); }
@Override
public boolean canExtractItem(int index, ItemStack stack, EnumFacing direction)
{ return false; }
// IEnergyStorage ----------------------------------------------------------------------------
@Override
public boolean canExtract()
{ return false; }
@Override
public boolean canReceive()
{ return true; }
@Override
public int getMaxEnergyStored()
{ return MAX_ENERGY_BUFFER; }
@Override
public int getEnergyStored()
{ return energy_stored_; }
@Override
public int extractEnergy(int maxExtract, boolean simulate)
{ return 0; }
@Override
public int receiveEnergy(int maxReceive, boolean simulate)
{
if(energy_stored_ >= MAX_ENERGY_BUFFER) return 0;
int n = Math.min(maxReceive, (MAX_ENERGY_BUFFER - energy_stored_));
if(n > MAX_ENERGY_TRANSFER) n = MAX_ENERGY_TRANSFER;
if(!simulate) {energy_stored_ += n; markDirty(); }
return n;
}
// IItemHandler --------------------------------------------------------------------------------
protected static class BItemHandler implements IItemHandler
{
private BTileEntity te;
BItemHandler(BTileEntity te)
{ this.te = te; }
@Override
public int getSlots()
{ return 1; }
@Override
public int getSlotLimit(int index)
{ return te.getInventoryStackLimit(); }
@Override
public boolean isItemValid(int slot, @Nonnull ItemStack stack)
{ return true; }
@Override
@Nonnull
public ItemStack insertItem(int index, @Nonnull ItemStack stack, boolean simulate)
{
if(stack.isEmpty()) return ItemStack.EMPTY;
if(index != 0) return ItemStack.EMPTY;
int slotno = 0;
ItemStack slotstack = getStackInSlot(slotno);
if(!slotstack.isEmpty())
{
if(slotstack.getCount() >= Math.min(slotstack.getMaxStackSize(), getSlotLimit(index))) return stack;
if(!ItemHandlerHelper.canItemStacksStack(stack, slotstack)) return stack;
if(!te.canInsertItem(slotno, stack, EnumFacing.UP) || (!te.isItemValidForSlot(slotno, stack))) return stack;
int n = Math.min(stack.getMaxStackSize(), getSlotLimit(index)) - slotstack.getCount();
if(stack.getCount() <= n) {
if(!simulate) {
ItemStack copy = stack.copy();
copy.grow(slotstack.getCount());
te.setInventorySlotContents(slotno, copy);
}
return ItemStack.EMPTY;
} else {
stack = stack.copy();
if(!simulate) {
ItemStack copy = stack.splitStack(n);
copy.grow(slotstack.getCount());
te.setInventorySlotContents(slotno, copy);
return stack;
} else {
stack.shrink(n);
return stack;
}
}
} else {
if(!te.canInsertItem(slotno, stack, EnumFacing.UP) || (!te.isItemValidForSlot(slotno, stack))) return stack;
int n = Math.min(stack.getMaxStackSize(), getSlotLimit(index));
if(n < stack.getCount()) {
stack = stack.copy();
if(!simulate) {
te.setInventorySlotContents(slotno, stack.splitStack(n));
return stack;
} else {
stack.shrink(n);
return stack;
}
} else {
if(!simulate) te.setInventorySlotContents(slotno, stack);
return ItemStack.EMPTY;
}
}
}
@Override
@Nonnull
public ItemStack extractItem(int index, int amount, boolean simulate)
{ return ItemStack.EMPTY; }
@Override
@Nonnull
public ItemStack getStackInSlot(int index)
{ return te.getStackInSlot(index); }
}
private BItemHandler item_handler_ = new BItemHandler(this);
// Capability export ----------------------------------------------------------------------------
@Override
public boolean hasCapability(Capability<?> cap, EnumFacing facing)
{ return ((cap==CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) || (cap==CapabilityEnergy.ENERGY)) || super.hasCapability(cap, facing); }
@Override
@SuppressWarnings("unchecked")
@Nullable
public <T> T getCapability(Capability<T> capability, @Nullable EnumFacing facing)
{
if((facing != null) && (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)) {
return (T)item_handler_;
} else if(capability == CapabilityEnergy.ENERGY) {
return (T)this;
} else {
return super.getCapability(capability, facing);
}
}
// ITickable ------------------------------------------------------------------------------------
@Override
public void update()
{
if(--tick_timer_ > 0) return;
tick_timer_ = TICK_INTERVAL;
if(world.isRemote) return;
final IBlockState state = world.getBlockState(pos);
if(!(state.getBlock() instanceof BlockDecorWasteIncinerator)) return;
boolean dirty = false;
ItemStack processing_stack = stacks_.get(BURN_SLOT_NO);
final boolean was_processing = !processing_stack.isEmpty();
boolean is_processing = was_processing;
boolean new_stack_processing = false;
if((!stacks_.get(0).isEmpty()) && transferItems(0, 1, getInventoryStackLimit())) dirty = true;
ItemStack first_stack = stacks_.get(0);
boolean shift = !first_stack.isEmpty();
if(is_processing) {
processing_stack.shrink(1);
if(processing_stack.getCount() <= 0) {
processing_stack = ItemStack.EMPTY;
is_processing = false;
}
stacks_.set(BURN_SLOT_NO, processing_stack);
if(energy_stored_ >= (energy_consumption * TICK_INTERVAL)) {
energy_stored_ -= (energy_consumption * TICK_INTERVAL);
tick_timer_ = ENERGIZED_TICK_INTERVAL;
}
dirty = true;
}
if(shift) {
int max_shift_slot_no = BURN_SLOT_NO-1;
for(int i=1; i<BURN_SLOT_NO-1; ++i) { if(stacks_.get(i).isEmpty()) { max_shift_slot_no=i; break; } }
if(max_shift_slot_no < (BURN_SLOT_NO-1)) {
shiftStacks(0, max_shift_slot_no);
// re-stack
for(int i=1; i<=max_shift_slot_no; ++i) {
if(transferItems(i-1, i, getInventoryStackLimit())) break;
}
dirty = true;
} else if(!is_processing) {
shiftStacks(0, BURN_SLOT_NO);
dirty = true;
}
}
if((was_processing != is_processing) || (new_stack_processing)) {
if(new_stack_processing) world.playSound(null, pos, SoundEvents.BLOCK_LAVA_AMBIENT, SoundCategory.BLOCKS, 0.05f, 2.4f);
world.setBlockState(pos, state.withProperty(LIT, is_processing), 2|16);
}
if(dirty) markDirty();
}
}
}

View file

@ -1,81 +0,0 @@
/*
* @file BlockDecorWindow.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Mod windows.
*/
package wile.engineersdecor.blocks;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.util.BlockRenderLayer;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class BlockDecorWindow extends BlockDecorDirected
{
public BlockDecorWindow(@Nonnull String registryName, long config, @Nullable Material material, float hardness, float resistance, @Nullable SoundType sound, @Nonnull AxisAlignedBB unrotatedAABB)
{ super(registryName, config, material, hardness, resistance, sound, unrotatedAABB); }
@Override
@SideOnly(Side.CLIENT)
public BlockRenderLayer getRenderLayer()
{ return BlockRenderLayer.TRANSLUCENT; }
@Override
@SideOnly(Side.CLIENT)
public boolean canRenderInLayer(IBlockState state, BlockRenderLayer layer)
{ return (layer==BlockRenderLayer.CUTOUT_MIPPED) || (layer==BlockRenderLayer.TRANSLUCENT); }
@Override
@SideOnly(Side.CLIENT)
public boolean shouldSideBeRendered(IBlockState state, IBlockAccess world, BlockPos pos, EnumFacing side)
{ return true; }
@Override
public boolean isFullCube(IBlockState state)
{ return false; }
@Override
public boolean isNormalCube(IBlockState state)
{ return false; }
@Override
public boolean isOpaqueCube(IBlockState state)
{ return false; }
@Override
public boolean doesSideBlockRendering(IBlockState state, IBlockAccess world, BlockPos pos, EnumFacing face)
{ return false; }
@Override
public IBlockState getStateForPlacement(World world, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer, EnumHand hand)
{
facing = placer.getHorizontalFacing();
if(Math.abs(placer.getLookVec().y) > 0.9) {
facing = EnumFacing.getDirectionFromEntityLiving(pos, placer);
} else {
for(EnumFacing f: EnumFacing.values()) {
IBlockState st = world.getBlockState(pos.offset(f));
if(st.getBlock() == this) {
facing = st.getValue(FACING);
break;
}
}
}
return getDefaultState().withProperty(FACING, facing);
}
}

View file

@ -1,43 +0,0 @@
/*
* @file BlockDecorWindowSill.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Block for windowsills to allow placing things on top
* (top side solid).
*/
package wile.engineersdecor.blocks;
import net.minecraft.block.material.Material;
import net.minecraft.block.SoundType;
import net.minecraft.block.state.BlockFaceShape;
import net.minecraft.block.state.IBlockState;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockAccess;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class BlockDecorWindowSill extends BlockDecorDirected
{
public BlockDecorWindowSill(@Nonnull String registryName, long config, @Nullable Material material, float hardness, float resistance, @Nullable SoundType sound, @Nonnull AxisAlignedBB unrotatedAABB)
{ super(registryName, config|CFG_HORIZIONTAL, material, hardness, resistance, sound, unrotatedAABB); }
@Override
public BlockFaceShape getBlockFaceShape(IBlockAccess world, IBlockState state, BlockPos pos, EnumFacing face)
{ return (face==EnumFacing.UP) ? BlockFaceShape.SOLID : BlockFaceShape.UNDEFINED; }
@Override
@SuppressWarnings("deprecation")
public boolean isSideSolid(IBlockState state, IBlockAccess world, BlockPos pos, EnumFacing side)
{ return side==EnumFacing.UP; }
@Override
@SuppressWarnings("deprecation")
public boolean isTopSolid(IBlockState state)
{ return true; }
}

View file

@ -1,114 +0,0 @@
/*
* @file BlockCategories.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Oredict based block category cache.
*/
package wile.engineersdecor.detail;
import wile.engineersdecor.ModEngineersDecor;
import net.minecraft.block.*;
import net.minecraft.block.properties.IProperty;
import net.minecraft.block.state.IBlockState;
import net.minecraft.block.material.Material;
import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraftforge.oredict.OreDictionary;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class BlockCategories
{
private static Set<Block> logs_ = new HashSet<Block>();
private static Set<Block> leaves_ = new HashSet<Block>();
private static Set<Block> variant_logs_ = new HashSet<Block>(); // logs that are not checked for log equivalence
public static final Set<Block> logs()
{ return logs_; } // wrap in case immutable needed one time.
public static final Set<Block> leaves()
{ return leaves_; }
public static boolean isLog(IBlockState state)
{
final Block block = state.getBlock();
return (block instanceof BlockLog) || (block instanceof BlockNewLog) || (logs().contains(block));
}
public static boolean isLeaves(IBlockState state)
{
if(state.getMaterial()==Material.LEAVES) return true;
final Block block = state.getBlock();
return (block instanceof BlockLeaves) || (leaves().contains(block));
}
public static final boolean isSameLeaves(IBlockState a, IBlockState b)
{
if(!isLeaves(a)) return false;
final Block block = a.getBlock();
if(block != b.getBlock()) return false;
if(block instanceof BlockNewLeaf) return a.getValue(BlockNewLeaf.VARIANT) == b.getValue(BlockNewLeaf.VARIANT);
if(block instanceof BlockOldLeaf) return a.getValue(BlockOldLeaf.VARIANT) == b.getValue(BlockOldLeaf.VARIANT);
return true;
}
public static final boolean isSameLog(IBlockState a, IBlockState b)
{
if((!isLog(a)) || (!isLog(b))) return false;
if(variant_logs_.contains(a.getBlock()) || (variant_logs_.contains(b.getBlock()))) return true;
if(a.getBlock()!=b.getBlock()) return false;
if(a.getBlock() instanceof BlockNewLog) return a.getValue(BlockNewLog.VARIANT) == b.getValue(BlockNewLog.VARIANT);
if(a.getBlock() instanceof BlockOldLog) return a.getValue(BlockOldLog.VARIANT)==b.getValue(BlockOldLog.VARIANT);
// Uagh, that hurts the heart of performance ...
final IProperty<?> prop = a.getPropertyKeys().stream().filter( (IProperty<?> p) -> (p.getName().contains("variant") || p.getName().contains("type"))).findFirst().orElse(null);
if(prop!=null) return a.getValue(prop).equals(b.getValue(prop));
// All other: We have to assume that there are no variants for this block, and the block type denotes the log type unambiguously.
return true;
}
public static final void reload()
{
{
HashSet<Block> logs = new HashSet<Block>();
for(final String ore_name : OreDictionary.getOreNames()) {
if(!ore_name.startsWith("logWood")) continue;
final List<ItemStack> stacks = OreDictionary.getOres(ore_name, false);
for(ItemStack stack : stacks) {
final Item item = stack.getItem();
if(!(item instanceof ItemBlock)) continue;
Block block = ((ItemBlock)item).getBlock();
logs.add(block);
// @todo: make this configurable
if(block.getRegistryName().getPath().contains("menril")) variant_logs_.add(block);
}
}
logs_ = logs;
ModEngineersDecor.logger.info("Found "+logs.size()+" types of 'choppable' log.");
if(ModConfig.zmisc.with_experimental) {
for(Block b:logs_) ModEngineersDecor.logger.info(" - choppable log: " + b.getRegistryName());
}
}
{
HashSet<Block> leaves = new HashSet<Block>();
for(final String ore_name : OreDictionary.getOreNames()) {
if(!ore_name.startsWith("treeLeaves")) continue;
final List<ItemStack> stacks = OreDictionary.getOres(ore_name, false);
for(ItemStack stack : stacks) {
final Item item = stack.getItem();
if(!(item instanceof ItemBlock)) continue;
leaves.add(((ItemBlock)item).getBlock());
}
}
leaves_ = leaves;
ModEngineersDecor.logger.info("Found "+leaves.size()+" types of leaves.");
if(ModConfig.zmisc.with_experimental) {
for(Block b:leaves_) ModEngineersDecor.logger.info(" - choppable leaf: " + b.getRegistryName());
}
}
}
}

View file

@ -1,32 +0,0 @@
/*
* @file ClientProxy.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2018 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Client side only initialisation.
*/
package wile.engineersdecor.detail;
import wile.engineersdecor.ModEngineersDecor;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.world.World;
import net.minecraft.client.Minecraft;
import net.minecraftforge.client.model.obj.OBJLoader;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
public class ClientProxy implements ModEngineersDecor.IProxy
{
@Override
public void preInit(FMLPreInitializationEvent e)
{ OBJLoader.INSTANCE.addDomain(ModEngineersDecor.MODID); }
@Override
public World getWorlClientSide()
{ return Minecraft.getMinecraft().world; }
@Override
public EntityPlayer getPlayerClientSide()
{ return Minecraft.getMinecraft().player; }
}

View file

@ -1,24 +0,0 @@
/*
* @file ExtItems.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Object holder based item references.
*/
package wile.engineersdecor.detail;
import net.minecraft.item.Item;
import net.minecraftforge.fml.common.registry.GameRegistry;
public class ExtItems
{
@GameRegistry.ObjectHolder("immersiveengineering:metal_device1")
public static final Item IE_EXTERNAL_HEATER = null;
@GameRegistry.ObjectHolder("bottledmilk:milk_bottle_drinkable")
public static final Item BOTTLED_MILK_BOTTLE_DRINKLABLE = null;
public static final void onPostInit()
{}
}

View file

@ -1,70 +0,0 @@
package wile.engineersdecor.detail;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.ISidedInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper;
import net.minecraftforge.items.wrapper.InvWrapper;
import net.minecraftforge.items.wrapper.SidedInvWrapper;
import javax.annotation.Nullable;
public class ItemHandling
{
public static IItemHandler itemhandler(World world, BlockPos pos, @Nullable EnumFacing side)
{
TileEntity te = world.getTileEntity(pos);
if(te==null) return null;
if(te.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side)) return (IItemHandler)te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side);
if((side!=null) && (te instanceof ISidedInventory)) return new SidedInvWrapper((ISidedInventory)te, side);
if(te instanceof IInventory) return new InvWrapper((IInventory)te);
return null;
}
public static ItemStack insert(IItemHandler inventory, ItemStack stack , boolean simulate)
{ return ItemHandlerHelper.insertItemStacked(inventory, stack, simulate); }
public static ItemStack insert(TileEntity te, @Nullable EnumFacing side, ItemStack stack, boolean simulate)
{
if(te==null) return stack;
IItemHandler hnd = null;
if(te.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side)) {
hnd = (IItemHandler)te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side);
} else if((side!=null) && (te instanceof ISidedInventory)) {
hnd = new SidedInvWrapper((ISidedInventory)te, side);
} else if(te instanceof IInventory) {
hnd = new InvWrapper((IInventory)te);
}
return (hnd==null) ? stack : ItemHandlerHelper.insertItemStacked(hnd, stack, simulate);
}
public static ItemStack extract(IItemHandler inventory, @Nullable ItemStack match, int amount, boolean simulate)
{
if((inventory==null) || (amount<=0)) return ItemStack.EMPTY;
final int max = inventory.getSlots();
ItemStack out_stack = ItemStack.EMPTY;
for(int i=0; i<max; ++i) {
final ItemStack stack = inventory.getStackInSlot(i);
if(stack.isEmpty()) continue;
if(out_stack.isEmpty()) {
if((match!=null) && (!stack.isItemEqual(match))) continue;
out_stack = inventory.extractItem(i, amount, simulate);
} else if(stack.isItemEqual(out_stack)) {
ItemStack es = inventory.extractItem(i, (amount-out_stack.getCount()), simulate);
out_stack.grow(es.getCount());
}
if(out_stack.getCount() >= amount) break;
}
return out_stack;
}
}

View file

@ -1,188 +0,0 @@
/*
* @file ModAuxiliaries.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2018 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* General commonly used functionality.
*/
package wile.engineersdecor.detail;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraftforge.fml.common.Loader;
import wile.engineersdecor.ModEngineersDecor;
import net.minecraft.world.World;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.text.TextComponentTranslation;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import org.lwjgl.input.Keyboard;
import javax.annotation.Nullable;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ModAuxiliaries
{
/**
* Text localisation wrapper, implicitly prepends `ModEngineersDecor.MODID` to the
* translation keys. Forces formatting argument, nullable if no special formatting shall be applied..
*/
public static TextComponentTranslation localizable(String modtrkey, @Nullable TextFormatting color, Object... args)
{
TextComponentTranslation tr = new TextComponentTranslation(ModEngineersDecor.MODID+"."+modtrkey, args);
if(color!=null) tr.getStyle().setColor(color);
return tr;
}
@SideOnly(Side.CLIENT)
public static String localize(String translationKey, Object... args)
{
TextComponentTranslation tr = new TextComponentTranslation(translationKey, args);
tr.getStyle().setColor(TextFormatting.RESET);
final String ft = tr.getFormattedText();
if(ft.contains("${")) {
// Non-recursive, non-argument lang file entry cross referencing.
Pattern pt = Pattern.compile("\\$\\{([^}]+)\\}");
Matcher mt = pt.matcher(ft);
StringBuffer sb = new StringBuffer();
while(mt.find()) {
String m = mt.group(1);
if(m.contains("?")) {
String[] kv = m.split("\\?", 2);
String key = kv[0].trim();
boolean not = key.startsWith("!");
if(not) key = key.replaceFirst("!", "");
m = kv[1].trim();
if(!ModConfig.getServerConfig().hasKey(key)) {
m = "";
} else {
boolean r = ModConfig.getServerConfig().getBoolean(key);
if(not) r = !r;
if(!r) m = "";
}
}
mt.appendReplacement(sb, (new TextComponentTranslation(m)).getFormattedText().trim());
}
mt.appendTail(sb);
return sb.toString();
} else {
return ft;
}
}
@SideOnly(Side.CLIENT)
public static final boolean isShiftDown()
{ return (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)||Keyboard.isKeyDown(Keyboard.KEY_RSHIFT)); }
@SideOnly(Side.CLIENT)
public static final boolean isCtrlDown()
{ return ((Keyboard.isKeyDown(Keyboard.KEY_LCONTROL)||Keyboard.isKeyDown(Keyboard.KEY_RCONTROL))); }
/**
* Returns true if a given key is translated for the current language.
*/
@SideOnly(Side.CLIENT)
public static boolean hasTranslation(String key)
{ return net.minecraft.client.resources.I18n.hasKey(key); }
public static final class Tooltip
{
@SideOnly(Side.CLIENT)
public static boolean extendedTipCondition()
{ return isShiftDown(); }
@SideOnly(Side.CLIENT)
public static boolean helpCondition()
{ return isShiftDown() && isCtrlDown(); }
/**
* Adds an extended tooltip or help tooltip depending on the key states of CTRL and SHIFT.
* Returns true if the localisable help/tip was added, false if not (either not CTL/SHIFT or
* no translation found).
*/
@SideOnly(Side.CLIENT)
public static boolean addInformation(@Nullable String advancedTooltipTranslationKey, @Nullable String helpTranslationKey, List<String> tooltip, ITooltipFlag flag, boolean addAdvancedTooltipHints)
{
// Note: intentionally not using keybinding here, this must be `control` or `shift`. MC uses lwjgl Keyboard,
// so using this also here should be ok.
if(ModConfig.noToolTips()) return false;
final boolean help_available = (helpTranslationKey != null) && ModAuxiliaries.hasTranslation(helpTranslationKey + ".help");
final boolean tip_available = (advancedTooltipTranslationKey != null) && ModAuxiliaries.hasTranslation(helpTranslationKey + ".tip");
if((!help_available) && (!tip_available)) return false;
if(helpCondition()) {
if(!help_available) return false;
String s = localize(helpTranslationKey + ".help");
if(s.isEmpty()) return false;
tooltip.add(s);
return true;
} else if(extendedTipCondition()) {
if(!tip_available) return false;
String s = localize(advancedTooltipTranslationKey + ".tip");
if(s.isEmpty()) return false;
tooltip.add(s);
return true;
} else if(addAdvancedTooltipHints) {
String s = "";
if(tip_available) s += localize(ModEngineersDecor.MODID + ".tooltip.hint.extended") + (help_available ? " " : "");
if(help_available) s += localize(ModEngineersDecor.MODID + ".tooltip.hint.help");
tooltip.add(s);
}
return false;
}
/**
* Adds an extended tooltip or help tooltip for a given stack depending on the key states of CTRL and SHIFT.
* Format in the lang file is (e.g. for items): "item.MODID.REGISTRYNAME.tip" and "item.MODID.REGISTRYNAME.help".
* Return value see method pattern above.
*/
@SideOnly(Side.CLIENT)
public static boolean addInformation(ItemStack stack, @Nullable World world, List<String> tooltip, ITooltipFlag flag, boolean addAdvancedTooltipHints)
{ return addInformation(stack.getTranslationKey(), stack.getTranslationKey(), tooltip, flag, addAdvancedTooltipHints); }
}
public static final AxisAlignedBB getPixeledAABB(double x0, double y0, double z0, double x1, double y1, double z1)
{ return new AxisAlignedBB(x0/16.0, y0/16.0, z0/16.0, x1/16.0, y1/16.0, z1/16.0); }
public static final AxisAlignedBB getRotatedAABB(AxisAlignedBB bb, EnumFacing new_facing, boolean horizontal_rotation)
{
if(!horizontal_rotation) {
switch(new_facing.getIndex()) {
case 0: return new AxisAlignedBB(1-bb.maxX, 1-bb.maxZ, 1-bb.maxY, 1-bb.minX, 1-bb.minZ, 1-bb.minY); // D
case 1: return new AxisAlignedBB(1-bb.maxX, bb.minZ, bb.minY, 1-bb.minX, bb.maxZ, bb.maxY); // U
case 2: return new AxisAlignedBB(1-bb.maxX, bb.minY, 1-bb.maxZ, 1-bb.minX, bb.maxY, 1-bb.minZ); // N
case 3: return new AxisAlignedBB( bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ); // S --> bb
case 4: return new AxisAlignedBB(1-bb.maxZ, bb.minY, bb.minX, 1-bb.minZ, bb.maxY, bb.maxX); // W
case 5: return new AxisAlignedBB( bb.minZ, bb.minY, 1-bb.maxX, bb.maxZ, bb.maxY, 1-bb.minX); // E
}
} else {
switch(new_facing.getIndex()) {
case 0: return new AxisAlignedBB( bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ); // D --> bb
case 1: return new AxisAlignedBB( bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ); // U --> bb
case 2: return new AxisAlignedBB( bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ); // N --> bb
case 3: return new AxisAlignedBB(1-bb.maxX, bb.minY, 1-bb.maxZ, 1-bb.minX, bb.maxY, 1-bb.minZ); // S
case 4: return new AxisAlignedBB( bb.minZ, bb.minY, 1-bb.maxX, bb.maxZ, bb.maxY, 1-bb.minX); // W
case 5: return new AxisAlignedBB(1-bb.maxZ, bb.minY, bb.minX, 1-bb.minZ, bb.maxY, bb.maxX); // E
}
}
return bb;
}
@SuppressWarnings("unused")
public static void playerChatMessage(EntityPlayer player, final String message)
{
String s = message.trim();
if(!s.isEmpty()) player.sendMessage(new TextComponentTranslation(s));
}
public static boolean isModLoaded(String id)
{ return Loader.isModLoaded(id); }
@SuppressWarnings("unused")
public interface IExperimentalFeature{}
}

View file

@ -1,632 +0,0 @@
/*
* @file ModConfig.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2018 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Main class for module settings. Handles reading and
* saving the config file.
*/
package wile.engineersdecor.detail;
import wile.engineersdecor.ModContent;
import wile.engineersdecor.ModEngineersDecor;
import wile.engineersdecor.blocks.*;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.block.Block;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.Item;
import net.minecraftforge.common.config.Config;
import net.minecraftforge.common.config.ConfigManager;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.client.event.ConfigChangedEvent;
import javax.annotation.Nullable;
import java.util.ArrayList;
@Config(modid = ModEngineersDecor.MODID)
@Config.LangKey("engineersdecor.config.title")
public class ModConfig
{
@Config.Comment({"Allows disabling specific features."})
@Config.Name("Feature opt-outs")
public static final SettingsOptouts optout = new SettingsOptouts();
public static final class SettingsOptouts
{
@Config.Comment({"Opt-out any block by its registry name ('*' wildcard matching, "
+ "comma separated list, whitespaces ignored. You must match the whole name, "
+ "means maybe add '*' also at the begin and end. Example: '*wood*,*steel*' "
+ "excludes everything that has 'wood' or 'steel' in the registry name. "
+ "The matching result is also traced in the log file. "
})
@Config.Name("Pattern excludes")
@Config.RequiresMcRestart
public String excludes = "";
@Config.Comment({"Prevent blocks from being opt'ed by registry name ('*' wildcard matching, "
+ "comma separated list, whitespaces ignored. Evaluated before all other opt-out checks. "
+ "You must match the whole name, means maybe add '*' also at the begin and end. Example: "
+ "'*wood*,*steel*' includes everything that has 'wood' or 'steel' in the registry name."
+ "The matching result is also traced in the log file."
})
@Config.Name("Pattern includes")
@Config.RequiresMcRestart
public String includes = "";
@Config.Comment({"Disable CTRL-SHIFT item tooltip display."})
@Config.Name("Without tooltips")
public boolean without_tooltips = false;
@Config.Comment({"Disable all tile entity special renderers."})
@Config.Name("Without TESRs")
public boolean without_tesrs = false;
@Config.Comment({"Disable clinker bricks and derived blocks."})
@Config.Name("Without clinker bricks")
@Config.RequiresMcRestart
public boolean without_clinker_bricks = false;
@Config.Comment({"Disable slag bricks and derived blocks."})
@Config.Name("Without slag bricks")
@Config.RequiresMcRestart
public boolean without_slag_bricks = false;
@Config.Comment({"Disable rebar concrete and derived blocks."})
@Config.Name("Without rebar concrete")
@Config.RequiresMcRestart
public boolean without_rebar_concrete = false;
@Config.Comment({"Disable gas concrete and derived blocks."})
@Config.Name("Without gas concrete")
@Config.RequiresMcRestart
public boolean without_gas_concrete = false;
@Config.Comment({"Disable all mod wall blocks."})
@Config.Name("Without walls")
@Config.RequiresMcRestart
public boolean without_walls = false;
@Config.Comment({"Disable all mod stairs blocks."})
@Config.Name("Without stairs")
@Config.RequiresMcRestart
public boolean without_stairs = false;
@Config.Comment({"Disable IE concrete wall."})
@Config.Name("Without concrete wall")
@Config.RequiresMcRestart
public boolean without_ie_concrete_wall = false;
@Config.Comment({"Disable panzer glass and derived blocks."})
@Config.Name("Without panzer glass")
@Config.RequiresMcRestart
public boolean without_panzer_glass = false;
@Config.Comment({"Disable ladders"})
@Config.Name("Without ladders")
@Config.RequiresMcRestart
public boolean without_ladders = false;
@Config.Comment({"Disable treated wood table, stool, windowsill, etc."})
@Config.Name("Without tr. wood furniture")
@Config.RequiresMcRestart
public boolean without_treated_wood_furniture = false;
@Config.Comment({"Disable treated wood window, etc."})
@Config.Name("Without windows")
@Config.RequiresMcRestart
public boolean without_windows = false;
@Config.Comment({"Disable light sources"})
@Config.Name("Without lights")
@Config.RequiresMcRestart
public boolean without_light_sources = false;
@Config.Comment({"Disable horizontal half-block slab."})
@Config.Name("Without slabs")
@Config.RequiresMcRestart
public boolean without_slabs = false;
@Config.Comment({"Disable stackable 1/8 block slices."})
@Config.Name("Without slab slices")
@Config.RequiresMcRestart
public boolean without_halfslabs = false;
@Config.Comment({"Disable poles of any material."})
@Config.Name("Without poles")
@Config.RequiresMcRestart
public boolean without_poles = false;
@Config.Comment({"Disable horizontal supports like the double-T support."})
@Config.Name("Without h. supports")
@Config.RequiresMcRestart
public boolean without_hsupports = false;
@Config.Comment({"Disable decorative sign plates (caution, hazards, etc)."})
@Config.Name("Without signs")
@Config.RequiresMcRestart
public boolean without_sign_plates = false;
@Config.Comment({"Disable the Floor Grating."})
@Config.Name("Without floor gratings")
@Config.RequiresMcRestart
public boolean without_floor_grating = false;
@Config.Comment({"Disable treated wood crafting table."})
@Config.Name("Without crafting table")
@Config.RequiresMcRestart
public boolean without_crafting_table = false;
@Config.Comment({"Disable small lab furnace."})
@Config.Name("Without lab furnace")
@Config.RequiresMcRestart
public boolean without_lab_furnace = false;
@Config.Comment({"Disable small electrical pass-through furnace."})
@Config.Name("Without electrical furnace")
@Config.RequiresMcRestart
public boolean without_electrical_furnace = false;
@Config.Comment({"Disable check valve, and redstone controlled valves."})
@Config.Name("Without valves")
@Config.RequiresMcRestart
public boolean without_valves = false;
@Config.Comment({"Disable the passive fluid accumulator."})
@Config.Name("Without fluid accumulator")
@Config.RequiresMcRestart
public boolean without_passive_fluid_accumulator = false;
@Config.Comment({"Disable item disposal/trash/void incinerator device."})
@Config.Name("Without waste incinerator")
@Config.RequiresMcRestart
public boolean without_waste_incinerator = false;
@Config.Comment({"Disable the factory dropper."})
@Config.Name("Without factory dropper")
@Config.RequiresMcRestart
public boolean without_factory_dropper = false;
@Config.Comment({"Disable the factory hopper."})
@Config.Name("Without factory hopper")
@Config.RequiresMcRestart
public boolean without_factory_hopper = false;
@Config.Comment({"Disable the Factory Block Placer."})
@Config.Name("Without block placer")
@Config.RequiresMcRestart
public boolean without_factory_placer = false;
@Config.Comment({"Disable the Small Block Breaker."})
@Config.Name("Without block breaker")
@Config.RequiresMcRestart
public boolean without_block_breaker = false;
@Config.Comment({"Disable the Small Solar Panel."})
@Config.Name("Without solar panel")
@Config.RequiresMcRestart
public boolean without_solar_panel = false;
@Config.Comment({"Disable the Small Fluid Collection Funnel."})
@Config.Name("Without fluid collector")
@Config.RequiresMcRestart
public boolean without_fluid_funnel = false;
@Config.Comment({"Disable the Small Mineral Smelter."})
@Config.Name("Without mineral smelter")
@Config.RequiresMcRestart
public boolean without_mineral_smelter = false;
@Config.Comment({"Disable the Small Tree Cutter."})
@Config.Name("Without tree cutter")
@Config.RequiresMcRestart
public boolean without_treecutter = false;
@Config.Comment({"Disable the Small Mikling Machine."})
@Config.Name("Without milking machine")
@Config.RequiresMcRestart
public boolean without_milker = false;
@Config.Comment({"Disable directly picking up layers from slabs and slab slices by left clicking while looking up/down."})
@Config.Name("Without slab pickup")
public boolean without_direct_slab_pickup = false;
@Config.Comment({"Disable possibility to sit on stools and chairs."})
@Config.Name("Without chair sitting")
public boolean without_chair_sitting = false;
@Config.Comment({"Disable that mobs will sit on chairs and stools."})
@Config.Name("Without chair mob sitting")
public boolean without_mob_chair_sitting = false;
@Config.Comment({"Disable the speed boost of ladders in this mod."})
@Config.Name("Without ladder speed boost")
public boolean without_ladder_speed_boost = false;
@Config.Comment({"Disable history refabrication feature of the treated wood crafting table."})
@Config.Name("Without crafting table history")
public boolean without_crafting_table_history = false;
}
@Config.Comment({
"Settings for beta testing and trouble shooting. Some of the settings " +
"may be moved to other categories after testing."
})
@Config.Name("Miscellaneous")
public static final SettingsZTesting zmisc = new SettingsZTesting();
public static final class SettingsZTesting
{
@Config.Comment({ "Enables experimental features. Use at own risk." })
@Config.Name("With experimental")
@Config.RequiresMcRestart
public boolean with_experimental = false;
@Config.Comment({ "Disable all internal recipes, allowing to use alternative pack recipes." })
@Config.Name("Without recipes")
@Config.RequiresMcRestart
public boolean without_recipes = false;
@Config.Comment({"Disable registration of opt'ed out blocks. That is normally not a good idea. Your choice."})
@Config.Name("Without opt-out registration")
@Config.RequiresMcRestart
public boolean without_optout_registration = false;
}
@Config.Comment({"Tweaks and block behaviour adaptions."})
@Config.Name("Tweaks")
public static final SettingsTweaks tweaks = new SettingsTweaks();
public static final class SettingsTweaks
{
@Config.Comment({
"Smelts ores to nuggets that are normally smelted to ingots, " +
"if detectable in the Forge ore dict. Prefers IE recipe results. " +
"The value can be changed on-the-fly for testing or age progression."
})
@Config.Name("Furnace: Nugget smelting")
public boolean furnace_smelts_nuggets = false;
@Config.Comment({
"Defines, in percent, how fast the lab furnace smelts compared to " +
"a vanilla furnace. 100% means vanilla furnace speed, 150% means the " +
"lab furnace is faster. The value can be changed on-the-fly for tuning."
})
@Config.Name("Furnace: Smelting speed %")
@Config.RangeInt(min=50, max=500)
public int furnace_smelting_speed_percent = 130;
@Config.Comment({
"Defines, in percent, how fuel efficient the lab furnace is, compared " +
"to a vanilla furnace. 100% means vanilla furnace consumiton, 200% means " +
"the lab furnace needs about half the fuel of a vanilla furnace, " +
"The value can be changed on-the-fly for tuning."
})
@Config.Name("Furnace: Fuel efficiency %")
@Config.RangeInt(min=50, max=250)
public int furnace_fuel_efficiency_percent = 100;
@Config.Comment({
"Defines the energy consumption (per tick) for speeding up the smelting process. " +
"If IE is installed, an external heater has to be inserted into an auxiliary slot " +
"of the lab furnace. The power source needs to be able to provide at least 4 times " +
"this consumption (fixed threshold value). The value can be changed on-the-fly for tuning. " +
"The default value corresponds to the IE heater consumption."
})
@Config.Name("Furnace: Boost energy")
@Config.RangeInt(min=16, max=256)
public int furnace_boost_energy_consumption = 24;
@Config.Comment({
"Defines, in percent, how high the probability is that a mob sits on a chair " +
"when colliding with it. Can be changed on-the-fly for tuning."
})
@Config.Name("Chairs: Sitting chance %")
@Config.RangeDouble(min=0.0, max=80)
public double chair_mob_sitting_probability_percent = 10;
@Config.Comment({
"Defines, in percent, probable it is that a mob leaves a chair when sitting " +
"on it. The 'dice is rolled' about every 20 ticks. There is also a minimum " +
"Sitting time of about 3s. The config value can be changed on-the-fly for tuning."
})
@Config.Name("Chairs: Stand up chance %")
@Config.RangeDouble(min=0.001, max=10)
public double chair_mob_standup_probability_percent = 1;
@Config.Comment({"Disables increasing/decreasing the crafting grid items by scrolling over the crafting result slot."})
@Config.Name("Crafting table: Move buttons")
public boolean with_crafting_quickmove_buttons = false;
@Config.Comment({"Enables small quick-move arrows from/to player/block storage. " +
"Makes the UI a bit too busy, therefore disabled by default."
})
@Config.Name("Crafting table: Mouse scrolling")
public boolean without_crafting_mouse_scrolling = false;
@Config.Comment({
"Defines how many millibuckets can be transferred (per tick) through the valves. " +
"That is technically the 'storage size' specified for blocks that want to fill " +
"fluids into the valve (the valve has no container and forward that to the output " +
"block), The value can be changed on-the-fly for tuning. "
})
@Config.Name("Valves: Max flow rate")
@Config.RangeInt(min=1, max=10000)
public int pipevalve_max_flowrate = 1000;
@Config.Comment({
"Defines how many millibuckets per redstone signal strength can be transferred per tick " +
"through the analog redstone controlled valves. Note: power 0 is always off, power 15 is always " +
"the max flow rate. Between power 1 and 14 this scaler will result in a flow = 'redstone slope' * 'current redstone power'. " +
"The value can be changed on-the-fly for tuning. "
})
@Config.Name("Valves: Redstone slope")
@Config.RangeInt(min=1, max=10000)
public int pipevalve_redstone_slope = 20;
@Config.Comment({
"Defines, in percent, how fast the electrical furnace smelts compared to " +
"a vanilla furnace. 100% means vanilla furnace speed, 150% means the " +
"electrical furnace is faster. The value can be changed on-the-fly for tuning."
})
@Config.Name("E-furnace: Smelting speed %")
@Config.RangeInt(min=50, max=500)
public int e_furnace_speed_percent = BlockDecorFurnaceElectrical.BTileEntity.DEFAULT_SPEED_PERCENT;
@Config.Comment({
"Defines how much RF per tick the the electrical furnace consumed (average) for smelting. " +
"The feeders transferring items from/to adjacent have this consumption/8 for each stack transaction. " +
"The default value is only slightly higher than a furnace with an IE external heater (and no burning fuel inside)." +
"The config value can be changed on-the-fly for tuning."
})
@Config.Name("E-furnace: Power consumption")
@Config.RangeInt(min=10, max=256)
public int e_furnace_power_consumption = BlockDecorFurnaceElectrical.BTileEntity.DEFAULT_ENERGY_CONSUMPTION;
@Config.Comment({
"Defines the peak power production (at noon) of the Small Solar Panel. " +
"Note that the agerage power is much less, as no power is produced at all during the night, " +
"and the power curve is nonlinear rising/falling during the day. Bad weather conditions also " +
"decrease the production. " +
"The config value can be changed on-the-fly for tuning."
})
@Config.Name("Solar panel: Peak power")
@Config.RangeInt(min=5, max=128)
public int solar_panel_peak_power = BlockDecorSolarPanel.BTileEntity.DEFAULT_PEAK_POWER;
@Config.Comment({
"Defines how much RF power the Small Block Breaker requires to magnificently increase the processing speed. " +
"The config value can be changed on-the-fly for tuning."
})
@Config.Name("Block Breaker: Power consumption")
@Config.RangeInt(min=16, max=512)
public int block_breaker_power_consumption = BlockDecorBreaker.DEFAULT_BOOST_ENERGY;
@Config.Comment({
"Defines how much time the Small Block Breaker needs per block hardness, " +
"means: 'reluctance' * hardness + min_time, you change the 'reluctance' here." +
"The unit is ticks/hardness. " +
"The config value can be changed on-the-fly for tuning."
})
@Config.Name("Block Breaker: Breaking reluctance")
@Config.RangeInt(min=5, max=50)
public int block_breaker_reluctance = BlockDecorBreaker.DEFAULT_BREAKING_RELUCTANCE;
@Config.Comment({
"Defines how much time the Small Block Breaker needs at least, better said it's an offset: " +
"'reluctance' * hardness + min_time, you change the 'min_time' here, value " +
"in ticks." +
"The config value can be changed on-the-fly for tuning."
})
@Config.Name("Block Breaker: Min breaking time")
@Config.RangeInt(min=10, max=100)
public int block_breaker_min_breaking_time = BlockDecorBreaker.DEFAULT_MIN_BREAKING_TIME;
@Config.Comment({
"Defines if the Small Block Breaker does not work without RF power."
})
@Config.Name("Block Breaker: Power required")
public boolean block_breaker_requires_power = false;
@Config.Comment({
"Defines how much RF power the Small Tree Cutter requires to magnificently increase the processing speed. " +
"The config value can be changed on-the-fly for tuning."
})
@Config.Name("Tree Cutter: Power consumption")
@Config.RangeInt(min=16, max=512)
public int tree_cuttter_energy_consumption = BlockDecorTreeCutter.DEFAULT_BOOST_ENERGY;
@Config.Comment({
"Defines how much time the Small Tree Cutter needs to cut a tree without RF power. " +
"The value is in seconds. With energy it is 6 times faster. " +
"The config value can be changed on-the-fly for tuning."
})
@Config.Name("Tree Cutter: Cutting time")
@Config.RangeInt(min=10, max=240)
public int tree_cuttter_cutting_time_needed = BlockDecorTreeCutter.DEFAULT_CUTTING_TIME_NEEDED;
@Config.Comment({
"Defines if the Small Tree Cutter does not work without RF power."
})
@Config.Name("Tree Cutter: Power required")
public boolean tree_cuttter_requires_power = false;
@Config.Comment({
"Defines how much RF power the milking machine needs to work. Note this is a permanent " +
"standby consumption (not only when the machine does something). If zero, the machine " +
"does not need power at all to function." +
"The config value can be changed on-the-fly for tuning."
})
@Config.Name("Milker: Power consumption")
@Config.RangeInt(min=0, max=128)
public int milker_energy_consumption = BlockDecorMilker.DEFAULT_ENERGY_CONSUMPTION;
}
@SuppressWarnings("unused")
@Mod.EventBusSubscriber(modid=ModEngineersDecor.MODID)
private static final class EventHandler
{
@SubscribeEvent
public static void onConfigChanged(final ConfigChangedEvent.OnConfigChangedEvent event) {
if(!event.getModID().equals(ModEngineersDecor.MODID)) return;
ConfigManager.sync(ModEngineersDecor.MODID, Config.Type.INSTANCE);
apply();
}
}
@SuppressWarnings("unused")
public static final void onPreInit()
{ startup_apply(); }
@SuppressWarnings("unused")
public static final void onPostInit(FMLPostInitializationEvent event)
{
for(Block e: ModContent.getRegisteredBlocks()) ModConfig.isOptedOut(e, true);
apply();
}
private static final ArrayList<String> includes_ = new ArrayList<String>();
private static final ArrayList<String> excludes_ = new ArrayList<String>();
private static final NBTTagCompound server_config_ = new NBTTagCompound();
public static final NBTTagCompound getServerConfig() // config that may be synchronized from server to client via net pkg.
{ return server_config_; }
public static final boolean isWithoutOptOutRegistration()
{ return (zmisc!=null) && (zmisc.without_optout_registration); }
public static final boolean isWithoutRecipes()
{ return (zmisc==null) || (zmisc.without_recipes); }
public static boolean noToolTips()
{ return optout.without_tooltips; }
public static final boolean isOptedOut(final @Nullable Block block)
{ return isOptedOut(block, false); }
public static final boolean isOptedOut(final @Nullable Block block, boolean with_log_details)
{
if((block == null) || (optout==null)) return true;
if(block == ModContent.SIGN_MODLOGO) return true;
if((!zmisc.with_experimental) && (block instanceof ModAuxiliaries.IExperimentalFeature)) return true;
final String rn = block.getRegistryName().getPath();
// Force-include/exclude pattern matching
try {
for(String e:includes_) {
if(rn.matches(e)) {
if(with_log_details) ModEngineersDecor.logger.info("Optout force include: " + rn);
return false;
}
}
for(String e:excludes_) {
if(rn.matches(e)) {
if(with_log_details) ModEngineersDecor.logger.info("Optout force exclude: " + rn);
return true;
}
}
} catch(Throwable ex) {
ModEngineersDecor.logger.error("optout include pattern failed, disabling.");
includes_.clear();
excludes_.clear();
}
// Early non-opt out type based evaluation
if(block instanceof BlockDecorHalfSlab) return optout.without_halfslabs;
if(block instanceof BlockDecorLadder) return optout.without_ladders;
if(block instanceof BlockDecorWindow) return optout.without_windows;
if(block instanceof BlockDecorHorizontalSupport) return optout.without_hsupports;
if(block instanceof BlockDecorFloorGrating) return optout.without_floor_grating;
if(block instanceof BlockDecorCraftingTable) return optout.without_crafting_table;
if(block instanceof BlockDecorFurnaceElectrical) return optout.without_electrical_furnace;
if((block instanceof BlockDecorFurnace) && (!(block instanceof BlockDecorFurnaceElectrical))) return optout.without_lab_furnace;
if(block instanceof BlockDecorPassiveFluidAccumulator) return optout.without_passive_fluid_accumulator;
if(block instanceof BlockDecorWasteIncinerator) return optout.without_waste_incinerator;
if(block instanceof BlockDecorDropper) return optout.without_factory_dropper;
if(block instanceof BlockDecorHopper) return optout.without_factory_hopper;
if(block instanceof BlockDecorPlacer) return optout.without_factory_placer;
if(block instanceof BlockDecorBreaker) return optout.without_block_breaker;
if(block instanceof BlockDecorSolarPanel) return optout.without_solar_panel;
if(block instanceof BlockDecorFluidFunnel) return optout.without_fluid_funnel;
if(block instanceof BlockDecorMineralSmelter) return optout.without_mineral_smelter;
if(block instanceof BlockDecorMilker) return optout.without_milker;
if(block instanceof BlockDecorPipeValve) return optout.without_valves;
if(block instanceof BlockDecorTreeCutter) return optout.without_treecutter;
// Type based evaluation where later filters may match, too
if(optout.without_slabs && (block instanceof BlockDecorSlab)) return true;
if(optout.without_stairs && (block instanceof BlockDecorStairs)) return true;
if(optout.without_walls && (block instanceof BlockDecorWall)) return true;
if(optout.without_poles && (block instanceof BlockDecorStraightPole)) return true;
// String matching based evaluation
if(optout.without_clinker_bricks && (rn.startsWith("clinker_brick_"))) return true;
if(optout.without_slag_bricks && rn.startsWith("slag_brick_")) return true;
if(optout.without_rebar_concrete && rn.startsWith("rebar_concrete")) return true;
if(optout.without_gas_concrete && rn.startsWith("gas_concrete")) return true;
if(optout.without_ie_concrete_wall && rn.startsWith("concrete_wall")) return true;
if(optout.without_panzer_glass && rn.startsWith("panzerglass_")) return true;
if(optout.without_light_sources && rn.endsWith("_light")) return true;
if(optout.without_sign_plates && rn.startsWith("sign_")) return true;
if(optout.without_treated_wood_furniture) {
if(block instanceof BlockDecorChair) return true;
if(rn.equals("treated_wood_table")) return true;
if(rn.equals("treated_wood_side_table")) return true;
if(rn.equals("treated_wood_stool")) return true;
if(rn.equals("treated_wood_windowsill")) return true;
if(rn.equals("treated_wood_broad_windowsill")) return true;
if(rn.equals("steel_table")) return true;
}
return false;
}
public static final boolean isOptedOut(final @Nullable Item item)
{
if((item == null) || (optout == null)) return true;
if(item instanceof ItemBlock) return isOptedOut(((ItemBlock)item).getBlock());
return false;
}
public static final void startup_apply()
{
ModRecipes.furnaceRecipeOverrideReset();
if(tweaks.furnace_smelts_nuggets) ModRecipes.furnaceRecipeOverrideSmeltsOresToNuggets();
{
optout.includes = optout.includes.toLowerCase().replaceAll(ModEngineersDecor.MODID+":", "").replaceAll("[^*_,a-z0-9]", "");
if(!optout.includes.isEmpty()) ModEngineersDecor.logger.info("Pattern includes: '" + optout.includes + "'");
String[] incl = optout.includes.split(",");
includes_.clear();
for(int i=0; i< incl.length; ++i) {
incl[i] = incl[i].replaceAll("[*]", ".*?");
if(!incl[i].isEmpty()) includes_.add(incl[i]);
}
}
{
optout.excludes = optout.excludes.toLowerCase().replaceAll(ModEngineersDecor.MODID+":", "").replaceAll("[^*_,a-z0-9]", "");
if(!optout.excludes.isEmpty()) ModEngineersDecor.logger.info("Pattern excludes: '" + optout.excludes + "'");
String[] excl = optout.excludes.split(",");
excludes_.clear();
for(int i=0; i< excl.length; ++i) {
excl[i] = excl[i].replaceAll("[*]", ".*?");
if(!excl[i].isEmpty()) excludes_.add(excl[i]);
}
}
}
public static final void apply()
{
BlockDecorFurnace.on_config(tweaks.furnace_smelting_speed_percent, tweaks.furnace_fuel_efficiency_percent, tweaks.furnace_boost_energy_consumption);
BlockDecorChair.on_config(optout.without_chair_sitting, optout.without_mob_chair_sitting, tweaks.chair_mob_sitting_probability_percent, tweaks.chair_mob_standup_probability_percent);
BlockDecorLadder.on_config(optout.without_ladder_speed_boost);
BlockDecorCraftingTable.on_config(optout.without_crafting_table_history, false, tweaks.with_crafting_quickmove_buttons, tweaks.without_crafting_mouse_scrolling);
BlockDecorPipeValve.on_config(tweaks.pipevalve_max_flowrate, tweaks.pipevalve_redstone_slope);
BlockDecorFurnaceElectrical.on_config(tweaks.e_furnace_speed_percent, tweaks.e_furnace_power_consumption, false);
BlockDecorSolarPanel.on_config(tweaks.solar_panel_peak_power, 128);
BlockDecorBreaker.on_config(tweaks.block_breaker_power_consumption, tweaks.block_breaker_reluctance, tweaks.block_breaker_min_breaking_time, tweaks.block_breaker_requires_power);
BlockDecorTreeCutter.on_config(tweaks.tree_cuttter_energy_consumption, tweaks.tree_cuttter_cutting_time_needed, tweaks.tree_cuttter_requires_power);
BlockDecorMilker.on_config(tweaks.milker_energy_consumption);
BlockDecorPlacer.BTileEntity.on_config();
{
// Check if the config is already synchronized or has to be synchronised.
server_config_.setBoolean("tree_cuttter_requires_power", tweaks.tree_cuttter_requires_power);
server_config_.setBoolean("block_breaker_requires_power", tweaks.block_breaker_requires_power);
}
}
}

View file

@ -1,88 +0,0 @@
/*
* @file ModRecipes.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2018 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* General handling auxiliaries for mod recipes.
*
* Credits/references:
*
* - Looked up how blusunrise did the ore-to-grit recipes in `blusunrize.immersiveengineering.common.IERecipes`.
*/
package wile.engineersdecor.detail;
import wile.engineersdecor.ModEngineersDecor;
import wile.engineersdecor.blocks.BlockDecorFurnace;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.item.crafting.FurnaceRecipes;
import net.minecraft.util.NonNullList;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.oredict.OreDictionary;
import java.util.*;
public class ModRecipes
{
public static final void registerRecipes(RegistryEvent.Register<IRecipe> event)
{}
//--------------------------------------------------------------------------------------------------------------------
// Furnace
//--------------------------------------------------------------------------------------------------------------------
/**
* Not a standard recipe, on-the-fly changable behaviour of the furnace.
*/
public static final void furnaceRecipeOverrideReset()
{ BlockDecorFurnace.BRecipes.instance().reset(); }
/**
* Not a standard recipe, on-the-fly changable behaviour of the furnace.
*/
public static final void furnaceRecipeOverrideSmeltsOresToNuggets()
{
try {
ArrayList<String> ores = new ArrayList<String>();
ArrayList<String> ingots = new ArrayList<String>();
ArrayList<String> nuggets = new ArrayList<String>();
String[] names = OreDictionary.getOreNames();
for(String name:names) {
if(name.startsWith("ore")) ores.add(name);
if(name.startsWith("ingot")) ingots.add(name);
if(name.startsWith("nugget")) nuggets.add(name);
}
for(String ore_name:ores) {
final String ingot_name = ore_name.replace("ore", "ingot");
if(!ingots.contains(ingot_name)) continue;
final String nugget_name = ore_name.replace("ore", "nugget");
if(!nuggets.contains(nugget_name)) continue;
final NonNullList<ItemStack> ore_list = OreDictionary.getOres(ore_name, false);
final NonNullList<ItemStack> ingot_list = OreDictionary.getOres(ingot_name, false);
final NonNullList<ItemStack> nugget_list = OreDictionary.getOres(nugget_name, false);
if(ore_list.isEmpty() || ingot_list.isEmpty() || nugget_list.isEmpty()) continue;
final ItemStack ore_stack = ore_list.get(0);
final ItemStack ingot_stack = ingot_list.get(0);
ItemStack nugget_stack = nugget_list.get(0);
for(ItemStack stack:nugget_list) {
if(stack.getItem().getRegistryName().getNamespace() == "immersiveengineering") {
nugget_stack = stack;
break;
}
}
if(ore_stack.isEmpty() || ingot_stack.isEmpty() || nugget_stack.isEmpty()) continue;
if(FurnaceRecipes.instance().getSmeltingResult(ore_stack).getItem().equals(ingot_stack.getItem())) {
final float xp = FurnaceRecipes.instance().getSmeltingExperience(ore_stack);
BlockDecorFurnace.BRecipes.instance().add(ore_stack, nugget_stack, xp);
ModEngineersDecor.logger.info("Lab furnace override: " + ore_name + " -> " + nugget_name);
}
}
} catch(Throwable e) {
ModEngineersDecor.logger.error("Lab furnace override failed with exception, skipping further override processing.");
ModEngineersDecor.logger.error("Exception is: ", e);
}
}
}

View file

@ -1,171 +0,0 @@
/*
* @file ModTesrs.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2018 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Yet unstructured initial experiments with TESRs.
* May be structured after I know what I am doing there.
*/
package wile.engineersdecor.detail;
import wile.engineersdecor.ModEngineersDecor;
import wile.engineersdecor.blocks.BlockDecorCraftingTable;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.renderer.*;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.init.Blocks;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms.TransformType;
import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.MathHelper;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import wile.engineersdecor.blocks.BlockDecorLabeledCrate;
import wile.engineersdecor.blocks.BlockDecorTest;
public class ModTesrs
{
//--------------------------------------------------------------------------------------------------------------------
// Crafting table
//--------------------------------------------------------------------------------------------------------------------
@SideOnly(Side.CLIENT)
public static class TesrDecorCraftingTable extends TileEntitySpecialRenderer<BlockDecorCraftingTable.BTileEntity>
{
private static int tesr_error_counter = 4;
private static double scaler = 0.10;
private static double gap = 0.19;
private static double yrotations[] = {0, 90, 180, 270}; // [hdirection] S-W-N-E
private static double offsets[][][] = { // [hdirection][slotindex][xz]
{ {-1,-1},{+0,-1},{+1,-1}, {-1,+0},{+0,+0},{+1,+0}, {-1,+1},{+0,+1},{+1,+1} }, // S
{ {+1,-1},{+1,+0},{+1,+1}, {+0,-1},{+0,+0},{+0,+1}, {-1,-1},{-1,+0},{-1,+1} }, // W
{ {+1,+1},{+0,+1},{-1,+1}, {+1,+0},{+0,+0},{-1,+0}, {+1,-1},{+0,-1},{-1,-1} }, // N
{ {-1,+1},{-1,+0},{-1,-1}, {+0,+1},{+0,+0},{+0,-1}, {+1,+1},{+1,+0},{+1,-1} }, // E
};
@Override
public void render(final BlockDecorCraftingTable.BTileEntity te, final double x, final double y, final double z, final float partialTicks, final int destroyStage, final float alpha)
{
if(tesr_error_counter<=0) return;
try {
int di = MathHelper.clamp(te.getWorld().getBlockState(te.getPos()).getValue(BlockDecorCraftingTable.FACING).getHorizontalIndex(), 0, 3);
long posrnd = te.getPos().toLong();
posrnd = (posrnd>>16)^(posrnd<<1);
for(int i=0; i<BlockDecorCraftingTable.BTileEntity.NUM_OF_CRAFTING_SLOTS; ++i) {
final ItemStack stack = te.getStackInSlot(BlockDecorCraftingTable.BTileEntity.CRAFTING_SLOTS_BEGIN+i);
if(stack.isEmpty()) continue;
boolean isblock = (stack.getItem() instanceof ItemBlock);
double prnd = ((double)(((Integer.rotateRight(stack.getItem().hashCode()^(int)posrnd,(stack.getCount()+i)&31)))&1023))/1024.0;
double rndo = gap * ((prnd*0.1)-0.05);
double ox = gap * offsets[di][i][0], oz = gap * offsets[di][i][1];
double oy = 0.5;
double ry = ((yrotations[di]+180) + ((prnd*60)-30)) % 360;
if(stack.isEmpty()) return;
GlStateManager.pushMatrix();
GlStateManager.disableLighting();
RenderHelper.enableStandardItemLighting();
GlStateManager.translate(x+0.5+ox, y+0.5+oy, z+0.5+oz);
GlStateManager.rotate((float)90, 1, 0, 0);
GlStateManager.rotate((float)ry, 0, 0, 1);
GlStateManager.translate(rndo, rndo, 0);
GlStateManager.scale(scaler, scaler, scaler);
Minecraft.getMinecraft().getRenderItem().renderItem(stack, TransformType.FIXED);
RenderHelper.disableStandardItemLighting();
GlStateManager.enableLighting();
GlStateManager.popMatrix();
}
} catch(Throwable e) {
if(--tesr_error_counter<=0) {
ModEngineersDecor.logger.error("Crafting Table TESR was disabled because broken, exception was: " + e.getMessage());
ModEngineersDecor.logger.error(e.getStackTrace());
}
}
}
}
//--------------------------------------------------------------------------------------------------------------------
// Labeled Crate
//--------------------------------------------------------------------------------------------------------------------
@SideOnly(Side.CLIENT)
public static class TesrDecorLabeledCrate extends TileEntitySpecialRenderer<BlockDecorLabeledCrate.LabeledCrateTileEntity>
{
private static int tesr_error_counter = 4;
private static double scaler = 0.35;
double tr[][]= { // [hdirection=S-W-N-E][param]
{ +8.0/32, -8.0/32, +15.5/32, 180.0 }, // N
{ -15.5/32, -8.0/32, +8.0/32, 90.0 }, // E
{ -8.0/32, -8.0/32, -15.5/32, 0.0 }, // S param=tx,ty,tz,ry
{ +15.5/32, -8.0/32, -8.0/32, 270.0 }, // W
};
@Override
public void render(final BlockDecorLabeledCrate.LabeledCrateTileEntity te, final double x, final double y, final double z, final float partialTicks, final int destroyStage, final float alpha)
{
if(tesr_error_counter<=0) return;
try {
final ItemStack stack = te.getItemFrameStack();
if(stack.isEmpty()) return;
final int di = MathHelper.clamp(te.getWorld().getBlockState(te.getPos()).getValue(BlockDecorLabeledCrate.FACING).getHorizontalIndex(), 0, 3);
double ox = tr[di][0], oy = tr[di][1], oz = tr[di][2], ry = tr[di][3];
GlStateManager.pushMatrix();
GlStateManager.disableLighting();
RenderHelper.enableStandardItemLighting();
GlStateManager.translate(x+0.5+ox, y+0.5+oy, z+0.5+oz);
GlStateManager.rotate((float)ry, 0, 1, 0);
GlStateManager.scale(scaler, scaler, scaler);
Minecraft.getMinecraft().getRenderItem().renderItem(stack, TransformType.FIXED);
RenderHelper.disableStandardItemLighting();
GlStateManager.enableLighting();
GlStateManager.popMatrix();
} catch(Throwable e) {
if(--tesr_error_counter<=0) {
ModEngineersDecor.logger.error("Labeled Crate TESR was disabled (because broken), exception was: " + e.getMessage());
}
}
}
}
//--------------------------------------------------------------------------------------------------------------------
// Test Block
//--------------------------------------------------------------------------------------------------------------------
@SideOnly(Side.CLIENT)
public static class TesrDecorTest extends TileEntitySpecialRenderer<BlockDecorTest.BTileEntity>
{
@Override
public void render(final BlockDecorTest.BTileEntity te, double x, double y, double z, final float partialTicks, final int destroyStage, final float alpha)
{
if(te.progress() < 0) return;
renderBlockState(Blocks.SANDSTONE.getDefaultState(), te.getPos(), (new Vec3d(1,1,1)).scale(te.progress()), x,y,z);
}
public void renderBlockState(IBlockState state, BlockPos pos, Vec3d offset, double basex, double basey, double basez)
{
if(state.getMaterial() == Material.AIR) return;
BlockRendererDispatcher brd = Minecraft.getMinecraft().getBlockRendererDispatcher();
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bb = tessellator.getBuffer();
bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE);
RenderHelper.disableStandardItemLighting();
GlStateManager.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA);
GlStateManager.enableBlend();
GlStateManager.disableCull();
GlStateManager.shadeModel(Minecraft.isAmbientOcclusionEnabled() ? 7425 : 7424);
bb.begin(7, DefaultVertexFormats.BLOCK);
bb.setTranslation(basex-(double)pos.getX()+offset.x, basey-(double)pos.getY()+offset.y,basez-(double)pos.getZ()+offset.z);
final boolean checkSides=true;
brd.getBlockModelRenderer().renderModel(getWorld(), brd.getModelForState(state), state, pos, bb, checkSides);
bb.setTranslation(0.0, 0.0, 0.0);
tessellator.draw();
RenderHelper.enableStandardItemLighting();
}
}
}

View file

@ -1,119 +0,0 @@
/*
* @file Networking.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Main client/server message handling.
*/
package wile.engineersdecor.detail;
import wile.engineersdecor.ModEngineersDecor;
import net.minecraft.client.Minecraft;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.fml.common.network.ByteBufUtils;
import net.minecraftforge.fml.common.network.NetworkRegistry;
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper;
import net.minecraftforge.fml.relauncher.Side;
import io.netty.buffer.ByteBuf;
public class Networking
{
private static SimpleNetworkWrapper snw = null;
public static void init()
{
if(snw != null) return;
int discr = -1;
snw = NetworkRegistry.INSTANCE.newSimpleChannel(ModEngineersDecor.MODID);
snw.registerMessage(PacketTileNotify.ServerHandler.class, PacketTileNotify.class, ++discr, Side.SERVER);
snw.registerMessage(PacketTileNotify.ClientHandler.class, PacketTileNotify.class, ++discr, Side.CLIENT);
}
public interface IPacketReceiver
{
default void onServerPacketReceived(NBTTagCompound nbt) {}
default void onClientPacketReceived(EntityPlayer player, NBTTagCompound nbt) {}
}
//--------------------------------------------------------------------------------------------------------------------
// Tile entity notifications
//--------------------------------------------------------------------------------------------------------------------
public static class PacketTileNotify implements IMessage
{
NBTTagCompound nbt = null;
BlockPos pos = BlockPos.ORIGIN;
public static void sendToServer(TileEntity te, NBTTagCompound nbt)
{ if((te != null) && (nbt!=null)) snw.sendToServer(new PacketTileNotify(te, nbt)); }
public static void sendToPlayer(EntityPlayer player, TileEntity te, NBTTagCompound nbt)
{ if((player instanceof EntityPlayerMP) && (te != null) && (nbt!=null)) snw.sendTo(new PacketTileNotify(te, nbt), (EntityPlayerMP)player); }
public PacketTileNotify(TileEntity te, NBTTagCompound nbt)
{ this.nbt=nbt; pos=te.getPos(); }
public PacketTileNotify()
{}
@Override
public void fromBytes(ByteBuf buf)
{ pos=BlockPos.fromLong(buf.readLong()); nbt= ByteBufUtils.readTag(buf); }
@Override
public void toBytes(ByteBuf buf)
{ buf.writeLong(pos.toLong()); ByteBufUtils.writeTag(buf, nbt); }
public static class ServerHandler implements IMessageHandler<PacketTileNotify, IMessage>
{
@Override
public IMessage onMessage(PacketTileNotify pkt, MessageContext ctx)
{
EntityPlayer player = ctx.getServerHandler().player;
WorldServer world = ctx.getServerHandler().player.getServerWorld();
world.addScheduledTask(() -> {
try {
if(!world.isBlockLoaded(pkt.pos)) return;
TileEntity te = world.getTileEntity(pkt.pos);
if(!(te instanceof IPacketReceiver)) return;
((IPacketReceiver)te).onClientPacketReceived(player, pkt.nbt);
} catch(Throwable ex) {
ModEngineersDecor.logger.error("Failed to process TE notify packet: " + ex.getMessage());
}
});
return null;
}
}
public static class ClientHandler implements IMessageHandler<PacketTileNotify, IMessage>
{
@Override
public IMessage onMessage(PacketTileNotify pkt, MessageContext ctx)
{
Minecraft.getMinecraft().addScheduledTask(() -> {
try {
final World world = ModEngineersDecor.proxy.getWorlClientSide();
if(!(world instanceof World)) return;
TileEntity te = world.getTileEntity(pkt.pos);
if(!(te instanceof IPacketReceiver)) return;
((IPacketReceiver) te).onServerPacketReceived(pkt.nbt);
} catch(Throwable ex) {
ModEngineersDecor.logger.error("Failed to process TE notify packet: " + ex.getMessage());
}
});
return null;
}
}
}
}

View file

@ -1,80 +0,0 @@
/*
* @file RecipeCondRegistered.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2018 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Recipe condition to enable opt'ing out JSON based recipes, referenced
* in assets/engineersdecor/recipes/_factories.json with full path (therefore
* I had to make a separate file for that instead of a few lines in
* ModAuxiliaries).
*/
package wile.engineersdecor.detail;
import wile.engineersdecor.ModEngineersDecor;
import net.minecraft.block.Block;
import net.minecraft.item.Item;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.crafting.IConditionFactory;
import net.minecraftforge.common.crafting.JsonContext;
import net.minecraftforge.registries.IForgeRegistry;
import net.minecraftforge.fml.common.registry.ForgeRegistries;
import com.google.gson.*;
import java.util.function.BooleanSupplier;
public class RecipeCondModSpecific implements IConditionFactory
{
public static final BooleanSupplier RECIPE_INCLUDE = ()->true;
public static final BooleanSupplier RECIPE_EXCLUDE = ()->false;
public static int num_skipped = 0;
private static BooleanSupplier exclude()
{ ++num_skipped; return RECIPE_EXCLUDE; }
@Override
public BooleanSupplier parse(JsonContext context, JsonObject json) {
if(ModConfig.isWithoutRecipes()) return exclude();
try {
final JsonPrimitive experimental = json.getAsJsonPrimitive("experimental");
if((experimental!=null) && (experimental.getAsBoolean())) {
if(!ModConfig.zmisc.with_experimental) return exclude();
}
final IForgeRegistry<Block> block_registry = ForgeRegistries.BLOCKS;
final IForgeRegistry<Item> item_registry = ForgeRegistries.ITEMS;
final JsonArray items = json.getAsJsonArray("required");
if(items!=null) {
for(JsonElement e: items) {
if(!e.isJsonPrimitive()) continue;
final ResourceLocation rl = new ResourceLocation(((JsonPrimitive)e).getAsString());
if((!block_registry.containsKey(rl)) && (!item_registry.containsKey(rl))) return exclude(); // required item not registered
}
}
final JsonPrimitive result = json.getAsJsonPrimitive("result");
if(result != null) {
final ResourceLocation rl = new ResourceLocation(result.getAsString());
if((!block_registry.containsKey(rl)) && (!item_registry.containsKey(rl))) return exclude(); // required result not registered
if(ModConfig.isOptedOut(block_registry.getValue(rl))) return exclude(); // disabled in mod config
}
final JsonArray missing = json.getAsJsonArray("missing");
if((missing!=null) && (missing.size() > 0)) {
int num_missing = 0;
for(JsonElement e: missing) {
if(!e.isJsonPrimitive()) continue;
final ResourceLocation rl = new ResourceLocation(((JsonPrimitive)e).getAsString());
if((!block_registry.containsKey(rl)) && (!item_registry.containsKey(rl))) ++num_missing;
}
// At least one item missing, enable this recipe as alternative recipe for another one that check the missing item as required item.
// --> e.g. if IE not installed there is no slag. One recipe requires slag, and another one (for the same result) is used if there
// is no slag.
return (num_missing == 0) ? (exclude()) : (RECIPE_INCLUDE);
} else {
return RECIPE_INCLUDE; // no missing given, means include if result and required are all there.
}
} catch(Throwable ex) {
ModEngineersDecor.logger.error("ResultRegisteredCondition failed: " + ex.toString());
}
return exclude(); // skip on exception.
}
}

View file

@ -1,14 +0,0 @@
/*
* @file ServerProxy.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2018 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Module initialisation event handling, server side only.
*/
package wile.engineersdecor.detail;
import wile.engineersdecor.ModEngineersDecor;
public class ServerProxy implements ModEngineersDecor.IProxy
{}

View file

@ -1,278 +0,0 @@
/*
* @file TreeCutting.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Simple tree cutting algorithm.
*/
package wile.engineersdecor.detail;
import wile.engineersdecor.ModEngineersDecor;
import net.minecraft.init.Blocks;
import net.minecraft.block.Block;
import net.minecraft.block.BlockVine;
import net.minecraft.block.properties.IProperty;
import net.minecraft.block.state.IBlockState;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3i;
import net.minecraft.world.World;
import net.minecraftforge.fml.common.registry.ForgeRegistries;
import com.google.common.collect.ImmutableList;
import java.util.*;
public class TreeCutting
{
private static org.apache.logging.log4j.Logger LOGGER = ModEngineersDecor.logger;
private static int max_log_tracing_steps = 128;
private static int max_cutting_height = 128;
private static int max_cutting_radius = 12;
private static class Compat
{
enum ChoppingMethod { None, RootBlockBreaking }
private static final HashMap<IBlockState, ChoppingMethod> choppable_states = new HashMap<IBlockState, ChoppingMethod>();
public static long num_breaking_exceptions = 0;
static void reload()
{
try {
choppable_states.clear();
if(ModAuxiliaries.isModLoaded("dynamictrees")) {
ForgeRegistries.BLOCKS.getKeys().forEach((regname)->{
if(!regname.getPath().contains("branch")) return;
try {
Block block = ForgeRegistries.BLOCKS.getValue(regname);
IBlockState state = block.getDefaultState();
for(IProperty<?> vaprop: state.getProperties().keySet()) {
if(!("radius".equals(vaprop.getName())) || (vaprop.getValueClass() != Integer.class)) continue;
@SuppressWarnings("unchecked")
IProperty<Integer> prop = (IProperty<Integer>)vaprop;
Integer max = ((Collection<Integer>)prop.getAllowedValues()).stream().max(Integer::compare).orElse(0);
if(max<7) continue;
for(int r=7; r<=max; ++r) choppable_states.put(state.withProperty(prop, r), ChoppingMethod.RootBlockBreaking);
}
} catch(Throwable e) {
LOGGER.warn("Failed to register chopping for " + regname.toString());
return;
}
});
}
LOGGER.info("Dynamic Trees chopping compat: " + choppable_states.size() + " choppable states found.");
if(ModConfig.zmisc.with_experimental) {
for(IBlockState b:choppable_states.keySet()) ModEngineersDecor.logger.info(" - dynamic tree state: " + b);
}
} catch(Throwable e) {
choppable_states.clear();
LOGGER.warn("Failed to determine choppings for dynamic trees compat, skipping that:" + e);
}
}
private static boolean canChop(IBlockState state)
{ return choppable_states.containsKey(state); }
private static int chop(World world, IBlockState state, BlockPos pos, int max_blocks_to_break, boolean without_target_block)
{
final int default_expense = 5;
switch(choppable_states.getOrDefault(state, ChoppingMethod.None)) {
case None:
return 0;
case RootBlockBreaking: {
if(num_breaking_exceptions < 16) {
try {
world.setBlockState(pos, Blocks.AIR.getDefaultState(), 1);
state.getBlock().breakBlock(world, pos, state);
} catch(Throwable e) {
if(++num_breaking_exceptions == 1) LOGGER.warn("Tree Chopper: There was an exception while trying to break a tree trunk ("+state.getBlock().getRegistryName()+"): " + e);
if(num_breaking_exceptions == 16) LOGGER.warn("Tree Chopper: There were 16 exceptions in total trying to chop modded trees. Feature has been disabled.");
}
}
return 5;
}
default:
return 0;
}
}
}
private static final List<Vec3i> hoffsets = ImmutableList.of(
new Vec3i( 1,0, 0), new Vec3i( 1,0, 1), new Vec3i( 0,0, 1),
new Vec3i(-1,0, 1), new Vec3i(-1,0, 0), new Vec3i(-1,0,-1),
new Vec3i( 0,0,-1), new Vec3i( 1,0,-1)
);
public static void reload()
{
Compat.reload();
// later config, now keep IJ from suggesting that a private variable should be used.
max_log_tracing_steps = 128;
max_cutting_height = 128;
max_cutting_radius = 12;
}
private static List<BlockPos> findBlocksAround(final World world, final BlockPos centerPos, final IBlockState leaf_type_state, final Set<BlockPos> checked, int recursion_left)
{
ArrayList<BlockPos> to_decay = new ArrayList<BlockPos>();
for(int y=-1; y<=1; ++y) {
final BlockPos layer = centerPos.add(0,y,0);
for(Vec3i v:hoffsets) {
BlockPos pos = layer.add(v);
if((!checked.contains(pos)) && BlockCategories.isSameLeaves(leaf_type_state, world.getBlockState(pos))) {
checked.add(pos);
to_decay.add(pos);
if(recursion_left > 0) {
to_decay.addAll(findBlocksAround(world, pos, leaf_type_state, checked, recursion_left-1));
}
}
}
}
return to_decay;
}
private static boolean too_far(BlockPos start, BlockPos pos)
{
int dy = pos.getY()-start.getY();
if((dy < 0) || (dy>max_cutting_height)) return true;
final int dx = Math.abs(pos.getX()-start.getX());
final int dz = Math.abs(pos.getZ()-start.getZ());
if(dy > max_cutting_radius) dy = max_cutting_radius;
if((dx >= dy+4) || (dz >= dy+4)) return true;
return false;
}
public static boolean canChop(IBlockState state)
{ return BlockCategories.isLog(state) || Compat.canChop(state); }
/**
* Chops a tree, returns the damage that the cutting tool shall take
*/
public static int chopTree(World world, IBlockState broken_state, BlockPos startPos, int max_blocks_to_break, boolean without_target_block)
{
if((Compat.canChop(broken_state))) return Compat.chop(world, broken_state, startPos, max_blocks_to_break, without_target_block);
if(!BlockCategories.isLog(broken_state)) return 0;
Set<BlockPos> checked = new HashSet<BlockPos>();
ArrayList<BlockPos> to_break = new ArrayList<BlockPos>();
ArrayList<BlockPos> to_decay = new ArrayList<BlockPos>();
{
LinkedList<BlockPos> queue = new LinkedList<BlockPos>();
queue.add(startPos);
int steps_left = max_log_tracing_steps;
IBlockState tracked_leaves_state = null;
while(!queue.isEmpty() && (--steps_left >= 0) && (to_break.size()<max_blocks_to_break)) {
final BlockPos pos = queue.removeFirst();
if(checked.contains(pos)) continue;
checked.add(pos);
if(too_far(startPos, pos)) continue;
// Vertical search
final BlockPos uppos = pos.up();
final IBlockState upstate = world.getBlockState(uppos);
if(BlockCategories.isSameLog(upstate, broken_state)) {
queue.add(uppos);
to_break.add(uppos);
steps_left = max_log_tracing_steps;
} else {
boolean isleaf = BlockCategories.isLeaves(upstate);
if(isleaf || world.isAirBlock(uppos) || (upstate.getBlock() instanceof BlockVine)) {
if(isleaf) {
if(tracked_leaves_state==null) {
tracked_leaves_state=upstate;
to_decay.add(uppos);
queue.add(uppos);
} else if(BlockCategories.isSameLeaves(upstate, tracked_leaves_state)) {
to_decay.add(uppos);
queue.add(uppos);
} else {
checked.add(uppos); // no block of interest
}
} else {
checked.add(uppos);
}
// Up is air, check adjacent for diagonal up (e.g. Accacia)
for(Vec3i v:hoffsets) {
final BlockPos p = uppos.add(v);
final IBlockState st = world.getBlockState(p);
if(BlockCategories.isSameLog(st, broken_state)) {
queue.add(p);
to_break.add(p);
} else if(BlockCategories.isLeaves(st)) {
if(tracked_leaves_state==null) {
tracked_leaves_state=st;
to_decay.add(p);
} else if(BlockCategories.isSameLeaves(st, tracked_leaves_state)) {
to_decay.add(p);
} else {
checked.add(uppos);
}
} else {
checked.add(uppos);
}
}
}
}
// Lateral search
for(Vec3i v:hoffsets) {
final BlockPos p = pos.add(v);
if(checked.contains(p)) continue;
final IBlockState st = world.getBlockState(p);
if(BlockCategories.isSameLog(st, broken_state)) {
queue.add(p);
to_break.add(p);
} else if(BlockCategories.isLeaves(st)) {
if((tracked_leaves_state==null) || (BlockCategories.isSameLeaves(st, tracked_leaves_state))) {
to_decay.add(p);
} else {
checked.add(p);
}
} else {
checked.add(p);
}
}
}
}
// Determine lose logs between the leafs
{
for(BlockPos pos:to_decay) {
int distance = 2;
to_break.addAll(findBlocksAround(world, pos, broken_state, checked, distance));
}
if(!to_decay.isEmpty()) {
final IBlockState leaf_type_state = world.getBlockState(to_decay.get(0));
final ArrayList<BlockPos> leafs = to_decay;
to_decay = new ArrayList<BlockPos>();
for(BlockPos pos:leafs) {
int dist = 3;
to_decay.add(pos);
to_decay.addAll(findBlocksAround(world, pos, leaf_type_state, checked, dist));
}
}
}
// Break blocks
{
if(without_target_block) {
checked.remove(startPos);
} else {
to_break.add(startPos);
}
int num_broken = 0;
Collections.reverse(to_break);
for(BlockPos pos:to_break) {
if(++num_broken > max_blocks_to_break) break;
IBlockState state = world.getBlockState(pos);
world.setBlockToAir(pos);
state.getBlock().dropBlockAsItem(world, pos, state, 0);
}
for(BlockPos pos:to_decay) {
if(++num_broken > max_blocks_to_break) break;
IBlockState state = world.getBlockState(pos);
world.setBlockToAir(pos);
state.getBlock().dropBlockAsItem(world, pos, state, 0);
}
}
// And the bill.
{
return MathHelper.clamp(((to_break.size()*6/5)+(to_decay.size()/10)-1), 1, 65535);
}
}
}

View file

@ -1,58 +0,0 @@
/*
* @file JEIPlugin.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* JEI plugin (see https://github.com/mezz/JustEnoughItems/wiki/Creating-Plugins)
*/
package wile.engineersdecor.eapi.jei;
import wile.engineersdecor.ModEngineersDecor;
import wile.engineersdecor.ModContent;
import wile.engineersdecor.blocks.*;
import wile.engineersdecor.detail.ModConfig;
import net.minecraft.block.Block;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
@mezz.jei.api.JEIPlugin
public class JEIPlugin implements mezz.jei.api.IModPlugin
{
@Override
@SuppressWarnings("deprecation")
public void register(mezz.jei.api.IModRegistry registry)
{
// Block/item hiding
try {
for(Block e:ModContent.getRegisteredBlocks()) {
if(ModConfig.isOptedOut(e)) {
ItemStack stack = new ItemStack(Item.getItemFromBlock(e));
if(stack != null) {
if(!registry.getJeiHelpers().getIngredientBlacklist().isIngredientBlacklisted(stack)) {
registry.getJeiHelpers().getIngredientBlacklist().addIngredientToBlacklist(stack);
}
if(!registry.getJeiHelpers().getItemBlacklist().isItemBlacklisted(stack)) {
registry.getJeiHelpers().getItemBlacklist().addItemToBlacklist(stack);
}
}
}
}
} catch(Throwable e) {
ModEngineersDecor.logger.warn("Exception in JEI opt-out processing: '" + e.getMessage() + "', skipping further JEI optout processing.");
}
// Crafting table registration
if(!ModConfig.optout.without_crafting_table) {
try {
mezz.jei.api.recipe.transfer.IRecipeTransferRegistry recipeTranferRegistry = registry.getRecipeTransferRegistry();
recipeTranferRegistry.addRecipeTransferHandler(
BlockDecorCraftingTable.BContainer.class,
mezz.jei.api.recipe.VanillaRecipeCategoryUid.CRAFTING,
1, 9, 10, 44
);
} catch(Throwable e) {
ModEngineersDecor.logger.warn("Exception in JEI crafting table handler registration: '" + e.getMessage() + "'.");
}
}
}
}

View file

@ -1,57 +0,0 @@
/*
* @file ItemDecor.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2018 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* Basic item functionality for mod items.
*/
package wile.engineersdecor.items;
import wile.engineersdecor.ModEngineersDecor;
import wile.engineersdecor.detail.ModAuxiliaries;
import wile.engineersdecor.detail.ModConfig;
import net.minecraft.client.renderer.block.model.ModelBakery;
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.block.Block;
import net.minecraft.item.ItemBlock;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
import net.minecraftforge.client.model.ModelLoader;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import javax.annotation.Nullable;
import java.util.List;
public class ItemDecor extends ItemBlock
{
public ItemDecor(Block block)
{
super(block);
setRegistryName(block.getRegistryName());
setTranslationKey(ModEngineersDecor.MODID + "." + block.getRegistryName().getPath());
setMaxStackSize(64);
setCreativeTab(ModEngineersDecor.CREATIVE_TAB_ENGINEERSDECOR);
setHasSubtypes(false);
}
@SideOnly(Side.CLIENT)
public void initModel()
{
ModelResourceLocation rc = new ModelResourceLocation(getRegistryName(),"inventory");
ModelBakery.registerItemVariants(this, rc);
ModelLoader.setCustomMeshDefinition(this, stack->rc);
}
@Override
@SideOnly(Side.CLIENT)
public void addInformation(ItemStack stack, @Nullable World world, List<String> tooltip, ITooltipFlag flag)
{ ModAuxiliaries.Tooltip.addInformation(stack, world, tooltip, flag, true); }
@Nullable
public CreativeTabs getCreativeTab()
{ return ModConfig.isOptedOut(this) ? null : super.getCreativeTab(); }
}

View file

@ -1,347 +0,0 @@
/*
* @file Inventories.java
* @author Stefan Wilhelm (wile)
* @copyright (C) 2019 Stefan Wilhelm
* @license MIT (see https://opensource.org/licenses/MIT)
*
* General inventory item handling functionality.
*/
package wile.engineersdecor.libmc.detail;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.world.World;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.ISidedInventory;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper;
import net.minecraftforge.items.wrapper.InvWrapper;
import net.minecraftforge.items.wrapper.SidedInvWrapper;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
public class Inventories
{
public static boolean areItemStacksIdentical(ItemStack a, ItemStack b)
{ return (a.getItem()==b.getItem()) && ItemStack.areItemStackTagsEqual(a, b); }
public static boolean areItemStacksDifferent(ItemStack a, ItemStack b)
{ return (a.getItem()!=b.getItem()) || (!ItemStack.areItemStackTagsEqual(a, b)); }
public static IItemHandler itemhandler(World world, BlockPos pos, @Nullable EnumFacing side)
{
TileEntity te = world.getTileEntity(pos);
if(te==null) return null;
IItemHandler ih = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side);
if(ih!=null) return ih;
if((side!=null) && (te instanceof ISidedInventory)) return new SidedInvWrapper((ISidedInventory)te, side);
if(te instanceof IInventory) return new InvWrapper((IInventory)te);
return null;
}
public static ItemStack insert(IItemHandler inventory, ItemStack stack , boolean simulate)
{ return ItemHandlerHelper.insertItemStacked(inventory, stack, simulate); }
public static ItemStack insert(TileEntity te, @Nullable EnumFacing side, ItemStack stack, boolean simulate)
{
if(te==null) return stack;
IItemHandler hnd = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side);
if(hnd != null) {
hnd = (IItemHandler)te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side);
} else if((side!=null) && (te instanceof ISidedInventory)) {
hnd = new SidedInvWrapper((ISidedInventory)te, side);
} else if(te instanceof IInventory) {
hnd = new InvWrapper((IInventory)te);
}
return (hnd==null) ? stack : ItemHandlerHelper.insertItemStacked(hnd, stack, simulate);
}
public static ItemStack extract(IItemHandler inventory, @Nullable ItemStack match, int amount, boolean simulate)
{
if((inventory==null) || (amount<=0)) return ItemStack.EMPTY;
final int max = inventory.getSlots();
ItemStack out_stack = ItemStack.EMPTY;
for(int i=0; i<max; ++i) {
final ItemStack stack = inventory.getStackInSlot(i);
if(stack.isEmpty()) continue;
if(out_stack.isEmpty()) {
if((match!=null) && areItemStacksDifferent(stack, match)) continue;
out_stack = inventory.extractItem(i, amount, simulate);
} else if(areItemStacksIdentical(stack, out_stack)) {
ItemStack es = inventory.extractItem(i, (amount-out_stack.getCount()), simulate);
out_stack.grow(es.getCount());
}
if(out_stack.getCount() >= amount) break;
}
return out_stack;
}
private static ItemStack checked(ItemStack stack)
{ return stack.isEmpty() ? ItemStack.EMPTY : stack; } // explicit EMPTY return
public static class SlotRange
{
public final IInventory inventory;
public final int start_slot, end_slot;
public SlotRange(IInventory inv, int start, int end)
{ inventory=inv; start_slot=start; end_slot=end; }
/**
* Returns the number of stacks that match the given stack with NBT.
*/
public int stackMatchCount(final ItemStack ref_stack)
{
int n = 0; // ... std::accumulate() the old school way.
for(int i = start_slot; i < end_slot; ++i) {
if(areItemStacksIdentical(ref_stack, inventory.getStackInSlot(i))) ++n;
}
return n;
}
public int totalMatchingItemCount(final ItemStack ref_stack)
{
int n = 0;
for(int i = start_slot; i < end_slot; ++i) {
ItemStack stack = inventory.getStackInSlot(i);
if(areItemStacksIdentical(ref_stack, stack)) n += stack.getCount();
}
return n;
}
/**
* Moves as much items from the stack to the slots in range [start_slot, end_slot] of the inventory,
* filling up existing stacks first, then (player inventory only) checks appropriate empty slots next
* to stacks that have that item already, and last uses any empty slot that can be found.
* Returns the stack that is still remaining in the referenced `stack`.
*/
public ItemStack insert(final ItemStack stack_to_move, boolean only_fillup, int limit)
{ return insert(stack_to_move, only_fillup, limit, false, false); }
public ItemStack insert(final ItemStack stack_to_move, boolean only_fillup, int limit, boolean reverse, boolean force_group_stacks)
{
final ItemStack mvstack = stack_to_move.copy();
if((mvstack.isEmpty()) || (start_slot < 0) || (end_slot > inventory.getSizeInventory())) return checked(mvstack);
int limit_left = (limit>0) ? (Math.min(limit, mvstack.getMaxStackSize())) : (mvstack.getMaxStackSize());
boolean matches[] = new boolean[end_slot];
boolean empties[] = new boolean[end_slot];
int num_matches = 0;
for(int i = start_slot; i < end_slot; ++i) {
final int sno = reverse ? (end_slot-1-i) : (i);
final ItemStack stack = inventory.getStackInSlot(sno);
if(stack.isEmpty() || (!inventory.isItemValidForSlot(sno, mvstack))) {
empties[sno] = true;
} else if(areItemStacksIdentical(stack, mvstack)) {
matches[sno] = true;
++num_matches;
}
}
// first iteration: fillup existing stacks
for(int i = start_slot; i < end_slot; ++i) {
final int sno = reverse ? (end_slot-1-i) : (i);
if(empties[sno] || !matches[sno]) continue;
final ItemStack stack = inventory.getStackInSlot(sno);
int nmax = Math.min(limit_left, stack.getMaxStackSize() - stack.getCount());
if(mvstack.getCount() <= nmax) {
stack.setCount(stack.getCount()+mvstack.getCount());
inventory.setInventorySlotContents(sno, stack);
return ItemStack.EMPTY;
} else {
stack.grow(nmax);
mvstack.shrink(nmax);
inventory.setInventorySlotContents(sno, stack);
limit_left -= nmax;
}
}
if(only_fillup) return checked(mvstack);
if((num_matches>0) && ((force_group_stacks) || (inventory instanceof InventoryPlayer))) {
// second iteration: use appropriate empty slots,
// a) between
{
int insert_start = -1;
int insert_end = -1;
int i = start_slot+1;
for(;i < end_slot-1; ++i) {
final int sno = reverse ? (end_slot-1-i) : (i);
if(insert_start < 0) {
if(matches[sno]) insert_start = sno;
} else if(matches[sno]) {
insert_end = sno;
}
}
for(i=insert_start;i < insert_end; ++i) {
final int sno = reverse ? (end_slot-1-i) : (i);
if(!empties[sno]) continue;
int nmax = Math.min(limit_left, mvstack.getCount());
ItemStack moved = mvstack.copy();
moved.setCount(nmax);
mvstack.shrink(nmax);
inventory.setInventorySlotContents(sno, moved);
return checked(mvstack);
}
}
// b) before/after
{
for(int i = start_slot+1; i < end_slot-1; ++i) {
final int sno = reverse ? (end_slot-1-i) : (i);
if(!matches[sno]) continue;
int ii = (empties[sno-1]) ? (sno-1) : (empties[sno+1] ? (sno+1) : -1);
if(ii >= 0) {
int nmax = Math.min(limit_left, mvstack.getCount());
ItemStack moved = mvstack.copy();
moved.setCount(nmax);
mvstack.shrink(nmax);
inventory.setInventorySlotContents(ii, moved);
return checked(mvstack);
}
}
}
}
// third iteration: use any empty slots
for(int i = start_slot; i < end_slot; ++i) {
final int sno = reverse ? (end_slot-1-i) : (i);
if(!empties[sno]) continue;
int nmax = Math.min(limit_left, mvstack.getCount());
ItemStack placed = mvstack.copy();
placed.setCount(nmax);
mvstack.shrink(nmax);
inventory.setInventorySlotContents(sno, placed);
return checked(mvstack);
}
return checked(mvstack);
}
/**
* Moves as much items from the slots in range [start_slot, end_slot] of the inventory into a new stack.
* Implicitly shrinks the inventory stacks and the `request_stack`.
*/
public ItemStack extract(final ItemStack request_stack)
{
if(request_stack.isEmpty()) return ItemStack.EMPTY;
final IInventory inventory = this.inventory;
List<ItemStack> matches = new ArrayList<>();
for(int i = start_slot; i < end_slot; ++i) {
final ItemStack stack = inventory.getStackInSlot(i);
if((!stack.isEmpty()) && (areItemStacksIdentical(stack, request_stack))) {
if(stack.hasTagCompound()) {
final NBTTagCompound nbt = stack.getTagCompound();
int n = nbt.getSize();
if((n > 0) && (nbt.hasKey("Damage"))) --n;
if(n > 0) continue;
}
matches.add(stack);
}
}
matches.sort(Comparator.comparingInt(ItemStack::getCount));
if(matches.isEmpty()) return ItemStack.EMPTY;
int n_left = request_stack.getCount();
ItemStack fetched_stack = matches.get(0).splitStack(n_left);
n_left -= fetched_stack.getCount();
for(int i=1; (i<matches.size()) && (n_left>0); ++i) {
ItemStack stack = matches.get(i).splitStack(n_left);
n_left -= stack.getCount();
fetched_stack.grow(stack.getCount());
}
return checked(fetched_stack);
}
}
public static class InventoryRange implements IInventory
{
public final IInventory inventory;
public final int offset, size;
public InventoryRange(IInventory inventory, int offset, int size)
{ this.inventory = inventory; this.offset = offset; this.size = size; }
@Override
public void clear()
{ inventory.clear(); }
@Override
public int getSizeInventory()
{ return size; }
@Override
public boolean isEmpty()
{ for(int i=0; i<size; ++i) if(!inventory.getStackInSlot(offset+i).isEmpty()){return false;} return true; }
@Override
public ItemStack getStackInSlot(int index)
{ return inventory.getStackInSlot(offset+index); }
@Override
public ItemStack decrStackSize(int index, int count)
{ return inventory.decrStackSize(offset+index, count); }
@Override
public ItemStack removeStackFromSlot(int index)
{ return inventory.removeStackFromSlot(offset+index); }
@Override
public void setInventorySlotContents(int index, ItemStack stack)
{ inventory.setInventorySlotContents(offset+index, stack); }
@Override
public int getInventoryStackLimit()
{ return inventory.getInventoryStackLimit(); }
@Override
public void markDirty()
{ inventory.markDirty(); }
@Override
public boolean isUsableByPlayer(EntityPlayer player)
{ return inventory.isUsableByPlayer(player); }
@Override
public void openInventory(EntityPlayer player)
{ inventory.openInventory(player); }
@Override
public void closeInventory(EntityPlayer player)
{ inventory.closeInventory(player); }
@Override
public boolean isItemValidForSlot(int index, ItemStack stack)
{ return inventory.isItemValidForSlot(offset+index, stack); }
@Override
public int getField(int index)
{ return 0; }
@Override
public void setField(int index, int value)
{}
@Override
public int getFieldCount()
{ return 0; }
@Override
public String getName()
{ return inventory.getName(); }
@Override
public boolean hasCustomName()
{ return inventory.hasCustomName(); }
@Override
public ITextComponent getDisplayName()
{ return inventory.getDisplayName(); }
}
}

View file

@ -1,20 +0,0 @@
{
"forge_marker": 1,
"defaults": {
"model": "engineersdecor:std/decor_full_block_model",
"textures": { "all": "engineersdecor:blocks/clinker_brick/clinker_brick_texture0" }
},
"variants": {
"normal": [
{ "textures": { "all": "engineersdecor:blocks/clinker_brick/clinker_brick_texture0" } },
{ "textures": { "all": "engineersdecor:blocks/clinker_brick/clinker_brick_texture1" } },
{ "textures": { "all": "engineersdecor:blocks/clinker_brick/clinker_brick_texture2" } },
{ "textures": { "all": "engineersdecor:blocks/clinker_brick/clinker_brick_texture3" } },
{ "textures": { "all": "engineersdecor:blocks/clinker_brick/clinker_brick_texture4" } },
{ "textures": { "all": "engineersdecor:blocks/clinker_brick/clinker_brick_texture5" } },
{ "textures": { "all": "engineersdecor:blocks/clinker_brick/clinker_brick_texture6" } },
{ "textures": { "all": "engineersdecor:blocks/clinker_brick/clinker_brick_texture7" } }
],
"inventory": [{}]
}
}

View file

@ -1,26 +0,0 @@
{
"forge_marker": 1,
"defaults": {
"model": "engineersdecor:slab/slab_s0_model",
"textures": { "all": "engineersdecor:blocks/clinker_brick/clinker_brick_texture0" }
},
"variants": {
"normal": [{}],
"inventory": [{}],
"parts": {
"0" : { "model": "engineersdecor:slab/slab_s0_model" },
"1" : { "model": "engineersdecor:slab/slab_s1_model" },
"2" : { "model": "engineersdecor:slab/slab_s2_model" }
},
"tvariant": {
"0":{"textures":{"all": "engineersdecor:blocks/clinker_brick/clinker_brick_texture0"}},
"1":{"textures":{"all": "engineersdecor:blocks/clinker_brick/clinker_brick_texture1"}},
"2":{"textures":{"all": "engineersdecor:blocks/clinker_brick/clinker_brick_texture2"}},
"3":{"textures":{"all": "engineersdecor:blocks/clinker_brick/clinker_brick_texture3"}},
"4":{"textures":{"all": "engineersdecor:blocks/clinker_brick/clinker_brick_texture4"}},
"5":{"textures":{"all": "engineersdecor:blocks/clinker_brick/clinker_brick_texture5"}},
"6":{"textures":{"all": "engineersdecor:blocks/clinker_brick/clinker_brick_texture6"}},
"7":{"textures":{"all": "engineersdecor:blocks/clinker_brick/clinker_brick_texture7"}}
}
}
}

View file

@ -1,20 +0,0 @@
{
"forge_marker": 1,
"defaults": {
"model": "engineersdecor:std/decor_full_block_model",
"textures": { "all": "engineersdecor:blocks/clinker_brick/clinker_brick_stained_texture0" }
},
"variants": {
"normal": [
{ "textures": { "all": "engineersdecor:blocks/clinker_brick/clinker_brick_stained_texture0" } },
{ "textures": { "all": "engineersdecor:blocks/clinker_brick/clinker_brick_stained_texture1" } },
{ "textures": { "all": "engineersdecor:blocks/clinker_brick/clinker_brick_stained_texture2" } },
{ "textures": { "all": "engineersdecor:blocks/clinker_brick/clinker_brick_stained_texture3" } },
{ "textures": { "all": "engineersdecor:blocks/clinker_brick/clinker_brick_stained_texture4" } },
{ "textures": { "all": "engineersdecor:blocks/clinker_brick/clinker_brick_stained_texture5" } },
{ "textures": { "all": "engineersdecor:blocks/clinker_brick/clinker_brick_stained_texture6" } },
{ "textures": { "all": "engineersdecor:blocks/clinker_brick/clinker_brick_stained_texture7" } }
],
"inventory": [{}]
}
}

View file

@ -1,26 +0,0 @@
{
"forge_marker": 1,
"defaults": {
"model": "engineersdecor:slab/slab_s0_model",
"textures": { "all": "engineersdecor:blocks/clinker_brick/clinker_brick_stained_texture0" }
},
"variants": {
"normal": [{}],
"inventory": [{}],
"parts": {
"0" : { "model": "engineersdecor:slab/slab_s0_model" },
"1" : { "model": "engineersdecor:slab/slab_s1_model" },
"2" : { "model": "engineersdecor:slab/slab_s2_model" }
},
"tvariant": {
"0":{"textures":{"all": "engineersdecor:blocks/clinker_brick/clinker_brick_stained_texture0"}},
"1":{"textures":{"all": "engineersdecor:blocks/clinker_brick/clinker_brick_stained_texture1"}},
"2":{"textures":{"all": "engineersdecor:blocks/clinker_brick/clinker_brick_stained_texture2"}},
"3":{"textures":{"all": "engineersdecor:blocks/clinker_brick/clinker_brick_stained_texture3"}},
"4":{"textures":{"all": "engineersdecor:blocks/clinker_brick/clinker_brick_stained_texture4"}},
"5":{"textures":{"all": "engineersdecor:blocks/clinker_brick/clinker_brick_stained_texture5"}},
"6":{"textures":{"all": "engineersdecor:blocks/clinker_brick/clinker_brick_stained_texture6"}},
"7":{"textures":{"all": "engineersdecor:blocks/clinker_brick/clinker_brick_stained_texture7"}}
}
}
}

View file

@ -1,56 +0,0 @@
{
"forge_marker": 1,
"defaults": {
"model": "engineersdecor:stairs/decor_straight_stairs_model",
"textures": {
"particle": "engineersdecor:blocks/clinker_brick/clinker_brick_stained_texture0",
"bottom": "engineersdecor:blocks/clinker_brick/clinker_brick_stained_texture0",
"top": "engineersdecor:blocks/clinker_brick/clinker_brick_stained_texture0",
"side": "engineersdecor:blocks/clinker_brick/clinker_brick_stained_texture0"
}
},
"variants": {
"normal": [{}],
"inventory": [{}],
"facing=east,half=bottom,shape=straight": { "model": "engineersdecor:stairs/decor_straight_stairs_model" },
"facing=west,half=bottom,shape=straight": { "model": "engineersdecor:stairs/decor_straight_stairs_model", "y": 180, "uvlock": true },
"facing=south,half=bottom,shape=straight": { "model": "engineersdecor:stairs/decor_straight_stairs_model", "y": 90, "uvlock": true },
"facing=north,half=bottom,shape=straight": { "model": "engineersdecor:stairs/decor_straight_stairs_model", "y": 270, "uvlock": true },
"facing=east,half=bottom,shape=outer_right": { "model": "engineersdecor:stairs/decor_outer_stairs_model" },
"facing=west,half=bottom,shape=outer_right": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "y": 180, "uvlock": true },
"facing=south,half=bottom,shape=outer_right": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "y": 90, "uvlock": true },
"facing=north,half=bottom,shape=outer_right": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "y": 270, "uvlock": true },
"facing=east,half=bottom,shape=outer_left": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "y": 270, "uvlock": true },
"facing=west,half=bottom,shape=outer_left": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "y": 90, "uvlock": true },
"facing=south,half=bottom,shape=outer_left": { "model": "engineersdecor:stairs/decor_outer_stairs_model" },
"facing=north,half=bottom,shape=outer_left": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "y": 180, "uvlock": true },
"facing=east,half=bottom,shape=inner_right": { "model": "engineersdecor:stairs/decor_inner_stairs_model" },
"facing=west,half=bottom,shape=inner_right": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "y": 180, "uvlock": true },
"facing=south,half=bottom,shape=inner_right": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "y": 90, "uvlock": true },
"facing=north,half=bottom,shape=inner_right": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "y": 270, "uvlock": true },
"facing=east,half=bottom,shape=inner_left": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "y": 270, "uvlock": true },
"facing=west,half=bottom,shape=inner_left": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "y": 90, "uvlock": true },
"facing=south,half=bottom,shape=inner_left": { "model": "engineersdecor:stairs/decor_inner_stairs_model" },
"facing=north,half=bottom,shape=inner_left": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "y": 180, "uvlock": true },
"facing=east,half=top,shape=straight": { "model": "engineersdecor:stairs/decor_straight_stairs_model", "x": 180, "uvlock": true },
"facing=west,half=top,shape=straight": { "model": "engineersdecor:stairs/decor_straight_stairs_model", "x": 180, "y": 180, "uvlock": true },
"facing=south,half=top,shape=straight": { "model": "engineersdecor:stairs/decor_straight_stairs_model", "x": 180, "y": 90, "uvlock": true },
"facing=north,half=top,shape=straight": { "model": "engineersdecor:stairs/decor_straight_stairs_model", "x": 180, "y": 270, "uvlock": true },
"facing=east,half=top,shape=outer_right": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "x": 180, "y": 90, "uvlock": true },
"facing=west,half=top,shape=outer_right": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "x": 180, "y": 270, "uvlock": true },
"facing=south,half=top,shape=outer_right": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "x": 180, "y": 180, "uvlock": true },
"facing=north,half=top,shape=outer_right": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "x": 180, "uvlock": true },
"facing=east,half=top,shape=outer_left": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "x": 180, "uvlock": true },
"facing=west,half=top,shape=outer_left": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "x": 180, "y": 180, "uvlock": true },
"facing=south,half=top,shape=outer_left": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "x": 180, "y": 90, "uvlock": true },
"facing=north,half=top,shape=outer_left": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "x": 180, "y": 270, "uvlock": true },
"facing=east,half=top,shape=inner_right": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "x": 180, "y": 90, "uvlock": true },
"facing=west,half=top,shape=inner_right": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "x": 180, "y": 270, "uvlock": true },
"facing=south,half=top,shape=inner_right": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "x": 180, "y": 180, "uvlock": true },
"facing=north,half=top,shape=inner_right": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "x": 180, "uvlock": true },
"facing=east,half=top,shape=inner_left": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "x": 180, "uvlock": true },
"facing=west,half=top,shape=inner_left": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "x": 180, "y": 180, "uvlock": true },
"facing=south,half=top,shape=inner_left": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "x": 180, "y": 90, "uvlock": true },
"facing=north,half=top,shape=inner_left": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "x": 180, "y": 270, "uvlock": true }
}
}

View file

@ -1,56 +0,0 @@
{
"forge_marker": 1,
"defaults": {
"model": "engineersdecor:stairs/decor_straight_stairs_model",
"textures": {
"particle": "engineersdecor:blocks/clinker_brick/clinker_brick_texture0",
"bottom": "engineersdecor:blocks/clinker_brick/clinker_brick_texture0",
"top": "engineersdecor:blocks/clinker_brick/clinker_brick_texture0",
"side": "engineersdecor:blocks/clinker_brick/clinker_brick_texture0"
}
},
"variants": {
"normal": [{}],
"inventory": [{}],
"facing=east,half=bottom,shape=straight": { "model": "engineersdecor:stairs/decor_straight_stairs_model" },
"facing=west,half=bottom,shape=straight": { "model": "engineersdecor:stairs/decor_straight_stairs_model", "y": 180, "uvlock": true },
"facing=south,half=bottom,shape=straight": { "model": "engineersdecor:stairs/decor_straight_stairs_model", "y": 90, "uvlock": true },
"facing=north,half=bottom,shape=straight": { "model": "engineersdecor:stairs/decor_straight_stairs_model", "y": 270, "uvlock": true },
"facing=east,half=bottom,shape=outer_right": { "model": "engineersdecor:stairs/decor_outer_stairs_model" },
"facing=west,half=bottom,shape=outer_right": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "y": 180, "uvlock": true },
"facing=south,half=bottom,shape=outer_right": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "y": 90, "uvlock": true },
"facing=north,half=bottom,shape=outer_right": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "y": 270, "uvlock": true },
"facing=east,half=bottom,shape=outer_left": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "y": 270, "uvlock": true },
"facing=west,half=bottom,shape=outer_left": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "y": 90, "uvlock": true },
"facing=south,half=bottom,shape=outer_left": { "model": "engineersdecor:stairs/decor_outer_stairs_model" },
"facing=north,half=bottom,shape=outer_left": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "y": 180, "uvlock": true },
"facing=east,half=bottom,shape=inner_right": { "model": "engineersdecor:stairs/decor_inner_stairs_model" },
"facing=west,half=bottom,shape=inner_right": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "y": 180, "uvlock": true },
"facing=south,half=bottom,shape=inner_right": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "y": 90, "uvlock": true },
"facing=north,half=bottom,shape=inner_right": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "y": 270, "uvlock": true },
"facing=east,half=bottom,shape=inner_left": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "y": 270, "uvlock": true },
"facing=west,half=bottom,shape=inner_left": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "y": 90, "uvlock": true },
"facing=south,half=bottom,shape=inner_left": { "model": "engineersdecor:stairs/decor_inner_stairs_model" },
"facing=north,half=bottom,shape=inner_left": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "y": 180, "uvlock": true },
"facing=east,half=top,shape=straight": { "model": "engineersdecor:stairs/decor_straight_stairs_model", "x": 180, "uvlock": true },
"facing=west,half=top,shape=straight": { "model": "engineersdecor:stairs/decor_straight_stairs_model", "x": 180, "y": 180, "uvlock": true },
"facing=south,half=top,shape=straight": { "model": "engineersdecor:stairs/decor_straight_stairs_model", "x": 180, "y": 90, "uvlock": true },
"facing=north,half=top,shape=straight": { "model": "engineersdecor:stairs/decor_straight_stairs_model", "x": 180, "y": 270, "uvlock": true },
"facing=east,half=top,shape=outer_right": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "x": 180, "y": 90, "uvlock": true },
"facing=west,half=top,shape=outer_right": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "x": 180, "y": 270, "uvlock": true },
"facing=south,half=top,shape=outer_right": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "x": 180, "y": 180, "uvlock": true },
"facing=north,half=top,shape=outer_right": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "x": 180, "uvlock": true },
"facing=east,half=top,shape=outer_left": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "x": 180, "uvlock": true },
"facing=west,half=top,shape=outer_left": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "x": 180, "y": 180, "uvlock": true },
"facing=south,half=top,shape=outer_left": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "x": 180, "y": 90, "uvlock": true },
"facing=north,half=top,shape=outer_left": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "x": 180, "y": 270, "uvlock": true },
"facing=east,half=top,shape=inner_right": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "x": 180, "y": 90, "uvlock": true },
"facing=west,half=top,shape=inner_right": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "x": 180, "y": 270, "uvlock": true },
"facing=south,half=top,shape=inner_right": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "x": 180, "y": 180, "uvlock": true },
"facing=north,half=top,shape=inner_right": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "x": 180, "uvlock": true },
"facing=east,half=top,shape=inner_left": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "x": 180, "uvlock": true },
"facing=west,half=top,shape=inner_left": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "x": 180, "y": 180, "uvlock": true },
"facing=south,half=top,shape=inner_left": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "x": 180, "y": 90, "uvlock": true },
"facing=north,half=top,shape=inner_left": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "x": 180, "y": 270, "uvlock": true }
}
}

View file

@ -1,30 +0,0 @@
{
"forge_marker": 1,
"defaults": {
"model": "engineersdecor:wall/clinker_brick_wall_default",
"textures": {
"wall": "engineersdecor:blocks/clinker_brick/clinker_brick_wall0",
"postside": "engineersdecor:blocks/clinker_brick/clinker_brick_pole_side",
"top": "engineersdecor:blocks/clinker_brick/clinker_brick_top",
"particle": "engineersdecor:blocks/clinker_brick/clinker_brick_top"
}
},
"variants": {
"inventory": { "model": "engineersdecor:wall/clinker_brick_wall_inventory" },
"up" : { "false":{}, "true": {"submodel": {"clinker_wall_up" : {"model": "engineersdecor:wall/clinker_brick_wall_post" }}} },
"north": { "false":{}, "true": {"submodel": {"clinker_wall_north" : {"model": "engineersdecor:wall/clinker_brick_wall_side", "uvlock": true, "y": 0 }}} },
"east" : { "false":{}, "true": {"submodel": {"clinker_wall_east" : {"model": "engineersdecor:wall/clinker_brick_wall_side", "uvlock": true, "y": 90 }}} },
"south": { "false":{}, "true": {"submodel": {"clinker_wall_south" : {"model": "engineersdecor:wall/clinker_brick_wall_side", "uvlock": true, "y": 180 }}} },
"west" : { "false":{}, "true": {"submodel": {"clinker_wall_west" : {"model": "engineersdecor:wall/clinker_brick_wall_side", "uvlock": true, "y": 270 }}} },
"tvariant": {
"0":{"textures":{"wall": "engineersdecor:blocks/clinker_brick/clinker_brick_wall0"}},
"1":{"textures":{"wall": "engineersdecor:blocks/clinker_brick/clinker_brick_wall1"}},
"2":{"textures":{"wall": "engineersdecor:blocks/clinker_brick/clinker_brick_wall2"}},
"3":{"textures":{"wall": "engineersdecor:blocks/clinker_brick/clinker_brick_wall3"}},
"4":{"textures":{"wall": "engineersdecor:blocks/clinker_brick/clinker_brick_wall4"}},
"5":{"textures":{"wall": "engineersdecor:blocks/clinker_brick/clinker_brick_wall5"}},
"6":{"textures":{"wall": "engineersdecor:blocks/clinker_brick/clinker_brick_wall6"}},
"7":{"textures":{"wall": "engineersdecor:blocks/clinker_brick/clinker_brick_wall7"}}
}
}
}

View file

@ -1,19 +0,0 @@
{
"forge_marker": 1,
"defaults": {
"model": "engineersdecor:wall/concrete_wall_default",
"textures": {
"wall": "engineersdecor:blocks/iestyle/stone_decoration_concrete_by_blusunrize",
"particle": "engineersdecor:blocks/iestyle/stone_decoration_concrete_by_blusunrize"
}
},
"variants": {
"inventory": { "model": "engineersdecor:wall/concrete_wall_inventory" },
"up" : { "false":{}, "true": {"submodel": {"concrete_wall_up" : {"model": "engineersdecor:wall/concrete_wall_post" }}} },
"north": { "false":{}, "true": {"submodel": {"concrete_wall_north" : {"model": "engineersdecor:wall/concrete_wall_side", "uvlock": true, "y": 0 }}} },
"east" : { "false":{}, "true": {"submodel": {"concrete_wall_east" : {"model": "engineersdecor:wall/concrete_wall_side", "uvlock": true, "y": 90 }}} },
"south": { "false":{}, "true": {"submodel": {"concrete_wall_south" : {"model": "engineersdecor:wall/concrete_wall_side", "uvlock": true, "y": 180 }}} },
"west" : { "false":{}, "true": {"submodel": {"concrete_wall_west" : {"model": "engineersdecor:wall/concrete_wall_side", "uvlock": true, "y": 270 }}} },
"tvariant": { "0":{},"1":{},"2":{},"3":{},"4":{},"5":{},"6":{},"7":{} }
}
}

View file

@ -1,12 +0,0 @@
{
"forge_marker": 1,
"defaults": {
"model": "engineersdecor:device/factory_dropper_model"
},
"variants": {
"normal": [{}],
"inventory": [{}],
"facing": { "north":{"y":0}, "south":{"y":180}, "west":{"y":270}, "east":{"y":90}, "up": {"x":-90}, "down": {"x":90} },
"open": { "false":{}, "true":{ "model": "engineersdecor:device/factory_dropper_model_open" } }
}
}

View file

@ -1,18 +0,0 @@
{
"forge_marker": 1,
"defaults": {
"model": "engineersdecor:device/factory_hopper_model"
},
"variants": {
"normal": [{}],
"inventory": [{}],
"facing": {
"north":{"y":0},
"south":{"y":180},
"west":{"y":270},
"east":{"y":90},
"up": { "model": "engineersdecor:device/factory_hopper_model_up" },
"down": { "model": "engineersdecor:device/factory_hopper_model_down" }
}
}
}

View file

@ -1,11 +0,0 @@
{
"forge_marker": 1,
"defaults": {
"model": "engineersdecor:device/factory_placer_model"
},
"variants": {
"normal": [{}],
"inventory": [{}],
"facing": { "north":{"y":0}, "south":{"y":180}, "west":{"y":270}, "east":{"y":90}, "up": {"x":-90}, "down": {"x":90} }
}
}

View file

@ -1,20 +0,0 @@
{
"forge_marker": 1,
"defaults": {
"model": "engineersdecor:std/decor_full_block_model",
"textures": { "all": "engineersdecor:blocks/concrete/gas_concrete_texture0" }
},
"variants": {
"normal": [
{ "textures": { "all": "engineersdecor:blocks/concrete/gas_concrete_texture0" } },
{ "textures": { "all": "engineersdecor:blocks/concrete/gas_concrete_texture1" } },
{ "textures": { "all": "engineersdecor:blocks/concrete/gas_concrete_texture2" } },
{ "textures": { "all": "engineersdecor:blocks/concrete/gas_concrete_texture3" } },
{ "textures": { "all": "engineersdecor:blocks/concrete/gas_concrete_texture4" } },
{ "textures": { "all": "engineersdecor:blocks/concrete/gas_concrete_texture5" } },
{ "textures": { "all": "engineersdecor:blocks/concrete/gas_concrete_texture6" } },
{ "textures": { "all": "engineersdecor:blocks/concrete/gas_concrete_texture7" } }
],
"inventory": [{}]
}
}

View file

@ -1,26 +0,0 @@
{
"forge_marker": 1,
"defaults": {
"model": "engineersdecor:slab/slab_s0_model",
"textures": { "all": "engineersdecor:blocks/concrete/gas_concrete_texture0" }
},
"variants": {
"normal": [{}],
"inventory": [{}],
"parts": {
"0" : { "model": "engineersdecor:slab/slab_s0_model" },
"1" : { "model": "engineersdecor:slab/slab_s1_model" },
"2" : { "model": "engineersdecor:slab/slab_s2_model" }
},
"tvariant": {
"0":{"textures":{"all": "engineersdecor:blocks/concrete/gas_concrete_texture0"}},
"1":{"textures":{"all": "engineersdecor:blocks/concrete/gas_concrete_texture1"}},
"2":{"textures":{"all": "engineersdecor:blocks/concrete/gas_concrete_texture2"}},
"3":{"textures":{"all": "engineersdecor:blocks/concrete/gas_concrete_texture3"}},
"4":{"textures":{"all": "engineersdecor:blocks/concrete/gas_concrete_texture4"}},
"5":{"textures":{"all": "engineersdecor:blocks/concrete/gas_concrete_texture5"}},
"6":{"textures":{"all": "engineersdecor:blocks/concrete/gas_concrete_texture6"}},
"7":{"textures":{"all": "engineersdecor:blocks/concrete/gas_concrete_texture7"}}
}
}
}

View file

@ -1,56 +0,0 @@
{
"forge_marker": 1,
"defaults": {
"model": "engineersdecor:stairs/decor_straight_stairs_model",
"textures": {
"particle": "engineersdecor:blocks/concrete/gas_concrete_texture0",
"bottom": "engineersdecor:blocks/concrete/gas_concrete_texture0",
"top": "engineersdecor:blocks/concrete/gas_concrete_texture0",
"side": "engineersdecor:blocks/concrete/gas_concrete_texture0"
}
},
"variants": {
"normal": [{}],
"inventory": [{}],
"facing=east,half=bottom,shape=straight": { "model": "engineersdecor:stairs/decor_straight_stairs_model" },
"facing=west,half=bottom,shape=straight": { "model": "engineersdecor:stairs/decor_straight_stairs_model", "y": 180, "uvlock": true },
"facing=south,half=bottom,shape=straight": { "model": "engineersdecor:stairs/decor_straight_stairs_model", "y": 90, "uvlock": true },
"facing=north,half=bottom,shape=straight": { "model": "engineersdecor:stairs/decor_straight_stairs_model", "y": 270, "uvlock": true },
"facing=east,half=bottom,shape=outer_right": { "model": "engineersdecor:stairs/decor_outer_stairs_model" },
"facing=west,half=bottom,shape=outer_right": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "y": 180, "uvlock": true },
"facing=south,half=bottom,shape=outer_right": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "y": 90, "uvlock": true },
"facing=north,half=bottom,shape=outer_right": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "y": 270, "uvlock": true },
"facing=east,half=bottom,shape=outer_left": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "y": 270, "uvlock": true },
"facing=west,half=bottom,shape=outer_left": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "y": 90, "uvlock": true },
"facing=south,half=bottom,shape=outer_left": { "model": "engineersdecor:stairs/decor_outer_stairs_model" },
"facing=north,half=bottom,shape=outer_left": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "y": 180, "uvlock": true },
"facing=east,half=bottom,shape=inner_right": { "model": "engineersdecor:stairs/decor_inner_stairs_model" },
"facing=west,half=bottom,shape=inner_right": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "y": 180, "uvlock": true },
"facing=south,half=bottom,shape=inner_right": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "y": 90, "uvlock": true },
"facing=north,half=bottom,shape=inner_right": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "y": 270, "uvlock": true },
"facing=east,half=bottom,shape=inner_left": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "y": 270, "uvlock": true },
"facing=west,half=bottom,shape=inner_left": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "y": 90, "uvlock": true },
"facing=south,half=bottom,shape=inner_left": { "model": "engineersdecor:stairs/decor_inner_stairs_model" },
"facing=north,half=bottom,shape=inner_left": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "y": 180, "uvlock": true },
"facing=east,half=top,shape=straight": { "model": "engineersdecor:stairs/decor_straight_stairs_model", "x": 180, "uvlock": true },
"facing=west,half=top,shape=straight": { "model": "engineersdecor:stairs/decor_straight_stairs_model", "x": 180, "y": 180, "uvlock": true },
"facing=south,half=top,shape=straight": { "model": "engineersdecor:stairs/decor_straight_stairs_model", "x": 180, "y": 90, "uvlock": true },
"facing=north,half=top,shape=straight": { "model": "engineersdecor:stairs/decor_straight_stairs_model", "x": 180, "y": 270, "uvlock": true },
"facing=east,half=top,shape=outer_right": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "x": 180, "y": 90, "uvlock": true },
"facing=west,half=top,shape=outer_right": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "x": 180, "y": 270, "uvlock": true },
"facing=south,half=top,shape=outer_right": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "x": 180, "y": 180, "uvlock": true },
"facing=north,half=top,shape=outer_right": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "x": 180, "uvlock": true },
"facing=east,half=top,shape=outer_left": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "x": 180, "uvlock": true },
"facing=west,half=top,shape=outer_left": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "x": 180, "y": 180, "uvlock": true },
"facing=south,half=top,shape=outer_left": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "x": 180, "y": 90, "uvlock": true },
"facing=north,half=top,shape=outer_left": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "x": 180, "y": 270, "uvlock": true },
"facing=east,half=top,shape=inner_right": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "x": 180, "y": 90, "uvlock": true },
"facing=west,half=top,shape=inner_right": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "x": 180, "y": 270, "uvlock": true },
"facing=south,half=top,shape=inner_right": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "x": 180, "y": 180, "uvlock": true },
"facing=north,half=top,shape=inner_right": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "x": 180, "uvlock": true },
"facing=east,half=top,shape=inner_left": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "x": 180, "uvlock": true },
"facing=west,half=top,shape=inner_left": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "x": 180, "y": 180, "uvlock": true },
"facing=south,half=top,shape=inner_left": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "x": 180, "y": 90, "uvlock": true },
"facing=north,half=top,shape=inner_left": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "x": 180, "y": 270, "uvlock": true }
}
}

View file

@ -1,28 +0,0 @@
{
"forge_marker": 1,
"defaults": {
"model": "engineersdecor:wall/concrete_wall_default",
"textures": {
"wall": "engineersdecor:blocks/concrete/gas_concrete_texture0",
"particle": "engineersdecor:blocks/concrete/gas_concrete_texture0"
}
},
"variants": {
"inventory": { "model": "engineersdecor:wall/concrete_wall_inventory" },
"up" : { "false":{}, "true": {"submodel": {"concrete_wall_up" : {"model": "engineersdecor:wall/concrete_wall_post" }}} },
"north": { "false":{}, "true": {"submodel": {"concrete_wall_north" : {"model": "engineersdecor:wall/concrete_wall_side", "uvlock": true, "y": 0 }}} },
"east" : { "false":{}, "true": {"submodel": {"concrete_wall_east" : {"model": "engineersdecor:wall/concrete_wall_side", "uvlock": true, "y": 90 }}} },
"south": { "false":{}, "true": {"submodel": {"concrete_wall_south" : {"model": "engineersdecor:wall/concrete_wall_side", "uvlock": true, "y": 180 }}} },
"west" : { "false":{}, "true": {"submodel": {"concrete_wall_west" : {"model": "engineersdecor:wall/concrete_wall_side", "uvlock": true, "y": 270 }}} },
"tvariant": {
"0":{"textures":{ "wall": "engineersdecor:blocks/concrete/gas_concrete_texture0" }},
"1":{"textures":{ "wall": "engineersdecor:blocks/concrete/gas_concrete_texture1" }},
"2":{"textures":{ "wall": "engineersdecor:blocks/concrete/gas_concrete_texture2" }},
"3":{"textures":{ "wall": "engineersdecor:blocks/concrete/gas_concrete_texture3" }},
"4":{"textures":{ "wall": "engineersdecor:blocks/concrete/gas_concrete_texture4" }},
"5":{"textures":{ "wall": "engineersdecor:blocks/concrete/gas_concrete_texture5" }},
"6":{"textures":{ "wall": "engineersdecor:blocks/concrete/gas_concrete_texture6" }},
"7":{"textures":{ "wall": "engineersdecor:blocks/concrete/gas_concrete_texture7" }}
}
}
}

View file

@ -1,28 +0,0 @@
{
"forge_marker": 1,
"defaults": {
"model": "engineersdecor:slab/halfslab_s0_model",
"textures": { "all": "immersiveengineering:blocks/stone_decoration_concrete" }
},
"variants": {
"normal": [{}],
"inventory": [{}],
"parts": {
"0" : { "model": "engineersdecor:slab/halfslab_s0_model" },
"1" : { "model": "engineersdecor:slab/halfslab_s1_model" },
"2" : { "model": "engineersdecor:slab/halfslab_s2_model" },
"3" : { "model": "engineersdecor:slab/halfslab_s3_model" },
"4" : { "model": "engineersdecor:slab/halfslab_s4_model" },
"5" : { "model": "engineersdecor:slab/halfslab_s5_model" },
"6" : { "model": "engineersdecor:slab/halfslab_s6_model" },
"7" : { "model": "engineersdecor:slab/halfslab_s7_model" },
"8" : { "model": "engineersdecor:slab/halfslab_s8_model" },
"9" : { "model": "engineersdecor:slab/halfslab_s9_model" },
"10": { "model": "engineersdecor:slab/halfslab_sa_model" },
"11": { "model": "engineersdecor:slab/halfslab_sb_model" },
"12": { "model": "engineersdecor:slab/halfslab_sc_model" },
"13": { "model": "engineersdecor:slab/halfslab_sd_model" },
"14": { "model": "engineersdecor:slab/halfslab_se_model" }
}
}
}

View file

@ -1,28 +0,0 @@
{
"forge_marker": 1,
"defaults": {
"model": "engineersdecor:slab/halfslab_s0_model",
"textures": { "all": "engineersdecor:blocks/concrete/gas_concrete_texture0" }
},
"variants": {
"normal": [{}],
"inventory": [{}],
"parts": {
"0" : { "model": "engineersdecor:slab/halfslab_s0_model" },
"1" : { "model": "engineersdecor:slab/halfslab_s1_model" },
"2" : { "model": "engineersdecor:slab/halfslab_s2_model" },
"3" : { "model": "engineersdecor:slab/halfslab_s3_model" },
"4" : { "model": "engineersdecor:slab/halfslab_s4_model" },
"5" : { "model": "engineersdecor:slab/halfslab_s5_model" },
"6" : { "model": "engineersdecor:slab/halfslab_s6_model" },
"7" : { "model": "engineersdecor:slab/halfslab_s7_model" },
"8" : { "model": "engineersdecor:slab/halfslab_s8_model" },
"9" : { "model": "engineersdecor:slab/halfslab_s9_model" },
"10": { "model": "engineersdecor:slab/halfslab_sa_model" },
"11": { "model": "engineersdecor:slab/halfslab_sb_model" },
"12": { "model": "engineersdecor:slab/halfslab_sc_model" },
"13": { "model": "engineersdecor:slab/halfslab_sd_model" },
"14": { "model": "engineersdecor:slab/halfslab_se_model" }
}
}
}

View file

@ -1,28 +0,0 @@
{
"forge_marker": 1,
"defaults": {
"model": "engineersdecor:slab/halfslab_s0_model",
"textures": { "all": "engineersdecor:blocks/concrete/rebar_concrete_texture0" }
},
"variants": {
"normal": [{}],
"inventory": [{}],
"parts": {
"0" : { "model": "engineersdecor:slab/halfslab_s0_model" },
"1" : { "model": "engineersdecor:slab/halfslab_s1_model" },
"2" : { "model": "engineersdecor:slab/halfslab_s2_model" },
"3" : { "model": "engineersdecor:slab/halfslab_s3_model" },
"4" : { "model": "engineersdecor:slab/halfslab_s4_model" },
"5" : { "model": "engineersdecor:slab/halfslab_s5_model" },
"6" : { "model": "engineersdecor:slab/halfslab_s6_model" },
"7" : { "model": "engineersdecor:slab/halfslab_s7_model" },
"8" : { "model": "engineersdecor:slab/halfslab_s8_model" },
"9" : { "model": "engineersdecor:slab/halfslab_s9_model" },
"10": { "model": "engineersdecor:slab/halfslab_sa_model" },
"11": { "model": "engineersdecor:slab/halfslab_sb_model" },
"12": { "model": "engineersdecor:slab/halfslab_sc_model" },
"13": { "model": "engineersdecor:slab/halfslab_sd_model" },
"14": { "model": "engineersdecor:slab/halfslab_se_model" }
}
}
}

View file

@ -1,28 +0,0 @@
{
"forge_marker": 1,
"defaults": {
"model": "engineersdecor:slab/halfslab_s0_model",
"textures": { "all": "immersiveengineering:blocks/sheetmetal_aluminum" }
},
"variants": {
"normal": [{}],
"inventory": [{}],
"parts": {
"0" : { "model": "engineersdecor:slab/halfslab_s0_model" },
"1" : { "model": "engineersdecor:slab/halfslab_s1_model" },
"2" : { "model": "engineersdecor:slab/halfslab_s2_model" },
"3" : { "model": "engineersdecor:slab/halfslab_s3_model" },
"4" : { "model": "engineersdecor:slab/halfslab_s4_model" },
"5" : { "model": "engineersdecor:slab/halfslab_s5_model" },
"6" : { "model": "engineersdecor:slab/halfslab_s6_model" },
"7" : { "model": "engineersdecor:slab/halfslab_s7_model" },
"8" : { "model": "engineersdecor:slab/halfslab_s8_model" },
"9" : { "model": "engineersdecor:slab/halfslab_s9_model" },
"10": { "model": "engineersdecor:slab/halfslab_sa_model" },
"11": { "model": "engineersdecor:slab/halfslab_sb_model" },
"12": { "model": "engineersdecor:slab/halfslab_sc_model" },
"13": { "model": "engineersdecor:slab/halfslab_sd_model" },
"14": { "model": "engineersdecor:slab/halfslab_se_model" }
}
}
}

View file

@ -1,28 +0,0 @@
{
"forge_marker": 1,
"defaults": {
"model": "engineersdecor:slab/halfslab_s0_model",
"textures": { "all": "immersiveengineering:blocks/sheetmetal_copper" }
},
"variants": {
"normal": [{}],
"inventory": [{}],
"parts": {
"0" : { "model": "engineersdecor:slab/halfslab_s0_model" },
"1" : { "model": "engineersdecor:slab/halfslab_s1_model" },
"2" : { "model": "engineersdecor:slab/halfslab_s2_model" },
"3" : { "model": "engineersdecor:slab/halfslab_s3_model" },
"4" : { "model": "engineersdecor:slab/halfslab_s4_model" },
"5" : { "model": "engineersdecor:slab/halfslab_s5_model" },
"6" : { "model": "engineersdecor:slab/halfslab_s6_model" },
"7" : { "model": "engineersdecor:slab/halfslab_s7_model" },
"8" : { "model": "engineersdecor:slab/halfslab_s8_model" },
"9" : { "model": "engineersdecor:slab/halfslab_s9_model" },
"10": { "model": "engineersdecor:slab/halfslab_sa_model" },
"11": { "model": "engineersdecor:slab/halfslab_sb_model" },
"12": { "model": "engineersdecor:slab/halfslab_sc_model" },
"13": { "model": "engineersdecor:slab/halfslab_sd_model" },
"14": { "model": "engineersdecor:slab/halfslab_se_model" }
}
}
}

View file

@ -1,28 +0,0 @@
{
"forge_marker": 1,
"defaults": {
"model": "engineersdecor:slab/halfslab_s0_model",
"textures": { "all": "immersiveengineering:blocks/sheetmetal_gold" }
},
"variants": {
"normal": [{}],
"inventory": [{}],
"parts": {
"0" : { "model": "engineersdecor:slab/halfslab_s0_model" },
"1" : { "model": "engineersdecor:slab/halfslab_s1_model" },
"2" : { "model": "engineersdecor:slab/halfslab_s2_model" },
"3" : { "model": "engineersdecor:slab/halfslab_s3_model" },
"4" : { "model": "engineersdecor:slab/halfslab_s4_model" },
"5" : { "model": "engineersdecor:slab/halfslab_s5_model" },
"6" : { "model": "engineersdecor:slab/halfslab_s6_model" },
"7" : { "model": "engineersdecor:slab/halfslab_s7_model" },
"8" : { "model": "engineersdecor:slab/halfslab_s8_model" },
"9" : { "model": "engineersdecor:slab/halfslab_s9_model" },
"10": { "model": "engineersdecor:slab/halfslab_sa_model" },
"11": { "model": "engineersdecor:slab/halfslab_sb_model" },
"12": { "model": "engineersdecor:slab/halfslab_sc_model" },
"13": { "model": "engineersdecor:slab/halfslab_sd_model" },
"14": { "model": "engineersdecor:slab/halfslab_se_model" }
}
}
}

View file

@ -1,28 +0,0 @@
{
"forge_marker": 1,
"defaults": {
"model": "engineersdecor:slab/halfslab_s0_model",
"textures": { "all": "immersiveengineering:blocks/sheetmetal_iron" }
},
"variants": {
"normal": [{}],
"inventory": [{}],
"parts": {
"0" : { "model": "engineersdecor:slab/halfslab_s0_model" },
"1" : { "model": "engineersdecor:slab/halfslab_s1_model" },
"2" : { "model": "engineersdecor:slab/halfslab_s2_model" },
"3" : { "model": "engineersdecor:slab/halfslab_s3_model" },
"4" : { "model": "engineersdecor:slab/halfslab_s4_model" },
"5" : { "model": "engineersdecor:slab/halfslab_s5_model" },
"6" : { "model": "engineersdecor:slab/halfslab_s6_model" },
"7" : { "model": "engineersdecor:slab/halfslab_s7_model" },
"8" : { "model": "engineersdecor:slab/halfslab_s8_model" },
"9" : { "model": "engineersdecor:slab/halfslab_s9_model" },
"10": { "model": "engineersdecor:slab/halfslab_sa_model" },
"11": { "model": "engineersdecor:slab/halfslab_sb_model" },
"12": { "model": "engineersdecor:slab/halfslab_sc_model" },
"13": { "model": "engineersdecor:slab/halfslab_sd_model" },
"14": { "model": "engineersdecor:slab/halfslab_se_model" }
}
}
}

View file

@ -1,28 +0,0 @@
{
"forge_marker": 1,
"defaults": {
"model": "engineersdecor:slab/halfslab_s0_model",
"textures": { "all": "immersiveengineering:blocks/sheetmetal_steel" }
},
"variants": {
"normal": [{}],
"inventory": [{}],
"parts": {
"0" : { "model": "engineersdecor:slab/halfslab_s0_model" },
"1" : { "model": "engineersdecor:slab/halfslab_s1_model" },
"2" : { "model": "engineersdecor:slab/halfslab_s2_model" },
"3" : { "model": "engineersdecor:slab/halfslab_s3_model" },
"4" : { "model": "engineersdecor:slab/halfslab_s4_model" },
"5" : { "model": "engineersdecor:slab/halfslab_s5_model" },
"6" : { "model": "engineersdecor:slab/halfslab_s6_model" },
"7" : { "model": "engineersdecor:slab/halfslab_s7_model" },
"8" : { "model": "engineersdecor:slab/halfslab_s8_model" },
"9" : { "model": "engineersdecor:slab/halfslab_s9_model" },
"10": { "model": "engineersdecor:slab/halfslab_sa_model" },
"11": { "model": "engineersdecor:slab/halfslab_sb_model" },
"12": { "model": "engineersdecor:slab/halfslab_sc_model" },
"13": { "model": "engineersdecor:slab/halfslab_sd_model" },
"14": { "model": "engineersdecor:slab/halfslab_se_model" }
}
}
}

View file

@ -1,28 +0,0 @@
{
"forge_marker": 1,
"defaults": {
"model": "engineersdecor:slab/halfslab_s0_model",
"textures": { "all": "immersiveengineering:blocks/treated_wood" }
},
"variants": {
"normal": [{}],
"inventory": [{}],
"parts": {
"0" : { "model": "engineersdecor:slab/halfslab_s0_model" },
"1" : { "model": "engineersdecor:slab/halfslab_s1_model" },
"2" : { "model": "engineersdecor:slab/halfslab_s2_model" },
"3" : { "model": "engineersdecor:slab/halfslab_s3_model" },
"4" : { "model": "engineersdecor:slab/halfslab_s4_model" },
"5" : { "model": "engineersdecor:slab/halfslab_s5_model" },
"6" : { "model": "engineersdecor:slab/halfslab_s6_model" },
"7" : { "model": "engineersdecor:slab/halfslab_s7_model" },
"8" : { "model": "engineersdecor:slab/halfslab_s8_model" },
"9" : { "model": "engineersdecor:slab/halfslab_s9_model" },
"10": { "model": "engineersdecor:slab/halfslab_sa_model" },
"11": { "model": "engineersdecor:slab/halfslab_sb_model" },
"12": { "model": "engineersdecor:slab/halfslab_sc_model" },
"13": { "model": "engineersdecor:slab/halfslab_sd_model" },
"14": { "model": "engineersdecor:slab/halfslab_se_model" }
}
}
}

View file

@ -1,9 +0,0 @@
{
"forge_marker": 1,
"defaults": { "model": "engineersdecor:light/floor_edge_light_model" },
"variants": {
"normal": [{}],
"facing": { "north":{"y":0}, "south":{"y":180}, "west":{"y":270}, "east":{"y":90}, "up": {}, "down": {} },
"inventory": [{}]
}
}

View file

@ -1,9 +0,0 @@
{
"forge_marker": 1,
"defaults": { "model": "engineersdecor:light/inset_light_model" },
"variants": {
"normal": [{}],
"facing": { "north":{"y":0}, "south":{"y":180}, "west":{"y":270}, "east":{"y":90}, "up": {"x":-90}, "down": {"x":90} },
"inventory": [{}]
}
}

View file

@ -1,11 +0,0 @@
{
"forge_marker": 1,
"defaults": {
"model": "engineersdecor:misc/labeled_crate_model"
},
"variants": {
"normal": [{}],
"inventory": [{}],
"facing": { "north": {"y":0}, "south": {"y":180}, "west": {"y":-90}, "east": {"y":90}, "up":{}, "down":{} }
}
}

View file

@ -1,9 +0,0 @@
{
"forge_marker": 1,
"defaults": { "model": "engineersdecor:ladder/metal_rung_ladder_model" },
"variants": {
"normal": [{}],
"facing": { "north":{"y":0}, "south":{"y":180}, "west":{"y":270}, "east":{"y":90}, "up": {"x":0}, "down": {"x":0} },
"inventory": [{}]
}
}

View file

@ -1,9 +0,0 @@
{
"forge_marker": 1,
"defaults": { "model": "engineersdecor:ladder/metal_rung_steps_model" },
"variants": {
"normal": [{}],
"facing": { "north":{"y":0}, "south":{"y":180}, "west":{"y":270}, "east":{"y":90}, "up": {"x":0}, "down": {"x":0} },
"inventory": [{}]
}
}

View file

@ -1,19 +0,0 @@
{
"forge_marker": 1,
"defaults": {
"model": "engineersdecor:glass/panzerglass_block_model",
"textures": { "all": "engineersdecor:blocks/glass/panzerglass_block_texture0" }
},
"variants": {
"normal": [
{ "textures": { "all": "engineersdecor:blocks/glass/panzerglass_block_texture0" } },
{ "textures": { "all": "engineersdecor:blocks/glass/panzerglass_block_texture1" } },
{ "textures": { "all": "engineersdecor:blocks/glass/panzerglass_block_texture2" } },
{ "textures": { "all": "engineersdecor:blocks/glass/panzerglass_block_texture3" } }
],
"inventory": {
"model": "engineersdecor:glass/panzerglass_block_model",
"textures": { "all": "engineersdecor:blocks/glass/panzerglass_block_texture_inventory" }
}
}
}

View file

@ -1,26 +0,0 @@
{
"forge_marker": 1,
"defaults": {
"model": "engineersdecor:slab/slab_s0_model",
"textures": { "all": "engineersdecor:blocks/glass/panzerglass_block_texture0" }
},
"variants": {
"normal": [{}],
"inventory": [{}],
"parts": {
"0" : { "model": "engineersdecor:slab/slab_s0_model" },
"1" : { "model": "engineersdecor:slab/slab_s1_model" },
"2" : { "model": "engineersdecor:slab/slab_s2_model" }
},
"tvariant": {
"0":{"textures":{"all": "engineersdecor:blocks/glass/panzerglass_block_texture0"}},
"1":{"textures":{"all": "engineersdecor:blocks/glass/panzerglass_block_texture1"}},
"2":{"textures":{"all": "engineersdecor:blocks/glass/panzerglass_block_texture2"}},
"3":{"textures":{"all": "engineersdecor:blocks/glass/panzerglass_block_texture3"}},
"4":{"textures":{"all": "engineersdecor:blocks/glass/panzerglass_block_texture0"}},
"5":{"textures":{"all": "engineersdecor:blocks/glass/panzerglass_block_texture1"}},
"6":{"textures":{"all": "engineersdecor:blocks/glass/panzerglass_block_texture2"}},
"7":{"textures":{"all": "engineersdecor:blocks/glass/panzerglass_block_texture3"}}
}
}
}

View file

@ -1,11 +0,0 @@
{
"forge_marker": 1,
"defaults": {
"model": "engineersdecor:pipe/passive_fluid_accumulator_model"
},
"variants": {
"normal": [{}],
"inventory": [{}],
"facing": { "north":{"y":0}, "south":{"y":180}, "west":{"y":270}, "east":{"y":90}, "up": {"x":-90}, "down": {"x":90} }
}
}

View file

@ -1,20 +0,0 @@
{
"forge_marker": 1,
"defaults": {
"model": "engineersdecor:std/decor_full_block_model",
"textures": { "all": "engineersdecor:blocks/concrete/rebar_concrete_texture0" }
},
"variants": {
"normal": [
{ "textures": { "all": "engineersdecor:blocks/concrete/rebar_concrete_texture0" } },
{ "textures": { "all": "engineersdecor:blocks/concrete/rebar_concrete_texture1" } },
{ "textures": { "all": "engineersdecor:blocks/concrete/rebar_concrete_texture2" } },
{ "textures": { "all": "engineersdecor:blocks/concrete/rebar_concrete_texture3" } },
{ "textures": { "all": "engineersdecor:blocks/concrete/rebar_concrete_texture4" } },
{ "textures": { "all": "engineersdecor:blocks/concrete/rebar_concrete_texture5" } },
{ "textures": { "all": "engineersdecor:blocks/concrete/rebar_concrete_texture6" } },
{ "textures": { "all": "engineersdecor:blocks/concrete/rebar_concrete_texture7" } }
],
"inventory": [{}]
}
}

View file

@ -1,26 +0,0 @@
{
"forge_marker": 1,
"defaults": {
"model": "engineersdecor:slab/slab_s0_model",
"textures": { "all": "engineersdecor:blocks/concrete/rebar_concrete_texture0" }
},
"variants": {
"normal": [{}],
"inventory": [{}],
"parts": {
"0" : { "model": "engineersdecor:slab/slab_s0_model" },
"1" : { "model": "engineersdecor:slab/slab_s1_model" },
"2" : { "model": "engineersdecor:slab/slab_s2_model" }
},
"tvariant": {
"0":{"textures":{"all": "engineersdecor:blocks/concrete/rebar_concrete_texture0"}},
"1":{"textures":{"all": "engineersdecor:blocks/concrete/rebar_concrete_texture1"}},
"2":{"textures":{"all": "engineersdecor:blocks/concrete/rebar_concrete_texture2"}},
"3":{"textures":{"all": "engineersdecor:blocks/concrete/rebar_concrete_texture3"}},
"4":{"textures":{"all": "engineersdecor:blocks/concrete/rebar_concrete_texture4"}},
"5":{"textures":{"all": "engineersdecor:blocks/concrete/rebar_concrete_texture5"}},
"6":{"textures":{"all": "engineersdecor:blocks/concrete/rebar_concrete_texture6"}},
"7":{"textures":{"all": "engineersdecor:blocks/concrete/rebar_concrete_texture7"}}
}
}
}

View file

@ -1,56 +0,0 @@
{
"forge_marker": 1,
"defaults": {
"model": "engineersdecor:stairs/decor_straight_stairs_model",
"textures": {
"particle": "engineersdecor:blocks/concrete/rebar_concrete_texture0",
"bottom": "engineersdecor:blocks/concrete/rebar_concrete_texture0",
"top": "engineersdecor:blocks/concrete/rebar_concrete_texture0",
"side": "engineersdecor:blocks/concrete/rebar_concrete_texture0"
}
},
"variants": {
"normal": [{}],
"inventory": [{}],
"facing=east,half=bottom,shape=straight": { "model": "engineersdecor:stairs/decor_straight_stairs_model" },
"facing=west,half=bottom,shape=straight": { "model": "engineersdecor:stairs/decor_straight_stairs_model", "y": 180, "uvlock": true },
"facing=south,half=bottom,shape=straight": { "model": "engineersdecor:stairs/decor_straight_stairs_model", "y": 90, "uvlock": true },
"facing=north,half=bottom,shape=straight": { "model": "engineersdecor:stairs/decor_straight_stairs_model", "y": 270, "uvlock": true },
"facing=east,half=bottom,shape=outer_right": { "model": "engineersdecor:stairs/decor_outer_stairs_model" },
"facing=west,half=bottom,shape=outer_right": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "y": 180, "uvlock": true },
"facing=south,half=bottom,shape=outer_right": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "y": 90, "uvlock": true },
"facing=north,half=bottom,shape=outer_right": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "y": 270, "uvlock": true },
"facing=east,half=bottom,shape=outer_left": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "y": 270, "uvlock": true },
"facing=west,half=bottom,shape=outer_left": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "y": 90, "uvlock": true },
"facing=south,half=bottom,shape=outer_left": { "model": "engineersdecor:stairs/decor_outer_stairs_model" },
"facing=north,half=bottom,shape=outer_left": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "y": 180, "uvlock": true },
"facing=east,half=bottom,shape=inner_right": { "model": "engineersdecor:stairs/decor_inner_stairs_model" },
"facing=west,half=bottom,shape=inner_right": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "y": 180, "uvlock": true },
"facing=south,half=bottom,shape=inner_right": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "y": 90, "uvlock": true },
"facing=north,half=bottom,shape=inner_right": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "y": 270, "uvlock": true },
"facing=east,half=bottom,shape=inner_left": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "y": 270, "uvlock": true },
"facing=west,half=bottom,shape=inner_left": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "y": 90, "uvlock": true },
"facing=south,half=bottom,shape=inner_left": { "model": "engineersdecor:stairs/decor_inner_stairs_model" },
"facing=north,half=bottom,shape=inner_left": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "y": 180, "uvlock": true },
"facing=east,half=top,shape=straight": { "model": "engineersdecor:stairs/decor_straight_stairs_model", "x": 180, "uvlock": true },
"facing=west,half=top,shape=straight": { "model": "engineersdecor:stairs/decor_straight_stairs_model", "x": 180, "y": 180, "uvlock": true },
"facing=south,half=top,shape=straight": { "model": "engineersdecor:stairs/decor_straight_stairs_model", "x": 180, "y": 90, "uvlock": true },
"facing=north,half=top,shape=straight": { "model": "engineersdecor:stairs/decor_straight_stairs_model", "x": 180, "y": 270, "uvlock": true },
"facing=east,half=top,shape=outer_right": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "x": 180, "y": 90, "uvlock": true },
"facing=west,half=top,shape=outer_right": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "x": 180, "y": 270, "uvlock": true },
"facing=south,half=top,shape=outer_right": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "x": 180, "y": 180, "uvlock": true },
"facing=north,half=top,shape=outer_right": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "x": 180, "uvlock": true },
"facing=east,half=top,shape=outer_left": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "x": 180, "uvlock": true },
"facing=west,half=top,shape=outer_left": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "x": 180, "y": 180, "uvlock": true },
"facing=south,half=top,shape=outer_left": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "x": 180, "y": 90, "uvlock": true },
"facing=north,half=top,shape=outer_left": { "model": "engineersdecor:stairs/decor_outer_stairs_model", "x": 180, "y": 270, "uvlock": true },
"facing=east,half=top,shape=inner_right": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "x": 180, "y": 90, "uvlock": true },
"facing=west,half=top,shape=inner_right": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "x": 180, "y": 270, "uvlock": true },
"facing=south,half=top,shape=inner_right": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "x": 180, "y": 180, "uvlock": true },
"facing=north,half=top,shape=inner_right": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "x": 180, "uvlock": true },
"facing=east,half=top,shape=inner_left": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "x": 180, "uvlock": true },
"facing=west,half=top,shape=inner_left": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "x": 180, "y": 180, "uvlock": true },
"facing=south,half=top,shape=inner_left": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "x": 180, "y": 90, "uvlock": true },
"facing=north,half=top,shape=inner_left": { "model": "engineersdecor:stairs/decor_inner_stairs_model", "x": 180, "y": 270, "uvlock": true }
}
}

View file

@ -1,20 +0,0 @@
{
"forge_marker": 1,
"defaults": {
"model": "engineersdecor:std/decor_full_block_model",
"textures": { "all": "engineersdecor:blocks/concrete/rebar_concrete_tile_texture0" }
},
"variants": {
"normal": [
{ "textures": { "all": "engineersdecor:blocks/concrete/rebar_concrete_tile_texture0" } },
{ "textures": { "all": "engineersdecor:blocks/concrete/rebar_concrete_tile_texture1" } },
{ "textures": { "all": "engineersdecor:blocks/concrete/rebar_concrete_tile_texture2" } },
{ "textures": { "all": "engineersdecor:blocks/concrete/rebar_concrete_tile_texture3" } },
{ "textures": { "all": "engineersdecor:blocks/concrete/rebar_concrete_tile_texture4" } },
{ "textures": { "all": "engineersdecor:blocks/concrete/rebar_concrete_tile_texture5" } },
{ "textures": { "all": "engineersdecor:blocks/concrete/rebar_concrete_tile_texture6" } },
{ "textures": { "all": "engineersdecor:blocks/concrete/rebar_concrete_tile_texture7" } }
],
"inventory": [{}]
}
}

Some files were not shown because too many files have changed in this diff Show more