diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a2db5a4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,32 @@ +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 diff --git a/Makefile b/Makefile index 4d60e9f..4594403 100644 --- a/Makefile +++ b/Makefile @@ -96,3 +96,10 @@ dist: sanatize dist-check clean-all mod @mkdir -p dist @cp build/libs/$(MOD_JAR_PREFIX)* dist/ @djs scripts/task-dist.js + +# For reviewers: I am using a local repository for experimental changes, +# this target copies the local working tree to the location of the +# repository that you cloned. +sync-main-repo: sanatize + @echo "Synchronising to github repository working tree ..." + @djs scripts/sync-main-repo.js diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..8d52f57 --- /dev/null +++ b/build.gradle @@ -0,0 +1,76 @@ +// @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' +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() + 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" +} + +dependencies { +} + +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 diff --git a/credits.md b/credits.md new file mode 100644 index 0000000..14493f4 --- /dev/null +++ b/credits.md @@ -0,0 +1,13 @@ + +As addon for Immersive Engineering, this mod is heavily inspired +by the designs and the code base of IE, and I would like to give +special credits to the Software Engineers of Immersive Engineering +(BluSunrize, malte0811, et al). Please see: + + - https://github.com/BluSunrize/ImmersiveEngineering/ + - https://github.com/BluSunrize/ImmersiveEngineering/graphs/contributors + +Mod components derived/inspired by IE: + + - Style color scheme of treated wood/steel/concrete to match IE color scheme. + - Recipe _constants.json file (for using IE items as ingredients) diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..af0c148 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,14 @@ +# @file gradle.properties +org.gradle.daemon=false +org.gradle.jvmargs=-Xmx8G +version_minecraft=1.12.2 +version_forge=14.23.5.2768 +version_engineersdecor=1.0.0 +# +# jar signing data loaded from signing.properties in the project root. +# +#signing.keystore_file= +#signing.keystore_alias= +#signing.keystore_pass= +#signing.keystore_keypass= +#fingerprint_sha1.fp_sha1= diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..d3b8398 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..bac49df --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#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 diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..27309d9 --- /dev/null +++ b/gradlew @@ -0,0 +1,164 @@ +#!/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 "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..f6d5974 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +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 diff --git a/license b/license index 37ec652..e86a396 100644 --- a/license +++ b/license @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2018-2018 Stefan Wilhelm (wile) +Copyright (c) 2018-2019 Stefan Wilhelm (wile) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/meta/update.json b/meta/update.json new file mode 100644 index 0000000..3e4df43 --- /dev/null +++ b/meta/update.json @@ -0,0 +1,14 @@ +{ + "homepage": "https://www.curseforge.com/minecraft/mc-mods/engineers-decor/", + "1.12.2": { + "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.0.0", + "1.12.2-latest": "1.0.0" + } +} \ No newline at end of file diff --git a/readme.md b/readme.md index 5096bf6..2c045f4 100644 --- a/readme.md +++ b/readme.md @@ -26,6 +26,14 @@ no tile entities or user interactions are used. Current feature set: explosion resistance than the vanilla brick wall. Also available as stairs, also with reverse recipe. +- Rebar (steel) reinforced concrete: Expensive but creeper-proof. Crafted 3x3 from + four concrete blocks and five steel rods. Texture design oriented at the IE concrete, + slightly darker, eight (position dependent) random texture variations with rust + traces. Also creaftable in form of *stairs* and *walls*. + +- Concrete wall: Solid concrete wall (not the vanilla wall design), crafted 3x3 + from six IE concrete blocks (normal wall recipe). + - *Treated wood ladder*: Crafted 3x3 with the known ladder pattern, items are treated wood sticks. @@ -65,6 +73,18 @@ More to come slowly but steadily. ---- ## Revision history + ------------------------------------------------------------------- + - 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. diff --git a/scripts/sanatize-dist-check.js b/scripts/sanatize-dist-check.js new file mode 100644 index 0000000..bdb67ef --- /dev/null +++ b/scripts/sanatize-dist-check.js @@ -0,0 +1,40 @@ +#!/usr/bin/djs +if((!fs.chdir(fs.dirname(fs.realpath(sys.script))+"/..")) || (!fs.isdir(".git"))) throw new Error("Failed to switch to mod source directory."); + +const uncommitted_changes = sys.shell("git status -s").trim(); + +const gittags = sys.shell('git log -1 --format="%D"') + .replace(/[\s]/g,"").split(",") + .filter(function(s){ return s.indexOf("tag:")==0;}) + .map(function(s){ return s.replace(/^tag:/,"");}); + +const version_engineersdecor = fs.readfile("gradle.properties", function(line){ + if(line.trim().indexOf("version_engineersdecor")!=0) return false; + return line.replace(/^.*?=/,"").trim() +}).trim(); + +const git_remote = sys.shell("git remote -v").trim(); +const git_branch = sys.shell("git rev-parse --abbrev-ref HEAD").trim(); +const git_diff = sys.shell("git diff").trim(); +var fails = []; + +if(version_engineersdecor=="") fails.push("Could not determine 'version_engineersdecor' from gradle properties."); +if(!gittags.length) fails.push("Version not tagged."); +if(!gittags.filter(function(s){return s.indexOf(version_engineersdecor.replace(/[-]/g,""))>=0}).length) fails.push("No tag version not found matching the gradle properties version."); +if(git_remote.replace(/[\s]/g,"").indexOf("git@github.com:stfwi/engineers-decor.git(push)") < 0) fails.push("Not the reference repository."); +if((git_branch != "develop") && (git_branch != "master")) { + fails.push("No valid branch for dist. (branch:'"+git_branch+"')"); +} else if((git_branch == "develop") && (version_engineersdecor.replace(/[^\w\.-]/g,"")=="")) { + fails.push("Cannot make release dist on develop branch."); +} else if((git_branch == "master") && (version_engineersdecor.replace(/[^\w\.-]/g,"")!="")) { + fails.push("Cannot make beta dist on master branch."); +} +if(git_diff !== "") fails.push("Not everything committed to the GIT repository."); +if((!fs.isfile("signing.jks")) || (!fs.isfile("signing.properties"))) fails.push("Jar signing files missing."); + +if(fails.length>0) { + for(var i in fails) fails[i] = " - " + fails[i]; + alert("Dist check failed"); + alert(fails.join("\n")+"\n"); + exit(1); +} diff --git a/scripts/sanatize-sync-languages.js b/scripts/sanatize-sync-languages.js new file mode 100644 index 0000000..3390036 --- /dev/null +++ b/scripts/sanatize-sync-languages.js @@ -0,0 +1,122 @@ +#!/usr/bin/djs +if((!fs.chdir(fs.dirname(fs.realpath(sys.script))+"/..")) || (!fs.isdir("src"))) throw new Error("Failed to switch to mod source directory."); + +function load() { + var lang_data = {}; + fs.find("./src/main/resources/assets/engineersdecor/lang", '*.lang', function(f){ + var lang_code = fs.basename(f).replace(/\..*$/,"").trim().toLowerCase(); + var lines = fs.readfile(f).trim().split("\n"); + var was_eol_escape = false; + for(var i in lines) { + if(was_eol_escape) { + var k=0; + for(k=i-1; k>=0; --k) { + if(lines[k] != null) { + lines[k] += "\n" + lines[i]; + break; + } + } + was_eol_escape = lines[i].match(/[^\\][\\]$/) != null; + lines[i] = null; + } else { + lines[i] = lines[i].trim(); + was_eol_escape = lines[i].match(/[^\\][\\]$/) != null; + } + } + lang_data[lang_code] = lines.filter(function(l){return (l!==null);}); + return false; + }); + return lang_data; +} + +function reference_content(lang_data, reflang_code) { + var lang_lines = []; + for(var i in lang_data[reflang_code]) { + var txt = lang_data[reflang_code][i].trim(); + if((txt.search(/^#/)>=0) || (txt.search("=")<0)) { lang_lines.push(txt); continue; }; // comment "#" or empty line in the ref lang file + var kv = txt.split("=", 2); + var key = kv[0].trim(); + var val = kv[1].trim(); + var o = {key:key, tr:{}}; + o.tr[reflang_code] = val; + lang_lines.push(o); + } + delete lang_data[reflang_code]; + return lang_lines; +} + +function add_language(lang_lines, lang_name, lang_data) { + const find_line = function(lines, key) { + for(var i in lines) { + if((typeof(lines[i]) !== "object")) continue; + if(lines[i].key.toLowerCase()==key.toLowerCase()) return i; + } + return -1; + }; + for(var i in lang_data) { + var txt = lang_data[i].trim(); + if(txt.search(/^#/)>=0) continue; + if(txt.search("=")<0) continue; + var kv = txt.split("=", 2); + var key = kv[0].trim(); + var val = kv[1].trim(); + var line_i = find_line(lang_lines, key); + if(line_i >= 0) { + lang_data[i] = undefined; + lang_lines[line_i].tr[lang_name] = val; + } + } + return lang_data; +} + +function complete_lang_lines(lang_lines, lang_names, reflang_code) { + var lang_outputs = {}; + for(var i in lang_names) lang_outputs[lang_names[i]] = []; + for(var i_line in lang_lines) { + var entry = lang_lines[i_line]; + if(typeof(entry) !== "object") { + for(var i in lang_names) lang_outputs[lang_names[i]].push(entry); + } else { + for(var i in lang_names) { + var name = lang_names[i]; + if(entry.tr[name] !== undefined) { + lang_outputs[name].push(entry.key + "=" + entry.tr[name]); + } else { + var added = entry.key + "=" + entry.tr[reflang_code]; + if((entry.key.search(/\.tip$/)>0) || (entry.key.search(/\.help$/)>0)) added = "#" + added; + lang_outputs[name].push(added); + if(added.search(/^#/)<0) print("[warn] Lang: Added default language for missing entry in " + name + ": '" + added + "'"); + } + } + } + } + return lang_outputs; +} + +const reflang_code = "en_us"; +var lang_data = load(); +var lang_names = Object.keys(lang_data); +var lang_lines = reference_content(lang_data, reflang_code); +for(var lang_name in lang_data) { + lang_data[lang_name] = add_language(lang_lines, lang_name, lang_data[lang_name]); + lang_data[lang_name] = lang_data[lang_name].filter(function(l){ return !!l; }); + if(lang_data[lang_name].length == 0) delete lang_data[lang_name]; +} +var output_data = complete_lang_lines(lang_lines, lang_names, reflang_code); +for(var i in output_data) output_data[i] = output_data[i].join("\n") + "\n\n"; + +// Remaining lines in lang files (not in the reference lang file) +for(var lang_name in lang_data) { + for(var i in lang_data[lang_name]) { + if(lang_data[lang_name][i].search(/^#/)<0) { + var added = "# " + lang_data[lang_name][i].replace(/^[#\s]+/,""); + output_data[lang_name] += added + "\n"; + print("[warn] Lang: Commented out unknown key in " + lang_name + ": '" + added + "'"); + } + } +} +for(var name in output_data) output_data[name] = output_data[name].trim() + "\n"; + +for(var name in output_data) { + fs.writefile("./src/main/resources/assets/engineersdecor/lang/" + name + ".lang", output_data[name]); +} diff --git a/scripts/sanatize-tabs-to-spaces.js b/scripts/sanatize-tabs-to-spaces.js new file mode 100644 index 0000000..1bb65a8 --- /dev/null +++ b/scripts/sanatize-tabs-to-spaces.js @@ -0,0 +1,25 @@ +#!/usr/bin/djs +if((!fs.chdir(fs.dirname(fs.realpath(sys.script))+"/..")) || (!fs.isdir("src"))) throw new Error("Failed to switch to mod source directory."); + +var file_list = (function() { + var ls = []; + const ext = ['java','lang']; + for(var i in ext) ls = ls.concat(fs.find("./src", '*.'+ext[i])); + for(var i in ls) ls[i] = ls[i].replace(/\\/g,"/"); + ls.sort(); + ls.push("readme.md"); + return ls; +})(); + +for(var file_i in file_list) { + var file = file_list[file_i]; + var txt = fs.readfile(file); + if(txt===undefined) throw new Error("Failed to read '" + file + "'"); + const txt_length = txt.length; + txt = txt.replace(/[\t]/g," "); + const n = txt.length - txt_length; + if(n > 0) { + print("File '" + file + "': Changed " + n + " tabs to 2 spaces." ); + fs.writefile(file, txt); + } +} diff --git a/scripts/sanatize-trailing-whitespaces.js b/scripts/sanatize-trailing-whitespaces.js new file mode 100644 index 0000000..ee683d8 --- /dev/null +++ b/scripts/sanatize-trailing-whitespaces.js @@ -0,0 +1,25 @@ +#!/usr/bin/djs +if((!fs.chdir(fs.dirname(fs.realpath(sys.script))+"/..")) || (!fs.isdir("src"))) throw new Error("Failed to switch to mod source directory."); + +var file_list = (function() { + var ls = []; + const ext = ['java','json','lang']; + for(var i in ext) ls = ls.concat(fs.find("./src", '*.'+ext[i])); + for(var i in ls) ls[i] = ls[i].replace(/\\/g,"/"); + ls.sort(); + ls.push("readme.md"); + return ls; +})(); + +for(var file_i in file_list) { + var file = file_list[file_i]; + var txt = fs.readfile(file); + if(txt===undefined) throw new Error("Failed to read '" + file + "'"); + const txt_length = txt.length; + txt = txt.replace(/[\r\t ]+[\n]/g,"\n"); + const n = txt_length - txt.length; + if(n > 0) { + print("File '" + file + "': Fixed " + n + " lines with trailing whitespaces." ); + fs.writefile(file, txt); + } +} diff --git a/scripts/sanatize-version-check.js b/scripts/sanatize-version-check.js new file mode 100644 index 0000000..975a02f --- /dev/null +++ b/scripts/sanatize-version-check.js @@ -0,0 +1,42 @@ +#!/usr/bin/djs +"use strict"; + +if((!fs.chdir(fs.dirname(fs.realpath(sys.script))+"/..")) || (!fs.isdir("src"))) throw new Error("Failed to switch to mod base directory."); + +var version_minecraft=""; +var version_forge=""; +var version_engineersdecor=""; + +fs.readfile("gradle.properties", function(line){ + if(line.search(/^[\s]*version_minecraft[\s]*=/i) >= 0) { + version_minecraft = line.replace(/^[^=]+=/,"").trim(); + } else if(line.search(/^[\s]*version_forge[\s]*=/i) >= 0) { + version_forge = line.replace(/^[^=]+=/,"").trim(); + } else if(line.search(/^[\s]*version_engineersdecor[\s]*=/i) >= 0) { + version_engineersdecor = line.replace(/^[^=]+=/,"").trim(); + } + return false; +}) + +const combined_version = version_minecraft + "-" + version_engineersdecor; + +var readme_version_found = fs.readfile("readme.md", function(line){ + var m = line.match(/^[\s]+-[\s]+v([\d]+[\.][\d]+[\.][\d]+[-][abrc][\d]+)/i); + if((!m) || (!m.length) || (m.length < 2)) { + m = line.match(/^[\s]+-[\s]+v([\d]+[\.][\d]+[\.][\d]+)/i); + if((!m) || (!m.length) || (m.length < 2)) return false; + } + return m[1]==version_engineersdecor; +}); + +var ok=true; +if(!readme_version_found) { + alert("Version 'v" + version_engineersdecor + "' not found in the readme changelog."); + ok = false; +} +if(!ok) { + alert("Version data:"); + alert(" - combined_version : '" + combined_version + "'"); + alert(" - version_forge : '" + version_forge + "'"); + exit(1); +} diff --git a/scripts/sync-main-repo.js b/scripts/sync-main-repo.js new file mode 100644 index 0000000..5144f5d --- /dev/null +++ b/scripts/sync-main-repo.js @@ -0,0 +1,16 @@ +#!/usr/bin/djs +"use strict"; +const main_repo_local = fs.realpath("../engineersdecor-github"); +if((!fs.chdir(fs.dirname(fs.realpath(sys.script))+"/..")) || (!fs.isdir(".git"))) throw new Error("Failed to switch to mod source directory."); +const test_repo_local = fs.cwd(); +if(main_repo_local == "") throw new Error("Main repository (real) path not found."); +if(fs.realpath(main_repo_local) == fs.realpath(test_repo_local)) throw new Error("This is already the main repository"); +if((!fs.chdir(main_repo_local)) || (!fs.isdir(".git"))) throw new Error("Failed to switch to main repository directory."); +if(fs.cwd().search("-github") < 0) throw new Error("Main repository is missing the '*-github' tag in the path name."); +sys.shell("rm -rf build documentation gradle meta scripts src") +sys.shell("rm -f .gitignore build.gradle gradle.properties gradlew gradlew.bat license Makefile readme.md") +if((!fs.chdir(test_repo_local)) || (!fs.isdir(".git"))) throw new Error("Failed to switch to local dev directory."); +sys.shell("cp -r documentation gradle meta scripts src " + main_repo_local + "/") +sys.shell("cp .gitignore build.gradle gradle.properties gradlew gradlew.bat license Makefile readme.md " + main_repo_local + "/") +if((!fs.chdir(main_repo_local)) || (!fs.isdir(".git"))) throw new Error("Failed to switch to main repository directory."); +print(sys.shell("git status -s")) diff --git a/scripts/task-dist.js b/scripts/task-dist.js new file mode 100644 index 0000000..6af7d72 --- /dev/null +++ b/scripts/task-dist.js @@ -0,0 +1,33 @@ +#!/usr/bin/djs +"use strict"; +if((!fs.chdir(fs.dirname(fs.realpath(sys.script))+"/..")) || (!fs.isdir(".git"))) throw new Error("Failed to switch to mod source directory."); + +function readme_history(file_path) { + var readme = fs.readfile(file_path); + if(!readme) throw new Error("Failed to load readme.md"); + readme = readme.split(/[\r]?[\n]/); + while((readme.length > 0) && readme[0].search(/^## Revision history/i)<0) readme.shift(); + while((readme.length > 0) && readme[0].trim()=="") readme.shift(); + // revision history section + if(!readme.length) throw new Error("Revision history section not found in readme"); + readme.shift(); + var end_of_history = readme.length; + for(var i=0; i= 0) { end_of_history=i; break; } + if(end_of_history >= readme.length) throw new Error("Could not find the end-of-history header marker."); + // remove empty lines, splitters + while(readme.length >= end_of_history) readme.pop(); + while((readme.length >0) && (readme[readme.length-1].replace(/[\s-]/g,"")=="")) readme.pop(); + + const min_indent = readme + .map(function(s){return s.search(/[^\s]/)}) + .filter(function(e){return e>=0}) + .reduce(function(acc,e){return (e 1) { + for(var i in readme) { readme[i] = readme[i].substr(min_indent-2); } + } + return readme.join("\n"); +} + +const html = "
\n" + (readme_history("readme.md").replace(/&/g, "&").replace(/>/g, ">").replace(/";
+fs.writefile("dist/revision-history.html", html);
diff --git a/scripts/task-update-json.js b/scripts/task-update-json.js
new file mode 100644
index 0000000..9923852
--- /dev/null
+++ b/scripts/task-update-json.js
@@ -0,0 +1,65 @@
+#!/usr/bin/djs
+"use strict";
+const root_dir = fs.realpath(fs.dirname(sys.script)+"/..");
+
+function read_history() {
+  var readme = fs.readfile(root_dir + "/readme.md");
+  if(!readme) throw new Error("Failed to load readme.md");
+  readme = readme.split(/[\r]?[\n]/);
+  while((readme.length > 0) && readme[0].search(/^## Revision history/i)<0) readme.shift();
+  // revision history section
+  if(!readme.length) throw new Error("Revision history section not found in readme");
+  readme.shift();
+  var end_of_history = readme.length;
+  for(var i=0; i= 0) { end_of_history=i; break; }
+  if(end_of_history >= readme.length) throw new Error("Could not find the end-of-history header marker.");
+  // remove empty lines, splitters
+  while(readme.length >= end_of_history) readme.pop();
+  for(var i in readme) readme[i] = readme[i].replace(/[\s]+$/g,"").replace(/[\t]/g,"  ");
+  readme = readme.filter(function(a){return a.replace(/[\s-]+/g,"")!="";});
+  // condense multilines to single line entries for each fix or feature. ([A] ... [M] ...)
+  for(var i=readme.length-1; i>0; --i) {
+    var line = readme[i].replace(/^\s+/,"");
+    if(line.search(/^[\[\-]/) < 0) {
+      readme[i-1] += " " + line;
+      readme[i] = "";
+    }
+  }
+  readme = readme.filter(function(a){return a!="";});
+  // Condense log entries sepatated with newlines to one line for each version
+  for(var i=readme.length-1; i>0; --i) {
+    var line = readme[i].replace(/^\s+/,"");
+    if(line.search(/^-/) < 0) {
+      readme[i-1] += "\n" + line;
+      readme[i] = "";
+    }
+  }
+  readme = readme.filter(function(a){return a!="";});
+  // Separate versions.
+  var history = {};
+  for(var i in readme) {
+    var line = readme[i].replace(/^[\sv-]+/g,"").trim();
+    var ver = line.substr(0, line.search(" ")).trim().toLowerCase();
+    var txt = line.substr(line.search(" ")).trim();
+    if(history[ver] !== undefined) throw new Error("Double definition of version '" + ver + "' in the readme revision history.");
+    history[ver] = txt;
+  }
+  return history;
+}
+
+var history = read_history();
+var latest_release = "";
+var latest_beta = "";
+for(var ver in history) { latest_beta=ver; break; }
+for(var ver in history) if(ver.search(/(rc|b|a)/) < 0) { latest_release=ver; break; }
+
+var update_json = {
+  homepage: "https://www.curseforge.com/minecraft/mc-mods/engineers-decor/",
+  "1.12.2": history,
+  promos: {
+    "1.12.2-recommended": latest_release,
+    "1.12.2-latest": latest_beta,
+  }
+}
+
+fs.writefile(root_dir + "/meta/update.json", JSON.stringify(update_json, null, 2));
diff --git a/src/main/java/wile/engineersdecor/ModEngineersDecor.java b/src/main/java/wile/engineersdecor/ModEngineersDecor.java
new file mode 100644
index 0000000..45b0dee
--- /dev/null
+++ b/src/main/java/wile/engineersdecor/ModEngineersDecor.java
@@ -0,0 +1,108 @@
+/*
+ * @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.ModConfig;
+import wile.engineersdecor.blocks.ModBlocks;
+import net.minecraftforge.client.event.ModelRegistryEvent;
+import net.minecraftforge.fml.common.Mod;
+import net.minecraftforge.fml.common.SidedProxy;
+import net.minecraftforge.fml.relauncher.SideOnly;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+import net.minecraftforge.event.RegistryEvent;
+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.minecraft.creativetab.CreativeTabs;
+import net.minecraft.item.ItemStack;
+import net.minecraft.block.Block;
+import net.minecraft.item.Item;
+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/engineersdecor/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;
+
+  @SidedProxy(clientSide = "wile.engineersdecor.detail.ClientProxy", serverSide = "wile.engineersdecor.detail.ServerProxy")
+  public static IProxy proxy;
+
+  public interface IProxy
+  {
+    default void preInit(FMLPreInitializationEvent e) {}
+    default void init(FMLInitializationEvent e) {}
+    default void postInit(FMLPostInitializationEvent e) {}
+  }
+
+  @Mod.EventHandler
+  public void preInit(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);
+  }
+
+  @Mod.EventHandler
+  public void init(FMLInitializationEvent event)
+  { proxy.init(event); }
+
+  @Mod.EventHandler
+  public void postInit(FMLPostInitializationEvent event)
+  { ModConfig.onPostInit(event); proxy.postInit(event); }
+
+  @Mod.EventBusSubscriber
+  public static final class RegistrationSubscriptions
+  {
+    @SubscribeEvent
+    public static void registerBlocks(RegistryEvent.Register event)
+    { ModBlocks.registerBlocks(event); }
+
+    @SubscribeEvent
+    public static void registerItems(RegistryEvent.Register event)
+    { ModBlocks.registerItemBlocks(event); }
+
+    @SideOnly(Side.CLIENT)
+    @SubscribeEvent
+    public static void registerModels(ModelRegistryEvent event)
+    { ModBlocks.initModels(); }
+  }
+
+  public static final CreativeTabs CREATIVE_TAB_ENGINEERSDECOR = (new CreativeTabs("tabengineersdecor") {
+    @Override
+    @SideOnly(Side.CLIENT)
+    public @Nonnull ItemStack createIcon()
+    { return new ItemStack(ModBlocks.TREATED_WOOD_LADDER); }
+  });
+
+}
diff --git a/src/main/java/wile/engineersdecor/blocks/BlockDecor.java b/src/main/java/wile/engineersdecor/blocks/BlockDecor.java
new file mode 100644
index 0000000..ce3d794
--- /dev/null
+++ b/src/main/java/wile/engineersdecor/blocks/BlockDecor.java
@@ -0,0 +1,163 @@
+/*
+ * @file BlockDecorFull.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
+ */
+package wile.engineersdecor.blocks;
+
+import net.minecraft.block.SoundType;
+import net.minecraft.util.*;
+import wile.engineersdecor.ModEngineersDecor;
+import wile.engineersdecor.detail.ModAuxiliaries;
+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.EntityLivingBase;
+import net.minecraft.entity.player.EntityPlayer;
+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;
+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_CUTOUT                 = 0x0000000000000001L; // cutout rendering
+  public static final long CFG_HORIZIONTAL            = 0x0000000000000002L; // horizontal block, affects bounding box calculation at construction time
+  public static final long CFG_HORIZIONTAL_PLACEMENT  = 0x0000000000000004L; // placed in the horizontzal direction the player is looking when placing.
+  public static final long CFG_WALL_DOOR_CONNECTION   = 0x0000000000000008L; // wall block connects to fence gates and doors.
+
+  public BlockDecor(@Nonnull String registryName, long config, @Nullable Material material, float hardness, float resistance, @Nullable SoundType sound)
+  {
+    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);
+    this.config = config;
+  }
+
+  @Override
+  @Nullable
+  @SuppressWarnings("deprecation")
+  public AxisAlignedBB getCollisionBoundingBox(IBlockState state, IBlockAccess world, BlockPos pos)
+  { return getBoundingBox(state, world, pos); }
+
+  @Override
+  @SideOnly(Side.CLIENT)
+  public void addInformation(ItemStack stack, @Nullable World world, List 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 : BlockRenderLayer.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)==0); }
+
+  @Override
+  @SuppressWarnings("deprecation")
+  public boolean isOpaqueCube(IBlockState state)
+  { return ((config & CFG_CUTOUT)==0); }
+
+  @Override
+  public boolean canSpawnInBlock()
+  { return false; }
+
+  @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
+  public boolean hasTileEntity(IBlockState state)
+  { return false; }
+
+  @Override
+  public void onBlockPlacedBy(World world, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack)
+  {}
+
+  @Override
+  public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
+  { return false; }
+
+  @Override
+  public void onBlockClicked(World world, BlockPos pos, EntityPlayer player)
+  {}
+
+  @Override
+  @SuppressWarnings("deprecation")
+  public void neighborChanged(IBlockState state, World world, BlockPos pos, Block blockIn, BlockPos fromPos)
+  {}
+
+  @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 super.getStateForPlacement(world, pos, facing, hitX, hitY, hitZ, meta, placer, hand); }
+
+  @Override
+  public boolean removedByPlayer(IBlockState state, World world, BlockPos pos, EntityPlayer player, boolean willHarvest)
+  { return super.removedByPlayer(state, world, pos, player, willHarvest); }
+
+}
diff --git a/src/main/java/wile/engineersdecor/blocks/BlockDecorDirected.java b/src/main/java/wile/engineersdecor/blocks/BlockDecorDirected.java
new file mode 100644
index 0000000..0a0d798
--- /dev/null
+++ b/src/main/java/wile/engineersdecor/blocks/BlockDecorDirected.java
@@ -0,0 +1,120 @@
+/*
+ * @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 net.minecraft.block.SoundType;
+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.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.BlockRenderLayer;
+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;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+
+public class BlockDecorDirected extends BlockDecor
+{
+  public static final PropertyDirection FACING = BlockDirectional.FACING;
+  protected final ArrayList 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(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
+  @SuppressWarnings("deprecation")
+  public BlockFaceShape getBlockFaceShape(IBlockAccess world, IBlockState state, BlockPos pos, EnumFacing face)
+  { return BlockFaceShape.UNDEFINED; }
+
+  @Override
+  @SuppressWarnings("deprecation")
+  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
+  @SideOnly(Side.CLIENT)
+  public BlockRenderLayer getRenderLayer()
+  { return BlockRenderLayer.CUTOUT; }
+
+  @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
+  @SuppressWarnings("deprecation")
+  public IBlockState getStateForPlacement(World world, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer)
+  {
+    if((config & CFG_HORIZIONTAL_PLACEMENT)!=0) {
+      // placement in direction the player is facing
+      return getDefaultState().withProperty(FACING, placer.getHorizontalFacing());
+    } else {
+      // default: placement on the face the player clicking
+      return getDefaultState().withProperty(FACING, facing);
+    }
+  }
+}
diff --git a/src/main/java/wile/engineersdecor/blocks/BlockDecorFull.java b/src/main/java/wile/engineersdecor/blocks/BlockDecorFull.java
new file mode 100644
index 0000000..a237d36
--- /dev/null
+++ b/src/main/java/wile/engineersdecor/blocks/BlockDecorFull.java
@@ -0,0 +1,60 @@
+/*
+ * @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);
+    setLightOpacity(255);
+  }
+
+  @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; }
+
+}
diff --git a/src/main/java/wile/engineersdecor/blocks/BlockDecorLadder.java b/src/main/java/wile/engineersdecor/blocks/BlockDecorLadder.java
new file mode 100644
index 0000000..a9a456f
--- /dev/null
+++ b/src/main/java/wile/engineersdecor/blocks/BlockDecorLadder.java
@@ -0,0 +1,106 @@
+/*
+ * @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.item.ItemStack;
+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
+{
+  protected static final AxisAlignedBB EDLADDER_SOUTH_AABB = ModAuxiliaries.getPixeledAABB(3, 0, 0, 13, 16, 2);
+  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 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
+  @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
+  @SuppressWarnings("deprecation")
+  public IBlockState getStateForPlacement(World world, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer)
+  {
+    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);
+  }
+
+}
diff --git a/src/main/java/wile/engineersdecor/blocks/BlockDecorStairs.java b/src/main/java/wile/engineersdecor/blocks/BlockDecorStairs.java
new file mode 100644
index 0000000..af107b4
--- /dev/null
+++ b/src/main/java/wile/engineersdecor/blocks/BlockDecorStairs.java
@@ -0,0 +1,25 @@
+/*
+ * @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.state.IBlockState;
+import wile.engineersdecor.ModEngineersDecor;
+import javax.annotation.Nonnull;
+
+
+public class BlockDecorStairs extends net.minecraft.block.BlockStairs
+{
+  public BlockDecorStairs(@Nonnull String registryName, IBlockState modelState)
+  {
+    super(modelState);
+    setCreativeTab(ModEngineersDecor.CREATIVE_TAB_ENGINEERSDECOR);
+    setRegistryName(ModEngineersDecor.MODID, registryName);
+    setTranslationKey(ModEngineersDecor.MODID + "." + registryName);
+  }
+}
diff --git a/src/main/java/wile/engineersdecor/blocks/BlockDecorWall.java b/src/main/java/wile/engineersdecor/blocks/BlockDecorWall.java
new file mode 100644
index 0000000..ed9a40e
--- /dev/null
+++ b/src/main/java/wile/engineersdecor/blocks/BlockDecorWall.java
@@ -0,0 +1,180 @@
+/*
+ * @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 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.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.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;
+
+  private static final double d_0 = 0.0d;
+  private static final double d_1 = 1.0d;
+  private static final double d_a = 0.25d;
+  private static final double d_b = 1.0d-d_a;
+  private static final double d_k = 0.26d; // 0.3125D;
+  private static final double d_l = 1.0d-d_k;
+  protected static final AxisAlignedBB[] AABB_BY_INDEX = new AxisAlignedBB[] {
+    new AxisAlignedBB(d_a, d_0, d_a, d_b, d_1, d_b),
+    new AxisAlignedBB(d_a, d_0, d_a, d_b, d_1, d_1),
+    new AxisAlignedBB(d_0, d_0, d_a, d_b, d_1, d_b),
+    new AxisAlignedBB(d_0, d_0, d_a, d_b, d_1, d_1),
+    new AxisAlignedBB(d_a, d_0, d_0, d_b, d_1, d_b),
+    new AxisAlignedBB(d_k, d_0, d_0, d_l, d_1, d_1),
+    new AxisAlignedBB(d_0, d_0, d_0, d_b, d_1, d_b),
+    new AxisAlignedBB(d_0, d_0, d_0, d_b, d_1, d_1),
+    new AxisAlignedBB(d_a, d_0, d_a, d_1, d_1, d_b),
+    new AxisAlignedBB(d_a, d_0, d_a, d_1, d_1, d_1),
+    new AxisAlignedBB(d_0, d_0, d_k, d_1, d_1, d_l),
+    new AxisAlignedBB(d_0, d_0, d_a, d_1, d_1, d_1),
+    new AxisAlignedBB(d_a, d_0, d_0, d_1, d_1, d_b),
+    new AxisAlignedBB(d_a, d_0, d_0, d_1, d_1, d_1),
+    new AxisAlignedBB(d_0, d_0, d_0, d_1, d_1, d_b),
+    new AxisAlignedBB(d_0, d_0, d_0, d_1, d_1, d_1)
+  };
+  private static final double clip_height = 1.5d;
+  protected static final AxisAlignedBB[] CLIP_AABB_BY_INDEX = new AxisAlignedBB[] { AABB_BY_INDEX[0].setMaxY(clip_height), AABB_BY_INDEX[1].setMaxY(clip_height), AABB_BY_INDEX[2].setMaxY(clip_height), AABB_BY_INDEX[3].setMaxY(clip_height), AABB_BY_INDEX[4].setMaxY(clip_height), AABB_BY_INDEX[5].setMaxY(clip_height), AABB_BY_INDEX[6].setMaxY(clip_height), AABB_BY_INDEX[7].setMaxY(clip_height), AABB_BY_INDEX[8].setMaxY(clip_height), AABB_BY_INDEX[9].setMaxY(clip_height), AABB_BY_INDEX[10].setMaxY(clip_height), AABB_BY_INDEX[11].setMaxY(clip_height), AABB_BY_INDEX[12].setMaxY(clip_height), AABB_BY_INDEX[13].setMaxY(clip_height), AABB_BY_INDEX[14].setMaxY(clip_height), AABB_BY_INDEX[15].setMaxY(clip_height) };
+
+  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
+  @SuppressWarnings("deprecation")
+  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 collidingBoxes, @Nullable Entity entityIn, boolean isActualState)
+  { addCollisionBoxToList(pos, entityBox, collidingBoxes, CLIP_AABB_BY_INDEX[getAABBIndex(isActualState ? state : getActualState(state, world, pos))]); }
+
+  @Nullable
+  @Override
+  @SuppressWarnings("deprecation")
+  public AxisAlignedBB getCollisionBoundingBox(IBlockState state, IBlockAccess world, BlockPos pos)
+  { return CLIP_AABB_BY_INDEX[getAABBIndex(getActualState(state, world, pos))]; }
+
+  private static int getAABBIndex(IBlockState state)
+  { return ((!(state.getValue(NORTH))) ? 0 : (1< registeredBlocks = new ArrayList<>();
+
+  @Nonnull
+  public static List getRegisteredBlocks()
+  { return Collections.unmodifiableList(registeredBlocks); }
+
+  // Invoked from CommonProxy.registerBlocks()
+  public static final void registerBlocks(RegistryEvent.Register event)
+  {
+    // Config based registry selection
+    ArrayList allBlocks = new ArrayList<>();
+    Collections.addAll(allBlocks, modBlocks);
+    if(Loader.isModLoaded("immersiveengineering")) {
+      ModEngineersDecor.logger.info("Immersive Engineering installed, registering dependent blocks...");
+      Collections.addAll(allBlocks, ieDependentBlocks);
+    }
+    if(ModConfig.zmisc.with_experimental) Collections.addAll(allBlocks, devBlocks);
+    for(Block e:allBlocks) registeredBlocks.add(e);
+    for(Block e:registeredBlocks) event.getRegistry().register(e);
+    ModEngineersDecor.logger.info("Registered " + Integer.toString(registeredBlocks.size()) + " blocks.");
+  }
+
+  // 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"));
+    }
+  }
+
+  // Invoked from CommonProxy.registerItems()
+  public static final void registerItemBlocks(RegistryEvent.Register event)
+  {
+    int n = 0;
+    for(Block e:registeredBlocks) {
+      ResourceLocation rl = e.getRegistryName();
+      if(rl == null) continue;
+      event.getRegistry().register(new ItemBlock(e).setRegistryName(rl));
+      ++n;
+    }
+  }
+
+}
diff --git a/src/main/java/wile/engineersdecor/detail/ClientProxy.java b/src/main/java/wile/engineersdecor/detail/ClientProxy.java
new file mode 100644
index 0000000..9a9bb4e
--- /dev/null
+++ b/src/main/java/wile/engineersdecor/detail/ClientProxy.java
@@ -0,0 +1,27 @@
+/*
+ * @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.minecraftforge.client.model.obj.OBJLoader;
+import net.minecraftforge.fml.common.event.FMLInitializationEvent;
+import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
+import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
+
+public class ClientProxy implements ModEngineersDecor.IProxy
+{
+  public void preInit(FMLPreInitializationEvent e)
+  { OBJLoader.INSTANCE.addDomain(ModEngineersDecor.MODID); }
+
+  public void init(FMLInitializationEvent e)
+  {}
+
+  public void postInit(FMLPostInitializationEvent e)
+  {}
+}
diff --git a/src/main/java/wile/engineersdecor/detail/ModAuxiliaries.java b/src/main/java/wile/engineersdecor/detail/ModAuxiliaries.java
new file mode 100644
index 0000000..3bea0b2
--- /dev/null
+++ b/src/main/java/wile/engineersdecor/detail/ModAuxiliaries.java
@@ -0,0 +1,147 @@
+/*
+ * @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.util.EnumFacing;
+import wile.engineersdecor.ModEngineersDecor;
+import net.minecraft.item.ItemStack;
+import net.minecraft.client.util.ITooltipFlag;
+import net.minecraft.world.World;
+import net.minecraft.util.text.TextComponentTranslation;
+import net.minecraft.util.text.TextFormatting;
+import net.minecraftforge.fml.relauncher.Side;
+import net.minecraft.util.math.AxisAlignedBB;
+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("\\$\\{([\\w\\.]+)\\}");
+      Matcher mt = pt.matcher(ft);
+      StringBuffer sb = new StringBuffer();
+      while(mt.find()) mt.appendReplacement(sb, (new TextComponentTranslation(mt.group(1))).getFormattedText().trim());
+      mt.appendTail(sb);
+      return sb.toString();
+    } else {
+      return ft;
+    }
+  }
+
+  /**
+   * 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 (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)||Keyboard.isKeyDown(Keyboard.KEY_RSHIFT)); }
+
+    @SideOnly(Side.CLIENT)
+    public static boolean helpCondition()
+    { return extendedTipCondition() && ((Keyboard.isKeyDown(Keyboard.KEY_LCONTROL)||Keyboard.isKeyDown(Keyboard.KEY_RCONTROL))); }
+
+    /**
+     * 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 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.
+      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 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;
+  }
+}
diff --git a/src/main/java/wile/engineersdecor/detail/ModConfig.java b/src/main/java/wile/engineersdecor/detail/ModConfig.java
new file mode 100644
index 0000000..79d42c4
--- /dev/null
+++ b/src/main/java/wile/engineersdecor/detail/ModConfig.java
@@ -0,0 +1,52 @@
+/*
+ * @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.ModEngineersDecor;
+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;
+
+@Config(modid = ModEngineersDecor.MODID)
+@Config.LangKey("engineersdecor.config.title")
+public class ModConfig
+{
+  @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")
+    public boolean with_experimental = false;
+  }
+
+  @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);
+    }
+  }
+
+  @SuppressWarnings("unused")
+  public static final void onPostInit(FMLPostInitializationEvent event)
+  {}
+
+}
diff --git a/src/main/java/wile/engineersdecor/detail/RecipeCondModSpecific.java b/src/main/java/wile/engineersdecor/detail/RecipeCondModSpecific.java
new file mode 100644
index 0000000..e89ae5d
--- /dev/null
+++ b/src/main/java/wile/engineersdecor/detail/RecipeCondModSpecific.java
@@ -0,0 +1,69 @@
+/*
+ * @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;
+
+  @Override
+  public BooleanSupplier parse(JsonContext context, JsonObject json) {
+    try {
+      final IForgeRegistry block_registry = ForgeRegistries.BLOCKS;
+      final IForgeRegistry 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 RECIPE_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 RECIPE_EXCLUDE; // required result not registered
+      }
+      final JsonArray missing = json.getAsJsonArray("missing");
+      if((missing!=null) && (missing.size() > 0)) {
+        for(JsonElement e: missing) {
+          if(!e.isJsonPrimitive()) continue;
+          final ResourceLocation rl = new ResourceLocation(((JsonPrimitive)e).getAsString());
+          // 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.
+          if((!block_registry.containsKey(rl)) && (!item_registry.containsKey(rl))) return RECIPE_INCLUDE;
+        }
+        return RECIPE_EXCLUDE; // all required there, but there is no item missing, so another recipe
+      } else {
+        return RECIPE_INCLUDE; // no missing given, means include if result and required are all there.
+      }
+    } catch(Throwable ex) {
+      ModEngineersDecor.logger.error("rsgauges::ResultRegisteredCondition failed: " + ex.toString());
+    }
+    return RECIPE_EXCLUDE; // skip on exception.
+  }
+}
diff --git a/src/main/java/wile/engineersdecor/detail/ServerProxy.java b/src/main/java/wile/engineersdecor/detail/ServerProxy.java
new file mode 100644
index 0000000..3007c27
--- /dev/null
+++ b/src/main/java/wile/engineersdecor/detail/ServerProxy.java
@@ -0,0 +1,26 @@
+/*
+ * @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;
+import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
+import net.minecraftforge.fml.common.event.FMLInitializationEvent;
+import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
+
+public class ServerProxy implements ModEngineersDecor.IProxy
+{
+  public void preInit(FMLPreInitializationEvent e)
+  {}
+
+  public void init(FMLInitializationEvent e)
+  {}
+
+  public void postInit(FMLPostInitializationEvent e)
+  {}
+}
diff --git a/src/main/resources/assets/engineersdecor/blockstates/clinker_brick_block.json b/src/main/resources/assets/engineersdecor/blockstates/clinker_brick_block.json
new file mode 100644
index 0000000..04aa8d2
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/blockstates/clinker_brick_block.json
@@ -0,0 +1,20 @@
+{
+  "forge_marker": 1,
+  "defaults": {
+    "model": "engineersdecor: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": [{}]
+  }
+}
diff --git a/src/main/resources/assets/engineersdecor/blockstates/clinker_brick_stairs.json b/src/main/resources/assets/engineersdecor/blockstates/clinker_brick_stairs.json
new file mode 100644
index 0000000..164f4ce
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/blockstates/clinker_brick_stairs.json
@@ -0,0 +1,56 @@
+{
+  "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 }
+  }
+}
diff --git a/src/main/resources/assets/engineersdecor/blockstates/concrete_wall.json b/src/main/resources/assets/engineersdecor/blockstates/concrete_wall.json
new file mode 100644
index 0000000..7956471
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/blockstates/concrete_wall.json
@@ -0,0 +1,18 @@
+{
+  "forge_marker": 1,
+  "defaults": {
+    "model": "engineersdecor:wall/concrete_wall_default",
+    "textures": {
+      "wall": "immersiveengineering:blocks/stone_decoration_concrete",
+      "particle": "immersiveengineering:blocks/stone_decoration_concrete"
+    }
+  },
+  "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 }}} }
+  }
+}
diff --git a/src/main/resources/assets/engineersdecor/blockstates/iron_sheet_roof.json b/src/main/resources/assets/engineersdecor/blockstates/iron_sheet_roof.json
new file mode 100644
index 0000000..364adae
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/blockstates/iron_sheet_roof.json
@@ -0,0 +1,55 @@
+{
+  "forge_marker": 1,
+  "defaults": {
+    "model": "engineersdecor:stairs/decor_straight_roof_model",
+    "textures": {
+      "bottom": "engineersdecor:blocks/iestyle/ironsheet_roof_top",
+      "side": "engineersdecor:blocks/iestyle/ironsheet_roof",
+      "top": "engineersdecor:blocks/iestyle/ironsheet_roof_top"
+    }
+  },
+  "variants": {
+    "normal": [{}],
+    "inventory": [{}],
+    "facing=east,half=bottom,shape=straight":  { "model": "engineersdecor:stairs/decor_straight_roof_model" },
+    "facing=west,half=bottom,shape=straight":  { "model": "engineersdecor:stairs/decor_straight_roof_model", "y": 180, "uvlock": true },
+    "facing=south,half=bottom,shape=straight": { "model": "engineersdecor:stairs/decor_straight_roof_model", "y": 90, "uvlock": true },
+    "facing=north,half=bottom,shape=straight": { "model": "engineersdecor:stairs/decor_straight_roof_model", "y": 270, "uvlock": true },
+    "facing=east,half=bottom,shape=outer_right":  { "model": "engineersdecor:stairs/decor_outer_roof_model" },
+    "facing=west,half=bottom,shape=outer_right":  { "model": "engineersdecor:stairs/decor_outer_roof_model", "y": 180, "uvlock": true },
+    "facing=south,half=bottom,shape=outer_right": { "model": "engineersdecor:stairs/decor_outer_roof_model", "y": 90, "uvlock": true },
+    "facing=north,half=bottom,shape=outer_right": { "model": "engineersdecor:stairs/decor_outer_roof_model", "y": 270, "uvlock": true },
+    "facing=east,half=bottom,shape=outer_left":  { "model": "engineersdecor:stairs/decor_outer_roof_model", "y": 270, "uvlock": true },
+    "facing=west,half=bottom,shape=outer_left":  { "model": "engineersdecor:stairs/decor_outer_roof_model", "y": 90, "uvlock": true },
+    "facing=south,half=bottom,shape=outer_left": { "model": "engineersdecor:stairs/decor_outer_roof_model" },
+    "facing=north,half=bottom,shape=outer_left": { "model": "engineersdecor:stairs/decor_outer_roof_model", "y": 180, "uvlock": true },
+    "facing=east,half=bottom,shape=inner_right":  { "model": "engineersdecor:stairs/decor_inner_roof_model" },
+    "facing=west,half=bottom,shape=inner_right":  { "model": "engineersdecor:stairs/decor_inner_roof_model", "y": 180, "uvlock": true },
+    "facing=south,half=bottom,shape=inner_right": { "model": "engineersdecor:stairs/decor_inner_roof_model", "y": 90, "uvlock": true },
+    "facing=north,half=bottom,shape=inner_right": { "model": "engineersdecor:stairs/decor_inner_roof_model", "y": 270, "uvlock": true },
+    "facing=east,half=bottom,shape=inner_left":  { "model": "engineersdecor:stairs/decor_inner_roof_model", "y": 270, "uvlock": true },
+    "facing=west,half=bottom,shape=inner_left":  { "model": "engineersdecor:stairs/decor_inner_roof_model", "y": 90, "uvlock": true },
+    "facing=south,half=bottom,shape=inner_left": { "model": "engineersdecor:stairs/decor_inner_roof_model" },
+    "facing=north,half=bottom,shape=inner_left": { "model": "engineersdecor:stairs/decor_inner_roof_model", "y": 180, "uvlock": true },
+    "facing=east,half=top,shape=straight":  { "model": "engineersdecor:stairs/decor_straight_roof_model", "x": 180, "uvlock": true },
+    "facing=west,half=top,shape=straight":  { "model": "engineersdecor:stairs/decor_straight_roof_model", "x": 180, "y": 180, "uvlock": true },
+    "facing=south,half=top,shape=straight": { "model": "engineersdecor:stairs/decor_straight_roof_model", "x": 180, "y": 90, "uvlock": true },
+    "facing=north,half=top,shape=straight": { "model": "engineersdecor:stairs/decor_straight_roof_model", "x": 180, "y": 270, "uvlock": true },
+    "facing=east,half=top,shape=outer_right":  { "model": "engineersdecor:stairs/decor_outer_roof_model", "x": 180, "y": 90, "uvlock": true },
+    "facing=west,half=top,shape=outer_right":  { "model": "engineersdecor:stairs/decor_outer_roof_model", "x": 180, "y": 270, "uvlock": true },
+    "facing=south,half=top,shape=outer_right": { "model": "engineersdecor:stairs/decor_outer_roof_model", "x": 180, "y": 180, "uvlock": true },
+    "facing=north,half=top,shape=outer_right": { "model": "engineersdecor:stairs/decor_outer_roof_model", "x": 180, "uvlock": true },
+    "facing=east,half=top,shape=outer_left":  { "model": "engineersdecor:stairs/decor_outer_roof_model", "x": 180, "uvlock": true },
+    "facing=west,half=top,shape=outer_left":  { "model": "engineersdecor:stairs/decor_outer_roof_model", "x": 180, "y": 180, "uvlock": true },
+    "facing=south,half=top,shape=outer_left": { "model": "engineersdecor:stairs/decor_outer_roof_model", "x": 180, "y": 90, "uvlock": true },
+    "facing=north,half=top,shape=outer_left": { "model": "engineersdecor:stairs/decor_outer_roof_model", "x": 180, "y": 270, "uvlock": true },
+    "facing=east,half=top,shape=inner_right":  { "model": "engineersdecor:stairs/decor_inner_roof_model", "x": 180, "y": 90, "uvlock": true },
+    "facing=west,half=top,shape=inner_right":  { "model": "engineersdecor:stairs/decor_inner_roof_model", "x": 180, "y": 270, "uvlock": true },
+    "facing=south,half=top,shape=inner_right": { "model": "engineersdecor:stairs/decor_inner_roof_model", "x": 180, "y": 180, "uvlock": true },
+    "facing=north,half=top,shape=inner_right": { "model": "engineersdecor:stairs/decor_inner_roof_model", "x": 180, "uvlock": true },
+    "facing=east,half=top,shape=inner_left":  { "model": "engineersdecor:stairs/decor_inner_roof_model", "x": 180, "uvlock": true },
+    "facing=west,half=top,shape=inner_left":  { "model": "engineersdecor:stairs/decor_inner_roof_model", "x": 180, "y": 180, "uvlock": true },
+    "facing=south,half=top,shape=inner_left": { "model": "engineersdecor:stairs/decor_inner_roof_model", "x": 180, "y": 90, "uvlock": true },
+    "facing=north,half=top,shape=inner_left": { "model": "engineersdecor:stairs/decor_inner_roof_model", "x": 180, "y": 270, "uvlock": true }
+  }
+}
diff --git a/src/main/resources/assets/engineersdecor/blockstates/iron_sheet_roof_block.json b/src/main/resources/assets/engineersdecor/blockstates/iron_sheet_roof_block.json
new file mode 100644
index 0000000..38c1161
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/blockstates/iron_sheet_roof_block.json
@@ -0,0 +1,11 @@
+{
+  "forge_marker": 1,
+  "defaults": {
+    "model": "engineersdecor:decor_full_block_model",
+    "textures": { "all": "engineersdecor:blocks/iestyle/ironsheet_roof" }
+  },
+  "variants": {
+    "normal": [{}],
+    "inventory": [{}]
+  }
+}
diff --git a/src/main/resources/assets/engineersdecor/blockstates/metal_rung_ladder.json b/src/main/resources/assets/engineersdecor/blockstates/metal_rung_ladder.json
new file mode 100644
index 0000000..f80feba
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/blockstates/metal_rung_ladder.json
@@ -0,0 +1,9 @@
+{
+  "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": [{}]
+  }
+}
diff --git a/src/main/resources/assets/engineersdecor/blockstates/metal_rung_steps.json b/src/main/resources/assets/engineersdecor/blockstates/metal_rung_steps.json
new file mode 100644
index 0000000..d759868
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/blockstates/metal_rung_steps.json
@@ -0,0 +1,9 @@
+{
+  "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": [{}]
+  }
+}
diff --git a/src/main/resources/assets/engineersdecor/blockstates/rebar_concrete.json b/src/main/resources/assets/engineersdecor/blockstates/rebar_concrete.json
new file mode 100644
index 0000000..cbeaeeb
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/blockstates/rebar_concrete.json
@@ -0,0 +1,20 @@
+{
+  "forge_marker": 1,
+  "defaults": {
+    "model": "engineersdecor: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": [{}]
+  }
+}
diff --git a/src/main/resources/assets/engineersdecor/blockstates/rebar_concrete_stairs.json b/src/main/resources/assets/engineersdecor/blockstates/rebar_concrete_stairs.json
new file mode 100644
index 0000000..0ad8c9e
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/blockstates/rebar_concrete_stairs.json
@@ -0,0 +1,56 @@
+{
+  "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 }
+  }
+}
diff --git a/src/main/resources/assets/engineersdecor/blockstates/rebar_concrete_wall.json b/src/main/resources/assets/engineersdecor/blockstates/rebar_concrete_wall.json
new file mode 100644
index 0000000..9590325
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/blockstates/rebar_concrete_wall.json
@@ -0,0 +1,18 @@
+{
+  "forge_marker": 1,
+  "defaults": {
+    "model": "engineersdecor:wall/concrete_wall_default",
+    "textures": {
+      "wall": "engineersdecor:blocks/concrete/rebar_concrete_texture0",
+      "particle": "engineersdecor:blocks/concrete/rebar_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 }}} }
+  }
+}
diff --git a/src/main/resources/assets/engineersdecor/blockstates/slag_brick_block.json b/src/main/resources/assets/engineersdecor/blockstates/slag_brick_block.json
new file mode 100644
index 0000000..23fc1ef
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/blockstates/slag_brick_block.json
@@ -0,0 +1,20 @@
+{
+  "forge_marker": 1,
+  "defaults": {
+    "model": "engineersdecor:decor_full_block_model",
+    "textures": { "all": "engineersdecor:blocks/slag_brick/slag_brick_texture0" }
+  },
+  "variants": {
+    "normal": [
+      { "textures": { "all": "engineersdecor:blocks/slag_brick/slag_brick_texture0" } },
+      { "textures": { "all": "engineersdecor:blocks/slag_brick/slag_brick_texture1" } },
+      { "textures": { "all": "engineersdecor:blocks/slag_brick/slag_brick_texture2" } },
+      { "textures": { "all": "engineersdecor:blocks/slag_brick/slag_brick_texture3" } },
+      { "textures": { "all": "engineersdecor:blocks/slag_brick/slag_brick_texture4" } },
+      { "textures": { "all": "engineersdecor:blocks/slag_brick/slag_brick_texture5" } },
+      { "textures": { "all": "engineersdecor:blocks/slag_brick/slag_brick_texture6" } },
+      { "textures": { "all": "engineersdecor:blocks/slag_brick/slag_brick_texture7" } }
+    ],
+    "inventory": [{}]
+  }
+}
diff --git a/src/main/resources/assets/engineersdecor/blockstates/slag_brick_stairs.json b/src/main/resources/assets/engineersdecor/blockstates/slag_brick_stairs.json
new file mode 100644
index 0000000..ac54ba7
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/blockstates/slag_brick_stairs.json
@@ -0,0 +1,56 @@
+{
+  "forge_marker": 1,
+  "defaults": {
+    "model": "engineersdecor:stairs/decor_straight_stairs_model",
+    "textures": {
+      "particle": "engineersdecor:blocks/slag_brick/slag_brick_texture0",
+      "bottom": "engineersdecor:blocks/slag_brick/slag_brick_texture0",
+      "top"   : "engineersdecor:blocks/slag_brick/slag_brick_texture0",
+      "side"  : "engineersdecor:blocks/slag_brick/slag_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 }
+  }
+}
diff --git a/src/main/resources/assets/engineersdecor/blockstates/treated_wood_ladder.json b/src/main/resources/assets/engineersdecor/blockstates/treated_wood_ladder.json
new file mode 100644
index 0000000..ea5b906
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/blockstates/treated_wood_ladder.json
@@ -0,0 +1,9 @@
+{
+  "forge_marker": 1,
+  "defaults": { "model": "engineersdecor:ladder/treated_wood_ladder_model" },
+  "variants": {
+    "normal": [{}],
+    "facing": { "north":{"y":0}, "south":{"y":180}, "west":{"y":270}, "east":{"y":90}, "up": {"x":0}, "down": {"x":0} },
+    "inventory": [{}]
+  }
+}
diff --git a/src/main/resources/assets/engineersdecor/blockstates/treated_wood_pole.json b/src/main/resources/assets/engineersdecor/blockstates/treated_wood_pole.json
new file mode 100644
index 0000000..dc6ff19
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/blockstates/treated_wood_pole.json
@@ -0,0 +1,17 @@
+{
+  "forge_marker": 1,
+  "defaults": {
+    "model": "engineersdecor:pole/straight_pole_model",
+    "x":-90,
+    "textures": {
+      "particle": "engineersdecor:blocks/pole/treated_wood_pole_side_texture",
+      "side": "engineersdecor:blocks/pole/treated_wood_pole_side_texture",
+      "top": "engineersdecor:blocks/pole/treated_wood_pole_top_texture"
+    }
+  },
+  "variants": {
+    "normal": [{}],
+    "facing": { "north": {"y":0}, "south": {"y":0}, "west": {"y":90}, "east": {"y":90}, "up": {"x":90}, "down": {"x":90} },
+    "inventory": [{}]
+  }
+}
diff --git a/src/main/resources/assets/engineersdecor/blockstates/treated_wood_table.json b/src/main/resources/assets/engineersdecor/blockstates/treated_wood_table.json
new file mode 100644
index 0000000..2279c04
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/blockstates/treated_wood_table.json
@@ -0,0 +1,8 @@
+{
+  "forge_marker": 1,
+  "defaults": { "model": "engineersdecor:furniture/treated_wood_table_model" },
+  "variants": {
+    "normal": [{}],
+    "inventory": [{}]
+  }
+}
diff --git a/src/main/resources/assets/engineersdecor/lang/en_us.lang b/src/main/resources/assets/engineersdecor/lang/en_us.lang
new file mode 100644
index 0000000..6000cab
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/lang/en_us.lang
@@ -0,0 +1,64 @@
+#
+# Engineer's Decor lang file
+#
+#PARSE_ESCAPES
+#
+#-----------------------------------------------------------------------------------------------------------
+itemGroup.tabengineersdecor=Engineer's Decor
+engineersdecor.config.title=Engineer's Decor config
+engineersdecor.tooltip.hint.extended=§6[§9SHIFT§r More info§6]§r
+engineersdecor.tooltip.hint.help=§6[§9CTRL-SHIFT§r Help§6]§r
+
+#-----------------------------------------------------------------------------------------------------------
+# Stone/"ceramic material" based blocks
+#-----------------------------------------------------------------------------------------------------------
+tile.engineersdecor.clinker_brick_block.name=Clinker brick
+tile.engineersdecor.clinker_brick_block.help=§6A brick block with position dependent texture variations.§r\nLooks slightly darker and more color intensive than the vanilla brick block.
+tile.engineersdecor.slag_brick_block.name=Slag brick
+tile.engineersdecor.slag_brick_block.help=§6A gray-brown brick block with position dependent texture variations.
+tile.engineersdecor.rebar_concrete.name=Rebar concrete
+tile.engineersdecor.rebar_concrete.help=§6Steel reinforced concrete block.§r Expensive but Creeper-proof like obsidian.
+tile.engineersdecor.rebar_concrete_wall.name=Rebar concrete wall
+tile.engineersdecor.rebar_concrete_wall.help=§6Steel reinforced concrete wall.§r Expensive but Creeper-proof like obsidian.
+tile.engineersdecor.concrete_wall.name=Concrete wall
+tile.engineersdecor.concrete_wall.help=§6Wall made of solid concrete.
+
+#-----------------------------------------------------------------------------------------------------------
+# Ladder blocks
+#-----------------------------------------------------------------------------------------------------------
+tile.engineersdecor.metal_rung_ladder.name=Metal rung ladder
+tile.engineersdecor.metal_rung_ladder.help=§6Typical industrial wall ladder, consisting of horizontal metal rod rungs.
+tile.engineersdecor.metal_rung_steps.name=Staggered metal steps
+tile.engineersdecor.metal_rung_steps.help=§6Staggered rod rungs affixed to a wall, allowing to climb up, fall down, and so on.
+tile.engineersdecor.treated_wood_ladder.name=Treated wood ladder
+tile.engineersdecor.treated_wood_ladder.help=§6Weather-proof wooden ladder.
+
+#-----------------------------------------------------------------------------------------------------------
+# Stairs and roofs
+#-----------------------------------------------------------------------------------------------------------
+tile.engineersdecor.clinker_brick_stairs.name=Clinker brick stairs
+tile.engineersdecor.clinker_brick_stairs.help=§6Looks slightly darker and more color intensive than the vanilla brick block.
+tile.engineersdecor.slag_brick_stairs.name=Clinker brick stairs
+tile.engineersdecor.slag_brick_stairs.help=§6Looks slightly darker and more color intensive than the vanilla brick block.
+tile.engineersdecor.rebar_concrete_stairs.name=Rebar concrete stairs
+tile.engineersdecor.rebar_concrete_stairs.help=§6Steel reinforced concrete stairs.§r Expensive but Creeper-proof like obsidian.
+
+tile.engineersdecor.iron_sheet_roof.name=Iron sheet metal roof
+tile.engineersdecor.iron_sheet_roof.help=§6Well, it's a roof.
+
+#-----------------------------------------------------------------------------------------------------------
+# Poles and supports
+#-----------------------------------------------------------------------------------------------------------
+tile.engineersdecor.treated_wood_pole.name=Straight treated wood pole
+tile.engineersdecor.treated_wood_pole.help=§6Straight pole fragment with the diameter of a wire relay.§r\n\
+              Can be useful as alternative to the wire posts if special special lengths are needed, \
+              or as support for structures.
+
+#-----------------------------------------------------------------------------------------------------------
+# Furniture
+#-----------------------------------------------------------------------------------------------------------
+tile.engineersdecor.treated_wood_table.name=Treated wood table
+tile.engineersdecor.treated_wood_table.help=§6Robust four-legged wood table.
+
+# EOF
+#-----------------------------------------------------------------------------------------------------------
diff --git a/src/main/resources/assets/engineersdecor/logo.png b/src/main/resources/assets/engineersdecor/logo.png
new file mode 100644
index 0000000..793e40f
Binary files /dev/null and b/src/main/resources/assets/engineersdecor/logo.png differ
diff --git a/src/main/resources/assets/engineersdecor/models/block/decor_full_block_model.json b/src/main/resources/assets/engineersdecor/models/block/decor_full_block_model.json
new file mode 100644
index 0000000..f7aee27
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/models/block/decor_full_block_model.json
@@ -0,0 +1 @@
+{ "parent": "block/cube_all", "textures": { "all": "engineersdecor:blocks/clinker_brick/clinker_brick_texture0" } }
\ No newline at end of file
diff --git a/src/main/resources/assets/engineersdecor/models/block/furniture/treated_wood_table_model.json b/src/main/resources/assets/engineersdecor/models/block/furniture/treated_wood_table_model.json
new file mode 100644
index 0000000..04b7880
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/models/block/furniture/treated_wood_table_model.json
@@ -0,0 +1,190 @@
+{
+	"credit": "I made this with the Blockbench",
+	"parent": "block/cube",
+	"textures": {
+		"o": "engineersdecor:blocks/iestyle/treated_wood_framed_texture",
+		"particle": "engineersdecor:blocks/iestyle/treated_wood_framed_texture"
+	},
+	"elements": [
+		{
+			"from": [1, 0, 1],
+			"to": [3, 14, 3],
+			"faces": {
+				"north": {"uv": [13, 2, 15, 16], "texture": "#o"},
+				"east": {"uv": [13, 2, 15, 16], "texture": "#o"},
+				"south": {"uv": [1, 2, 3, 16], "texture": "#o"},
+				"west": {"uv": [1, 2, 3, 16], "texture": "#o"},
+				"up": {"uv": [1, 1, 3, 3], "texture": "#o"},
+				"down": {"uv": [1, 13, 3, 15], "texture": "#o", "cullface": "down"}
+			}
+		},
+		{
+			"from": [13, 0, 1],
+			"to": [15, 14, 3],
+			"faces": {
+				"north": {"uv": [1, 2, 3, 16], "texture": "#o"},
+				"east": {"uv": [13, 2, 15, 16], "texture": "#o"},
+				"south": {"uv": [13, 2, 15, 16], "texture": "#o"},
+				"west": {"uv": [1, 2, 3, 16], "texture": "#o"},
+				"up": {"uv": [13, 1, 15, 3], "texture": "#o"},
+				"down": {"uv": [13, 13, 15, 15], "texture": "#o", "cullface": "down"}
+			}
+		},
+		{
+			"from": [13, 0, 13],
+			"to": [15, 14, 15],
+			"faces": {
+				"north": {"uv": [1, 2, 3, 16], "texture": "#o"},
+				"east": {"uv": [1, 2, 3, 16], "texture": "#o"},
+				"south": {"uv": [13, 2, 15, 16], "texture": "#o"},
+				"west": {"uv": [13, 2, 15, 16], "texture": "#o"},
+				"up": {"uv": [13, 13, 15, 15], "texture": "#o"},
+				"down": {"uv": [13, 1, 15, 3], "texture": "#o", "cullface": "down"}
+			}
+		},
+		{
+			"from": [1, 0, 13],
+			"to": [3, 14, 15],
+			"faces": {
+				"north": {"uv": [13, 2, 15, 16], "texture": "#o"},
+				"east": {"uv": [1, 2, 3, 16], "texture": "#o"},
+				"south": {"uv": [1, 2, 3, 16], "texture": "#o"},
+				"west": {"uv": [13, 2, 15, 16], "texture": "#o"},
+				"up": {"uv": [1, 13, 3, 15], "texture": "#o"},
+				"down": {"uv": [1, 1, 3, 3], "texture": "#o", "cullface": "down"}
+			}
+		},
+		{
+			"from": [0, 14, 0],
+			"to": [16, 15.875, 16],
+			"faces": {
+				"north": {"uv": [0, 0.125, 16, 2], "texture": "#o"},
+				"east": {"uv": [0, 0.125, 16, 2], "texture": "#o"},
+				"south": {"uv": [0, 0.125, 16, 2], "texture": "#o"},
+				"west": {"uv": [0, 0.125, 16, 2], "texture": "#o"},
+				"up": {"uv": [0, 0, 16, 16], "texture": "#o"},
+				"down": {"uv": [0, 0, 16, 16], "texture": "#o"}
+			}
+		},
+		{
+			"from": [0.125, 15.875, 0.125],
+			"to": [15.875, 16, 15.875],
+			"faces": {
+				"north": {"uv": [0.25, 0, 15.75, 0.125], "texture": "#o"},
+				"east": {"uv": [0.25, 0, 15.75, 0.125], "texture": "#o"},
+				"south": {"uv": [0.25, 0, 15.75, 0.125], "texture": "#o"},
+				"west": {"uv": [0.25, 0, 15.75, 0.125], "texture": "#o"},
+				"up": {"uv": [0.25, 0.25, 15.75, 15.75], "texture": "#o"},
+				"down": {"uv": [0.25, 0.25, 15.75, 15.75], "texture": "#o"}
+			}
+		},
+		{
+			"from": [13, 13.5, 3],
+			"to": [15, 14, 5],
+			"faces": {
+				"north": {"uv": [1, 2, 3, 2.5], "texture": "#o"},
+				"east": {"uv": [11, 2, 13, 2.5], "texture": "#o"},
+				"south": {"uv": [13, 2, 15, 2.5], "texture": "#o"},
+				"west": {"uv": [3, 2, 5, 2.5], "texture": "#o"},
+				"up": {"uv": [13, 3, 15, 5], "texture": "#o"},
+				"down": {"uv": [13, 11, 15, 13], "texture": "#o"}
+			}
+		},
+		{
+			"from": [13, 13.5, 11],
+			"to": [15, 14, 13],
+			"faces": {
+				"north": {"uv": [1, 2, 3, 2.5], "texture": "#o"},
+				"east": {"uv": [3, 2, 5, 2.5], "texture": "#o"},
+				"south": {"uv": [13, 2, 15, 2.5], "texture": "#o"},
+				"west": {"uv": [11, 2, 13, 2.5], "texture": "#o"},
+				"up": {"uv": [13, 11, 15, 13], "texture": "#o"},
+				"down": {"uv": [13, 3, 15, 5], "texture": "#o"}
+			}
+		},
+		{
+			"from": [1, 13.5, 11],
+			"to": [3, 14, 13],
+			"faces": {
+				"north": {"uv": [13, 2, 15, 2.5], "texture": "#o"},
+				"east": {"uv": [3, 2, 5, 2.5], "texture": "#o"},
+				"south": {"uv": [1, 2, 3, 2.5], "texture": "#o"},
+				"west": {"uv": [11, 2, 13, 2.5], "texture": "#o"},
+				"up": {"uv": [1, 11, 3, 13], "texture": "#o"},
+				"down": {"uv": [1, 3, 3, 5], "texture": "#o"}
+			}
+		},
+		{
+			"from": [1, 13.5, 3],
+			"to": [3, 14, 5],
+			"faces": {
+				"north": {"uv": [13, 2, 15, 2.5], "texture": "#o"},
+				"east": {"uv": [11, 2, 13, 2.5], "texture": "#o"},
+				"south": {"uv": [1, 2, 3, 2.5], "texture": "#o"},
+				"west": {"uv": [3, 2, 5, 2.5], "texture": "#o"},
+				"up": {"uv": [1, 3, 3, 5], "texture": "#o"},
+				"down": {"uv": [1, 11, 3, 13], "texture": "#o"}
+			}
+		},
+		{
+			"from": [11, 13.5, 1],
+			"to": [13, 14, 3],
+			"faces": {
+				"north": {"uv": [3, 2, 5, 2.5], "texture": "#o"},
+				"east": {"uv": [13, 2, 15, 2.5], "texture": "#o"},
+				"south": {"uv": [11, 2, 13, 2.5], "texture": "#o"},
+				"west": {"uv": [1, 2, 3, 2.5], "texture": "#o"},
+				"up": {"uv": [11, 1, 13, 3], "texture": "#o"},
+				"down": {"uv": [11, 13, 13, 15], "texture": "#o"}
+			}
+		},
+		{
+			"from": [3, 13.5, 1],
+			"to": [5, 14, 3],
+			"faces": {
+				"north": {"uv": [11, 2, 13, 2.5], "texture": "#o"},
+				"east": {"uv": [13, 2, 15, 2.5], "texture": "#o"},
+				"south": {"uv": [3, 2, 5, 2.5], "texture": "#o"},
+				"west": {"uv": [1, 2, 3, 2.5], "texture": "#o"},
+				"up": {"uv": [3, 1, 5, 3], "texture": "#o"},
+				"down": {"uv": [3, 13, 5, 15], "texture": "#o"}
+			}
+		},
+		{
+			"from": [11, 13.5, 13],
+			"to": [13, 14, 15],
+			"faces": {
+				"north": {"uv": [3, 2, 5, 2.5], "texture": "#o"},
+				"east": {"uv": [1, 2, 3, 2.5], "texture": "#o"},
+				"south": {"uv": [11, 2, 13, 2.5], "texture": "#o"},
+				"west": {"uv": [13, 2, 15, 2.5], "texture": "#o"},
+				"up": {"uv": [11, 13, 13, 15], "texture": "#o"},
+				"down": {"uv": [11, 1, 13, 3], "texture": "#o"}
+			}
+		},
+		{
+			"from": [3, 13.5, 13],
+			"to": [5, 14, 15],
+			"faces": {
+				"north": {"uv": [11, 2, 13, 2.5], "texture": "#o"},
+				"east": {"uv": [1, 2, 3, 2.5], "texture": "#o"},
+				"south": {"uv": [3, 2, 5, 2.5], "texture": "#o"},
+				"west": {"uv": [13, 2, 15, 2.5], "texture": "#o"},
+				"up": {"uv": [3, 13, 5, 15], "texture": "#o"},
+				"down": {"uv": [3, 1, 5, 3], "texture": "#o"}
+			}
+		}
+	],
+	"display": {
+		"ground": {
+			"scale": [0.2, 0.2, 0.2]
+		},
+		"gui": {
+			"rotation": [30, 225, 0],
+			"scale": [0.625, 0.625, 0.625]
+		},
+		"fixed": {
+			"scale": [0.5, 0.5, 0.5]
+		}
+	}
+}
\ No newline at end of file
diff --git a/src/main/resources/assets/engineersdecor/models/block/ladder/metal_rung_ladder_model.json b/src/main/resources/assets/engineersdecor/models/block/ladder/metal_rung_ladder_model.json
new file mode 100644
index 0000000..a982c45
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/models/block/ladder/metal_rung_ladder_model.json
@@ -0,0 +1,159 @@
+{
+  "credit": "I made this with the Blockbench",
+  "parent": "block/cube",
+	"textures": {
+    "particle": "engineersdecor:blocks/iestyle/steel_texture",
+		"o": "engineersdecor:blocks/iestyle/steel_texture"
+  },
+  "display": {
+		"gui":    { "rotation": [ 30, 225, 0 ], "scale": [0.625, 0.625, 0.625] },
+		"fixed":  { "scale": [0.5, 0.5, 0.5] },
+		"ground": {	"scale": [0.2, 0.2, 0.2] }
+	},
+	"elements": [
+		{
+			"from": [3, 2, 14],
+			"to": [13, 3, 15],
+			"faces": {
+				"north": {"uv": [1, 13, 16, 15], "texture": "#o"},
+				"east": {"uv": [12, 13, 14, 15], "texture": "#o"},
+				"south": {"uv": [1, 13, 16, 15], "texture": "#o"},
+				"west": {"uv": [13, 11, 15, 13], "texture": "#o"},
+				"up": {"uv": [1, 11, 16, 13], "texture": "#o"},
+				"down": {"uv": [1, 13, 16, 15], "texture": "#o"}
+			}
+		},
+		{
+			"from": [3, 6, 14],
+			"to": [13, 7, 15],
+			"faces": {
+				"north": {"uv": [3, 13, 16, 15], "texture": "#o"},
+				"east": {"uv": [6, 14, 8, 16], "texture": "#o"},
+				"south": {"uv": [3, 13, 16, 15], "texture": "#o"},
+				"west": {"uv": [7, 9, 9, 11], "texture": "#o"},
+				"up": {"uv": [0, 13, 13, 15], "texture": "#o"},
+				"down": {"uv": [3, 13, 16, 15], "texture": "#o"}
+			}
+		},
+		{
+			"from": [3, 14, 14],
+			"to": [13, 15, 15],
+			"faces": {
+				"north": {"uv": [2, 6, 16, 8], "texture": "#o"},
+				"east": {"uv": [7, 3, 9, 5], "texture": "#o"},
+				"south": {"uv": [2, 6, 16, 8], "texture": "#o"},
+				"west": {"uv": [2, 6, 4, 8], "texture": "#o"},
+				"up": {"uv": [0, 4, 14, 6], "texture": "#o"},
+				"down": {"uv": [2, 6, 16, 8], "texture": "#o"}
+			}
+		},
+		{
+			"from": [3, 10, 14],
+			"to": [13, 11, 15],
+			"faces": {
+				"north": {"uv": [0, 11, 13, 13], "texture": "#o"},
+				"east": {"uv": [1, 13, 3, 15], "texture": "#o"},
+				"south": {"uv": [0, 11, 13, 13], "texture": "#o"},
+				"west": {"uv": [0, 11, 2, 13], "texture": "#o"},
+				"up": {"uv": [0, 9, 13, 11], "texture": "#o"},
+				"down": {"uv": [0, 11, 13, 13], "texture": "#o"}
+			}
+		},
+		{
+			"from": [12, 2, 15],
+			"to": [13.25, 3, 16],
+			"faces": {
+				"north": {"uv": [0, 0, 1.25, 1], "texture": "#o"},
+				"east": {"uv": [7, 9, 9, 11], "texture": "#o"},
+				"south": {"uv": [1, 12, 4.25, 14], "texture": "#o"},
+				"west": {"uv": [0, 0, 1, 1], "texture": "#o"},
+				"up": {"uv": [13, 4, 16, 6], "texture": "#o"},
+				"down": {"uv": [1, 12, 4, 14], "texture": "#o"}
+			}
+		},
+		{
+			"from": [2.75, 2, 15],
+			"to": [4, 3, 16],
+			"faces": {
+				"north": {"uv": [0, 0, 1.25, 1], "texture": "#o"},
+				"east": {"uv": [0, 0, 1, 1], "texture": "#o"},
+				"south": {"uv": [11, 1, 14.25, 3], "texture": "#o"},
+				"west": {"uv": [11, 9, 13, 11], "texture": "#o"},
+				"up": {"uv": [12, 11, 15, 13], "texture": "#o"},
+				"down": {"uv": [7, 3, 10, 5], "texture": "#o"}
+			}
+		},
+		{
+			"from": [2.75, 10, 15],
+			"to": [4, 11, 16],
+			"faces": {
+				"north": {"uv": [0, 0, 1.25, 1], "texture": "#o"},
+				"east": {"uv": [0, 0, 1, 1], "texture": "#o"},
+				"south": {"uv": [12, 14, 15.25, 16], "texture": "#o"},
+				"west": {"uv": [7, 10, 9, 12], "texture": "#o"},
+				"up": {"uv": [5, 12, 8, 14], "texture": "#o"},
+				"down": {"uv": [4, 14, 7, 16], "texture": "#o"}
+			}
+		},
+		{
+			"from": [12, 10, 15],
+			"to": [13.25, 11, 16],
+			"faces": {
+				"north": {"uv": [0, 0, 1.25, 1.25], "texture": "#o"},
+				"east": {"uv": [2, 4, 5, 6.25], "texture": "#o"},
+				"south": {"uv": [10, 10, 13, 12], "texture": "#o"},
+				"west": {"uv": [0, 0, 1, 1.25], "texture": "#o"},
+				"up": {"uv": [7, 11, 9, 13], "texture": "#o"},
+				"down": {"uv": [8, 0, 11, 2], "texture": "#o"}
+			}
+		},
+		{
+			"from": [2.75, 6, 15],
+			"to": [4, 7, 16],
+			"faces": {
+				"north": {"uv": [0, 0, 1.25, 1], "texture": "#o"},
+				"east": {"uv": [0, 0, 1, 1], "texture": "#o"},
+				"south": {"uv": [4, 7, 7.25, 9], "texture": "#o"},
+				"west": {"uv": [11, 9, 13, 11], "texture": "#o"},
+				"up": {"uv": [0, 13, 3, 15], "texture": "#o"},
+				"down": {"uv": [4, 7, 7, 9], "texture": "#o"}
+			}
+		},
+		{
+			"from": [12, 6, 15],
+			"to": [13.25, 7, 16],
+			"faces": {
+				"north": {"uv": [0, 0, 1.25, 1], "texture": "#o"},
+				"east": {"uv": [8, 9, 10, 11], "texture": "#o"},
+				"south": {"uv": [0, 0, 1.25, 1], "texture": "#o"},
+				"west": {"uv": [0, 0, 1, 1], "texture": "#o"},
+				"up": {"uv": [5, 13, 8, 15], "texture": "#o"},
+				"down": {"uv": [8, 14, 11, 16], "texture": "#o"}
+			}
+		},
+		{
+			"from": [2.75, 14, 15],
+			"to": [4, 15, 16],
+			"faces": {
+				"north": {"uv": [0, 0, 1.25, 1], "texture": "#o"},
+				"east": {"uv": [0, 0, 1, 1], "texture": "#o"},
+				"south": {"uv": [3, 11, 6, 13], "texture": "#o"},
+				"west": {"uv": [14, 7, 16, 9], "texture": "#o"},
+				"up": {"uv": [7, 12, 10, 14], "texture": "#o"},
+				"down": {"uv": [12, 7, 15, 9], "texture": "#o"}
+			}
+		},
+		{
+			"from": [12, 14, 15],
+			"to": [13.25, 15, 16],
+			"faces": {
+				"north": {"uv": [0, 0, 1.25, 1.25], "texture": "#o"},
+				"east": {"uv": [0, 0, 3, 2.25], "texture": "#o"},
+				"south": {"uv": [0, 13, 3, 15], "texture": "#o"},
+				"west": {"uv": [0, 0, 1, 1.25], "texture": "#o"},
+				"up": {"uv": [3, 7, 5.25, 9], "texture": "#o"},
+				"down": {"uv": [0, 0, 1.25, 1], "texture": "#o"}
+			}
+		}
+	]
+}
\ No newline at end of file
diff --git a/src/main/resources/assets/engineersdecor/models/block/ladder/metal_rung_steps_model.json b/src/main/resources/assets/engineersdecor/models/block/ladder/metal_rung_steps_model.json
new file mode 100644
index 0000000..9b90fda
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/models/block/ladder/metal_rung_steps_model.json
@@ -0,0 +1,166 @@
+{
+	"credit": "I made this with the Blockbench",
+	"parent": "block/cube",
+	"textures": {
+		"o": "engineersdecor:blocks/iestyle/steel_texture",
+		"particle": "engineersdecor:blocks/iestyle/steel_texture"
+	},
+	"elements": [
+		{
+			"from": [3, 2, 14],
+			"to": [7, 3, 15],
+			"faces": {
+				"north": {"uv": [1, 13, 9, 15], "texture": "#o"},
+				"east": {"uv": [12, 13, 14, 15], "texture": "#o"},
+				"south": {"uv": [4, 10, 11, 12], "texture": "#o"},
+				"west": {"uv": [13, 11, 15, 13], "texture": "#o"},
+				"up": {"uv": [1, 11, 9, 13], "texture": "#o"},
+				"down": {"uv": [7, 2, 14, 4], "texture": "#o"}
+			}
+		},
+		{
+			"from": [9, 6, 14],
+			"to": [13, 7, 15],
+			"faces": {
+				"north": {"uv": [3, 13, 9, 15], "texture": "#o"},
+				"east": {"uv": [6, 14, 8, 16], "texture": "#o"},
+				"south": {"uv": [4, 10, 11, 12], "texture": "#o"},
+				"west": {"uv": [7, 9, 9, 11], "texture": "#o"},
+				"up": {"uv": [6, 11, 13, 13], "texture": "#o"},
+				"down": {"uv": [9, 12, 16, 14], "texture": "#o"}
+			}
+		},
+		{
+			"from": [9, 14, 14],
+			"to": [13, 15, 15],
+			"faces": {
+				"north": {"uv": [2, 6, 9, 8], "texture": "#o"},
+				"east": {"uv": [7, 3, 9, 5], "texture": "#o"},
+				"south": {"uv": [5, 13, 13, 15], "texture": "#o"},
+				"west": {"uv": [2, 6, 4, 8], "texture": "#o"},
+				"up": {"uv": [6, 9, 13, 11], "texture": "#o"},
+				"down": {"uv": [4, 10, 11, 12], "texture": "#o"}
+			}
+		},
+		{
+			"from": [3, 10, 14],
+			"to": [7, 11, 15],
+			"faces": {
+				"north": {"uv": [0, 11, 6, 13], "texture": "#o"},
+				"east": {"uv": [1, 13, 3, 15], "texture": "#o"},
+				"south": {"uv": [4, 6, 12, 8], "texture": "#o"},
+				"west": {"uv": [0, 11, 2, 13], "texture": "#o"},
+				"up": {"uv": [3, 5, 11, 7], "texture": "#o"},
+				"down": {"uv": [5, 7, 12, 9], "texture": "#o"}
+			}
+		},
+		{
+			"from": [6, 2, 15],
+			"to": [7.25, 3, 16],
+			"faces": {
+				"north": {"uv": [0, 0, 1.25, 1], "texture": "#o"},
+				"east": {"uv": [7, 9, 9, 11], "texture": "#o"},
+				"south": {"uv": [1, 12, 4.25, 14], "texture": "#o"},
+				"west": {"uv": [0, 0, 1, 1], "texture": "#o"},
+				"up": {"uv": [13, 4, 16, 6], "texture": "#o"},
+				"down": {"uv": [1, 12, 4, 14], "texture": "#o"}
+			}
+		},
+		{
+			"from": [2.75, 2, 15],
+			"to": [4, 3, 16],
+			"faces": {
+				"north": {"uv": [0, 0, 1.25, 1], "texture": "#o"},
+				"east": {"uv": [0, 0, 1, 1], "texture": "#o"},
+				"south": {"uv": [11, 1, 14.25, 3], "texture": "#o"},
+				"west": {"uv": [11, 9, 13, 11], "texture": "#o"},
+				"up": {"uv": [12, 11, 15, 13], "texture": "#o"},
+				"down": {"uv": [7, 3, 10, 5], "texture": "#o"}
+			}
+		},
+		{
+			"from": [2.75, 10, 15],
+			"to": [4, 11, 16],
+			"faces": {
+				"north": {"uv": [0, 0, 1.25, 1], "texture": "#o"},
+				"east": {"uv": [0, 0, 1, 1], "texture": "#o"},
+				"south": {"uv": [12, 14, 15.25, 16], "texture": "#o"},
+				"west": {"uv": [7, 10, 9, 12], "texture": "#o"},
+				"up": {"uv": [5, 12, 8, 14], "texture": "#o"},
+				"down": {"uv": [4, 14, 7, 16], "texture": "#o"}
+			}
+		},
+		{
+			"from": [6, 10, 15],
+			"to": [7.25, 11, 16],
+			"faces": {
+				"north": {"uv": [0, 0, 1.25, 1.25], "texture": "#o"},
+				"east": {"uv": [2, 4, 5, 6.25], "texture": "#o"},
+				"south": {"uv": [10, 10, 13, 12], "texture": "#o"},
+				"west": {"uv": [0, 0, 1, 1.25], "texture": "#o"},
+				"up": {"uv": [7, 11, 9, 13], "texture": "#o"},
+				"down": {"uv": [8, 0, 11, 2], "texture": "#o"}
+			}
+		},
+		{
+			"from": [8.75, 6, 15],
+			"to": [10, 7, 16],
+			"faces": {
+				"north": {"uv": [0, 0, 1.25, 1], "texture": "#o"},
+				"east": {"uv": [0, 0, 1, 1], "texture": "#o"},
+				"south": {"uv": [4, 7, 7.25, 9], "texture": "#o"},
+				"west": {"uv": [11, 9, 13, 11], "texture": "#o"},
+				"up": {"uv": [0, 13, 3, 15], "texture": "#o"},
+				"down": {"uv": [4, 7, 7, 9], "texture": "#o"}
+			}
+		},
+		{
+			"from": [12, 6, 15],
+			"to": [13.25, 7, 16],
+			"faces": {
+				"north": {"uv": [0, 0, 1.25, 1], "texture": "#o"},
+				"east": {"uv": [8, 9, 10, 11], "texture": "#o"},
+				"south": {"uv": [0, 0, 1.25, 1], "texture": "#o"},
+				"west": {"uv": [0, 0, 1, 1], "texture": "#o"},
+				"up": {"uv": [5, 13, 8, 15], "texture": "#o"},
+				"down": {"uv": [8, 14, 11, 16], "texture": "#o"}
+			}
+		},
+		{
+			"from": [8.75, 14, 15],
+			"to": [10, 15, 16],
+			"faces": {
+				"north": {"uv": [0, 0, 1.25, 1], "texture": "#o"},
+				"east": {"uv": [0, 0, 1, 1], "texture": "#o"},
+				"south": {"uv": [3, 11, 6, 13], "texture": "#o"},
+				"west": {"uv": [14, 7, 16, 9], "texture": "#o"},
+				"up": {"uv": [7, 12, 10, 14], "texture": "#o"},
+				"down": {"uv": [12, 7, 15, 9], "texture": "#o"}
+			}
+		},
+		{
+			"from": [12, 14, 15],
+			"to": [13.25, 15, 16],
+			"faces": {
+				"north": {"uv": [0, 0, 1.25, 1.25], "texture": "#o"},
+				"east": {"uv": [0, 0, 3, 2.25], "texture": "#o"},
+				"south": {"uv": [0, 13, 3, 15], "texture": "#o"},
+				"west": {"uv": [0, 0, 1, 1.25], "texture": "#o"},
+				"up": {"uv": [3, 7, 5.25, 9], "texture": "#o"},
+				"down": {"uv": [0, 0, 1.25, 1], "texture": "#o"}
+			}
+		}
+	],
+	"display": {
+		"ground": {
+			"scale": [0.2, 0.2, 0.2]
+		},
+		"gui": {
+			"rotation": [30, 225, 0],
+			"scale": [0.625, 0.625, 0.625]
+		},
+		"fixed": {
+			"scale": [0.5, 0.5, 0.5]
+		}
+	}
+}
\ No newline at end of file
diff --git a/src/main/resources/assets/engineersdecor/models/block/ladder/treated_wood_ladder_model.json b/src/main/resources/assets/engineersdecor/models/block/ladder/treated_wood_ladder_model.json
new file mode 100644
index 0000000..4e07b10
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/models/block/ladder/treated_wood_ladder_model.json
@@ -0,0 +1,94 @@
+{
+	"credit": "I made this with the Blockbench",
+	"parent": "block/cube",
+	"textures": {
+		"o": "engineersdecor:blocks/iestyle/treated_wood_rough_texture",
+		"particle": "engineersdecor:blocks/iestyle/treated_wood_rough_texture"
+	},
+	"elements": [
+		{
+			"from": [4, 2, 14.625],
+			"to": [12, 3, 15.625],
+			"faces": {
+				"north": {"uv": [0, 11, 15, 13], "texture": "#o"},
+				"east": {"uv": [12, 13, 14, 15], "texture": "#o"},
+				"south": {"uv": [1, 13, 16, 15], "texture": "#o"},
+				"west": {"uv": [13, 11, 15, 13], "texture": "#o"},
+				"up": {"uv": [1, 11, 16, 13], "texture": "#o"},
+				"down": {"uv": [1, 13, 16, 15], "texture": "#o"}
+			}
+		},
+		{
+			"from": [4, 6, 14.625],
+			"to": [12, 7, 15.625],
+			"faces": {
+				"north": {"uv": [1, 6, 14, 8], "texture": "#o"},
+				"east": {"uv": [6, 14, 8, 16], "texture": "#o"},
+				"south": {"uv": [3, 13, 16, 15], "texture": "#o"},
+				"west": {"uv": [7, 9, 9, 11], "texture": "#o"},
+				"up": {"uv": [0, 13, 13, 15], "texture": "#o"},
+				"down": {"uv": [3, 13, 16, 15], "texture": "#o"}
+			}
+		},
+		{
+			"from": [4, 14, 14.625],
+			"to": [12, 15, 15.625],
+			"faces": {
+				"north": {"uv": [0, 4, 14, 6], "texture": "#o"},
+				"east": {"uv": [7, 3, 9, 5], "texture": "#o"},
+				"south": {"uv": [2, 6, 16, 8], "texture": "#o"},
+				"west": {"uv": [2, 6, 4, 8], "texture": "#o"},
+				"up": {"uv": [0, 4, 14, 6], "texture": "#o"},
+				"down": {"uv": [2, 6, 16, 8], "texture": "#o"}
+			}
+		},
+		{
+			"from": [4, 10, 14.625],
+			"to": [12, 11, 15.625],
+			"faces": {
+				"north": {"uv": [3, 5, 16, 7], "texture": "#o"},
+				"east": {"uv": [1, 13, 3, 15], "texture": "#o"},
+				"south": {"uv": [0, 11, 13, 13], "texture": "#o"},
+				"west": {"uv": [0, 11, 2, 13], "texture": "#o"},
+				"up": {"uv": [0, 9, 13, 11], "texture": "#o"},
+				"down": {"uv": [0, 11, 13, 13], "texture": "#o"}
+			}
+		},
+		{
+			"from": [2.75, 0, 14.5],
+			"to": [4, 16, 16],
+			"faces": {
+				"north": {"uv": [2, 0, 4, 16], "texture": "#o"},
+				"east": {"uv": [2, 0, 4, 16], "texture": "#o"},
+				"south": {"uv": [5, 0, 7, 16], "texture": "#o"},
+				"west": {"uv": [8, 0, 11, 16], "texture": "#o"},
+				"up": {"uv": [11, 9, 13, 12], "texture": "#o"},
+				"down": {"uv": [13, 9, 15, 12], "texture": "#o"}
+			}
+		},
+		{
+			"from": [12, 0, 14.5],
+			"to": [13.25, 16, 16],
+			"faces": {
+				"north": {"uv": [1, 0, 3, 16], "texture": "#o"},
+				"east": {"uv": [5, 0, 7, 16], "texture": "#o"},
+				"south": {"uv": [13, 0, 15, 16], "texture": "#o"},
+				"west": {"uv": [1, 0, 3, 16], "texture": "#o"},
+				"up": {"uv": [6, 6, 8, 9], "texture": "#o"},
+				"down": {"uv": [8, 5, 10, 8], "texture": "#o"}
+			}
+		}
+	],
+	"display": {
+		"ground": {
+			"scale": [0.2, 0.2, 0.2]
+		},
+		"gui": {
+			"rotation": [30, 225, 0],
+			"scale": [0.625, 0.625, 0.625]
+		},
+		"fixed": {
+			"scale": [0.5, 0.5, 0.5]
+		}
+	}
+}
\ No newline at end of file
diff --git a/src/main/resources/assets/engineersdecor/models/block/pole/straight_pole_model.json b/src/main/resources/assets/engineersdecor/models/block/pole/straight_pole_model.json
new file mode 100644
index 0000000..81cff54
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/models/block/pole/straight_pole_model.json
@@ -0,0 +1,75 @@
+{
+	"credit": "I made this with the Blockbench",
+	"parent": "block/cube",
+	"textures": {
+		"side": "engineersdecor:blocks/pole/treated_wood_pole_side_texture",
+		"particle": "engineersdecor:blocks/pole/treated_wood_pole_side_texture",
+		"top": "engineersdecor:blocks/pole/treated_wood_pole_top_texture"
+	},
+	"elements": [
+		{
+			"from": [5.75, 5.75, 0],
+			"to": [10.25, 10.25, 16],
+			"faces": {
+				"north": {"uv": [5.25, 5.25, 10.75, 10.75], "texture": "#top", "cullface": "north"},
+				"south": {"uv": [5.25, 5.25, 10.75, 10.75], "texture": "#top", "cullface": "south"}
+			}
+		},
+		{
+			"from": [5.75, 10.25, 0],
+			"to": [10.25, 10.5, 16],
+			"faces": {
+				"north": {"uv": [5.25, 10.75, 10.75, 11], "texture": "#top", "cullface": "north"},
+				"east": {"uv": [10.75, 0, 11, 16], "rotation": 90, "texture": "#side"},
+				"south": {"uv": [5.25, 5, 10.75, 5.25], "texture": "#top", "cullface": "south"},
+				"west": {"uv": [5, 0, 5.25, 16], "rotation": 90, "texture": "#side"},
+				"up": {"uv": [5.25, 0, 10.75, 16], "texture": "#side"}
+			}
+		},
+		{
+			"from": [5.75, 5.5, 0],
+			"to": [10.25, 5.75, 16],
+			"faces": {
+				"north": {"uv": [5.25, 5, 10.75, 5.25], "texture": "#top", "cullface": "north"},
+				"east": {"uv": [5, 0, 5.25, 16], "rotation": 90, "texture": "#side"},
+				"south": {"uv": [5.25, 10.75, 10.75, 11], "texture": "#top", "cullface": "south"},
+				"west": {"uv": [10.75, 0, 11, 16], "rotation": 90, "texture": "#side"},
+				"down": {"uv": [5.25, 0, 10.75, 16], "rotation": 180, "texture": "#side"}
+			}
+		},
+		{
+			"from": [10.25, 5.75, 0],
+			"to": [10.5, 10.25, 16],
+			"faces": {
+				"north": {"uv": [10.75, 5.25, 11, 10.75], "texture": "#top", "cullface": "north"},
+				"east": {"uv": [5.25, 0, 10.75, 16], "rotation": 90, "texture": "#side"},
+				"south": {"uv": [10.75, 5.25, 11, 10.75], "texture": "#top", "cullface": "south"},
+				"up": {"uv": [5, 0, 5.25, 16], "texture": "#side"},
+				"down": {"uv": [10.75, 0, 11, 16], "rotation": 180, "texture": "#side"}
+			}
+		},
+		{
+			"from": [5.5, 5.75, 0],
+			"to": [5.75, 10.25, 16],
+			"faces": {
+				"north": {"uv": [5, 5.25, 5.25, 10.75], "texture": "#top", "cullface": "north"},
+				"south": {"uv": [5, 5.25, 5.25, 10.75], "texture": "#top", "cullface": "south"},
+				"west": {"uv": [5.25, 0, 10.75, 16], "rotation": 90, "texture": "#side"},
+				"up": {"uv": [10.75, 0, 11, 16], "texture": "#side"},
+				"down": {"uv": [5, 0, 5.25, 16], "rotation": 180, "texture": "#side"}
+			}
+		}
+	],
+	"display": {
+		"ground": {
+			"scale": [0.2, 0.2, 0.2]
+		},
+		"gui": {
+			"rotation": [30, 225, 0],
+			"scale": [0.625, 0.625, 0.625]
+		},
+		"fixed": {
+			"scale": [0.5, 0.5, 0.5]
+		}
+	}
+}
\ No newline at end of file
diff --git a/src/main/resources/assets/engineersdecor/models/block/stairs/decor_inner_roof_model.json b/src/main/resources/assets/engineersdecor/models/block/stairs/decor_inner_roof_model.json
new file mode 100644
index 0000000..13d1f42
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/models/block/stairs/decor_inner_roof_model.json
@@ -0,0 +1,163 @@
+{
+	"credit": "I made this with the Blockbench",
+	"textures": {
+		"side": "engineersdecor:blocks/iestyle/ironsheet_roof",
+		"particle": "engineersdecor:blocks/iestyle/ironsheet_roof",
+		"top": "engineersdecor:blocks/iestyle/ironsheet_roof_top"
+	},
+	"elements": [
+		{
+			"from": [6, 0, 0],
+			"to": [8, 8, 8],
+			"faces": {
+				"north": {"texture": "#side", "cullface": "north"},
+				"west": {"texture": "#top"},
+				"up": {"texture": "#top"},
+				"down": {"texture": "#side", "cullface": "down"}
+			}
+		},
+		{
+			"from": [14, 0, 0],
+			"to": [16, 16, 16],
+			"faces": {
+				"north": {"texture": "#side", "cullface": "north"},
+				"east": {"texture": "#side", "cullface": "east"},
+				"south": {"texture": "#side", "cullface": "south"},
+				"west": {"texture": "#top"},
+				"up": {"texture": "#top", "cullface": "up"},
+				"down": {"texture": "#side", "cullface": "down"}
+			}
+		},
+		{
+			"from": [0, 0, 14],
+			"to": [14, 16, 16],
+			"faces": {
+				"north": {"texture": "#top"},
+				"south": {"texture": "#side", "cullface": "south"},
+				"west": {"texture": "#side", "cullface": "west"},
+				"up": {"rotation": 270, "texture": "#top", "cullface": "up"},
+				"down": {"texture": "#side", "cullface": "down"}
+			}
+		},
+		{
+			"from": [10, 0, 0],
+			"to": [12, 12, 12],
+			"faces": {
+				"north": {"texture": "#side", "cullface": "north"},
+				"west": {"texture": "#top"},
+				"up": {"texture": "#top"},
+				"down": {"texture": "#side", "cullface": "down"}
+			}
+		},
+		{
+			"from": [0, 0, 10],
+			"to": [10, 12, 12],
+			"faces": {
+				"north": {"texture": "#top"},
+				"west": {"texture": "#side", "cullface": "west"},
+				"up": {"rotation": 90, "texture": "#top"},
+				"down": {"texture": "#side", "cullface": "down"}
+			}
+		},
+		{
+			"from": [0, 0, 6],
+			"to": [6, 8, 8],
+			"faces": {
+				"north": {"texture": "#top"},
+				"west": {"texture": "#side", "cullface": "west"},
+				"up": {"texture": "#top"},
+				"down": {"texture": "#side", "cullface": "down"}
+			}
+		},
+		{
+			"from": [0, 0, 0],
+			"to": [2, 2, 2],
+			"faces": {
+				"north": {"texture": "#side", "cullface": "north"},
+				"west": {"texture": "#side", "cullface": "west"},
+				"up": {"texture": "#top"},
+				"down": {"texture": "#side", "cullface": "down"}
+			}
+		},
+		{
+			"from": [12, 0, 0],
+			"to": [14, 14, 14],
+			"faces": {
+				"north": {"texture": "#side", "cullface": "north"},
+				"west": {"texture": "#top"},
+				"up": {"texture": "#top"},
+				"down": {"texture": "#side", "cullface": "down"}
+			}
+		},
+		{
+			"from": [0, 0, 12],
+			"to": [12, 14, 14],
+			"faces": {
+				"north": {"texture": "#top"},
+				"west": {"texture": "#side", "cullface": "west"},
+				"up": {"rotation": 270, "texture": "#top"},
+				"down": {"texture": "#side", "cullface": "down"}
+			}
+		},
+		{
+			"from": [8, 0, 0],
+			"to": [10, 10, 10],
+			"faces": {
+				"north": {"texture": "#side", "cullface": "north"},
+				"west": {"texture": "#top"},
+				"up": {"texture": "#top"},
+				"down": {"texture": "#side", "cullface": "down"}
+			}
+		},
+		{
+			"from": [0, 0, 8],
+			"to": [8, 10, 10],
+			"faces": {
+				"north": {"texture": "#top"},
+				"west": {"texture": "#side", "cullface": "west"},
+				"up": {"rotation": 90, "texture": "#top"},
+				"down": {"texture": "#side", "cullface": "down"}
+			}
+		},
+		{
+			"from": [4, 0, 0],
+			"to": [6, 6, 4],
+			"faces": {
+				"north": {"texture": "#side", "cullface": "north"},
+				"west": {"texture": "#top"},
+				"up": {"texture": "#top"},
+				"down": {"texture": "#side", "cullface": "down"}
+			}
+		},
+		{
+			"from": [0, 0, 4],
+			"to": [6, 6, 6],
+			"faces": {
+				"north": {"texture": "#side"},
+				"west": {"texture": "#side", "cullface": "west"},
+				"up": {"texture": "#top"},
+				"down": {"texture": "#side", "cullface": "down"}
+			}
+		},
+		{
+			"from": [0, 0, 2],
+			"to": [4, 4, 4],
+			"faces": {
+				"north": {"texture": "#top"},
+				"west": {"texture": "#side", "cullface": "west"},
+				"up": {"texture": "#top"},
+				"down": {"texture": "#side", "cullface": "down"}
+			}
+		},
+		{
+			"from": [2, 0, 0],
+			"to": [4, 4, 2],
+			"faces": {
+				"north": {"texture": "#side", "cullface": "north"},
+				"west": {"texture": "#top"},
+				"up": {"texture": "#top"},
+				"down": {"texture": "#side", "cullface": "down"}
+			}
+		}
+	]
+}
\ No newline at end of file
diff --git a/src/main/resources/assets/engineersdecor/models/block/stairs/decor_inner_stairs_model.json b/src/main/resources/assets/engineersdecor/models/block/stairs/decor_inner_stairs_model.json
new file mode 100644
index 0000000..770a2f7
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/models/block/stairs/decor_inner_stairs_model.json
@@ -0,0 +1,45 @@
+{
+  "credit": "I made this with the Blockbench",
+  "textures": {
+    "particle": "engineersdecor:blocks/clinker_brick/clinker_brick_texture0",
+    "side"  : "engineersdecor:blocks/clinker_brick/clinker_brick_texture0"
+  },
+	"elements": [
+		{
+			"from": [0, 0, 0],
+			"to": [16, 8, 16],
+			"faces": {
+				"north": {"uv": [0, 8, 16, 16], "texture": "#side", "cullface": "north"},
+				"east": {"uv": [0, 8, 16, 16], "texture": "#side", "cullface": "east"},
+				"south": {"uv": [0, 8, 16, 16], "texture": "#side", "cullface": "south"},
+				"west": {"uv": [0, 8, 16, 16], "texture": "#side", "cullface": "west"},
+				"up": {"uv": [0, 0, 16, 16], "texture": "#side"},
+				"down": {"uv": [0, 0, 16, 16], "texture": "#side", "cullface": "down"}
+			}
+		},
+		{
+			"from": [8, 8, 0],
+			"to": [16, 16, 16],
+			"faces": {
+				"north": {"uv": [0, 0, 8, 8], "texture": "#side", "cullface": "north"},
+				"east": {"uv": [0, 0, 16, 8], "texture": "#side", "cullface": "east"},
+				"south": {"uv": [8, 0, 16, 8], "texture": "#side", "cullface": "south"},
+				"west": {"uv": [0, 0, 16, 8], "texture": "#side"},
+				"up": {"uv": [8, 0, 16, 16], "texture": "#side", "cullface": "up"},
+				"down": {"uv": [8, 0, 16, 16], "texture": "#side", "cullface": "down"}
+			}
+		},
+		{
+			"from": [0, 8, 8],
+			"to": [8, 16, 16],
+			"faces": {
+				"north": {"uv": [8, 0, 16, 8], "texture": "#side"},
+				"east": {"uv": [0, 0, 8, 8], "texture": "#side", "cullface": "east"},
+				"south": {"uv": [0, 0, 8, 8], "texture": "#side", "cullface": "south"},
+				"west": {"uv": [8, 0, 16, 8], "texture": "#side", "cullface": "west"},
+				"up": {"uv": [0, 8, 8, 16], "texture": "#side", "cullface": "up"},
+				"down": {"uv": [0, 0, 8, 8], "texture": "#side", "cullface": "down"}
+			}
+		}
+	]
+}
\ No newline at end of file
diff --git a/src/main/resources/assets/engineersdecor/models/block/stairs/decor_outer_roof_model.json b/src/main/resources/assets/engineersdecor/models/block/stairs/decor_outer_roof_model.json
new file mode 100644
index 0000000..d4c6b36
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/models/block/stairs/decor_outer_roof_model.json
@@ -0,0 +1,99 @@
+{
+	"credit": "I made this with the Blockbench",
+	"textures": {
+		"particle": "engineersdecor:blocks/iestyle/ironsheet_roof",
+		"side": "engineersdecor:blocks/iestyle/ironsheet_roof",
+		"top": "engineersdecor:blocks/iestyle/ironsheet_roof_top"
+	},
+	"elements": [
+		{
+			"from": [0, 0, 0],
+			"to": [16, 2, 16],
+			"faces": {
+				"north": {"texture": "#top", "cullface": "north"},
+				"east": {"texture": "#side", "cullface": "east"},
+				"south": {"texture": "#side", "cullface": "south"},
+				"west": {"texture": "#top", "cullface": "west"},
+				"up": {"texture": "#top"},
+				"down": {"texture": "#side", "cullface": "down"}
+			}
+		},
+		{
+			"from": [2, 2, 2],
+			"to": [16, 4, 16],
+			"faces": {
+				"north": {"texture": "#top"},
+				"east": {"texture": "#side", "cullface": "east"},
+				"south": {"texture": "#side", "cullface": "south"},
+				"west": {"texture": "#top"},
+				"up": {"texture": "#top"}
+			}
+		},
+		{
+			"from": [4, 4, 4],
+			"to": [16, 6, 16],
+			"faces": {
+				"north": {"texture": "#top"},
+				"east": {"texture": "#side", "cullface": "east"},
+				"south": {"texture": "#side", "cullface": "south"},
+				"west": {"texture": "#top"},
+				"up": {"texture": "#top"}
+			}
+		},
+		{
+			"from": [6, 6, 6],
+			"to": [16, 8, 16],
+			"faces": {
+				"north": {"texture": "#top"},
+				"east": {"texture": "#side", "cullface": "east"},
+				"south": {"texture": "#side", "cullface": "south"},
+				"west": {"texture": "#top"},
+				"up": {"texture": "#top"}
+			}
+		},
+		{
+			"from": [8, 8, 8],
+			"to": [16, 10, 16],
+			"faces": {
+				"north": {"texture": "#top"},
+				"east": {"texture": "#side", "cullface": "east"},
+				"south": {"texture": "#side", "cullface": "south"},
+				"west": {"texture": "#top"},
+				"up": {"texture": "#top"}
+			}
+		},
+		{
+			"from": [10, 10, 10],
+			"to": [16, 12, 16],
+			"faces": {
+				"north": {"texture": "#top"},
+				"east": {"texture": "#side", "cullface": "east"},
+				"south": {"texture": "#side", "cullface": "south"},
+				"west": {"texture": "#top"},
+				"up": {"texture": "#top"}
+			}
+		},
+		{
+			"from": [12, 12, 12],
+			"to": [16, 14, 16],
+			"faces": {
+				"north": {"texture": "#top"},
+				"east": {"texture": "#side", "cullface": "east"},
+				"south": {"texture": "#side", "cullface": "south"},
+				"west": {"texture": "#top"},
+				"up": {"texture": "#top"}
+			}
+		},
+		{
+			"from": [14, 14, 14],
+			"to": [16, 16, 16],
+			"faces": {
+				"north": {"texture": "#top"},
+				"east": {"texture": "#side", "cullface": "east"},
+				"south": {"texture": "#side", "cullface": "south"},
+				"west": {"texture": "#top"},
+				"up": {"texture": "#top"}
+			}
+		}
+	]
+}
\ No newline at end of file
diff --git a/src/main/resources/assets/engineersdecor/models/block/stairs/decor_outer_stairs_model.json b/src/main/resources/assets/engineersdecor/models/block/stairs/decor_outer_stairs_model.json
new file mode 100644
index 0000000..baf8fdd
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/models/block/stairs/decor_outer_stairs_model.json
@@ -0,0 +1,33 @@
+{
+  "credit": "I made this with the Blockbench",
+  "textures": {
+    "particle": "engineersdecor:blocks/clinker_brick/clinker_brick_texture0",
+    "side"  : "engineersdecor:blocks/clinker_brick/clinker_brick_texture0"
+  },
+	"elements": [
+		{
+			"from": [0, 0, 0],
+			"to": [16, 8, 16],
+			"faces": {
+				"north": {"uv": [0, 8, 16, 16], "texture": "#side", "cullface": "north"},
+				"east": {"uv": [0, 8, 16, 16], "texture": "#side", "cullface": "east"},
+				"south": {"uv": [0, 8, 16, 16], "texture": "#side", "cullface": "south"},
+				"west": {"uv": [0, 8, 16, 16], "texture": "#side", "cullface": "west"},
+				"up": {"uv": [0, 0, 16, 16], "texture": "#side"},
+				"down": {"uv": [0, 0, 16, 16], "texture": "#side", "cullface": "down"}
+			}
+		},
+		{
+			"from": [8, 8, 8],
+			"to": [16, 16, 16],
+			"faces": {
+				"north": {"uv": [0, 0, 8, 8], "texture": "#side"},
+				"east": {"uv": [0, 0, 8, 8], "texture": "#side", "cullface": "east"},
+				"south": {"uv": [8, 0, 16, 8], "texture": "#side", "cullface": "south"},
+				"west": {"uv": [8, 0, 16, 8], "texture": "#side"},
+				"up": {"uv": [8, 8, 16, 16], "texture": "#side", "cullface": "up"},
+				"down": {"uv": [8, 0, 16, 8], "texture": "#side", "cullface": "down"}
+			}
+		}
+	]
+}
\ No newline at end of file
diff --git a/src/main/resources/assets/engineersdecor/models/block/stairs/decor_straight_roof_model.json b/src/main/resources/assets/engineersdecor/models/block/stairs/decor_straight_roof_model.json
new file mode 100644
index 0000000..e29ff83
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/models/block/stairs/decor_straight_roof_model.json
@@ -0,0 +1,114 @@
+{
+	"credit": "I made this with the Blockbench",
+	"parent": "block/block",
+	"textures": {
+		"side": "engineersdecor:blocks/iestyle/ironsheet_roof",
+		"particle": "engineersdecor:blocks/iestyle/ironsheet_roof",
+		"top": "engineersdecor:blocks/iestyle/ironsheet_roof_top"
+	},
+	"elements": [
+		{
+			"from": [2, 2, 0],
+			"to": [16, 4, 16],
+			"faces": {
+				"north": {"texture": "#side", "cullface": "north"},
+				"east": {"texture": "#side", "cullface": "east"},
+				"south": {"texture": "#side", "cullface": "south"},
+				"west": {"texture": "#top"},
+				"up": {"texture": "#top"}
+			}
+		},
+		{
+			"from": [14, 14, 0],
+			"to": [16, 16, 16],
+			"faces": {
+				"north": {"texture": "#side", "cullface": "north"},
+				"east": {"texture": "#side", "cullface": "east"},
+				"south": {"texture": "#side", "cullface": "south"},
+				"west": {"texture": "#top"},
+				"up": {"texture": "#top", "cullface": "up"}
+			}
+		},
+		{
+			"from": [0, 0, 0],
+			"to": [16, 2, 16],
+			"faces": {
+				"north": {"texture": "#side", "cullface": "north"},
+				"east": {"texture": "#side", "cullface": "east"},
+				"south": {"texture": "#side", "cullface": "south"},
+				"west": {"texture": "#top", "cullface": "west"},
+				"up": {"texture": "#top"},
+				"down": {"texture": "#side", "cullface": "down"}
+			}
+		},
+		{
+			"from": [4, 4, 0],
+			"to": [16, 6, 16],
+			"faces": {
+				"north": {"texture": "#side", "cullface": "north"},
+				"east": {"texture": "#side", "cullface": "east"},
+				"south": {"texture": "#side", "cullface": "south"},
+				"west": {"texture": "#top"},
+				"up": {"texture": "#top"}
+			}
+		},
+		{
+			"from": [6, 6, 0],
+			"to": [16, 8, 16],
+			"faces": {
+				"north": {"texture": "#side", "cullface": "north"},
+				"east": {"texture": "#side", "cullface": "east"},
+				"south": {"texture": "#side", "cullface": "south"},
+				"west": {"texture": "#top"},
+				"up": {"texture": "#top"}
+			}
+		},
+		{
+			"from": [12, 12, 0],
+			"to": [16, 14, 16],
+			"faces": {
+				"north": {"texture": "#side", "cullface": "north"},
+				"east": {"texture": "#side", "cullface": "east"},
+				"south": {"texture": "#side", "cullface": "south"},
+				"west": {"texture": "#top"},
+				"up": {"texture": "#top"}
+			}
+		},
+		{
+			"from": [10, 10, 0],
+			"to": [16, 12, 16],
+			"faces": {
+				"north": {"texture": "#side", "cullface": "north"},
+				"east": {"texture": "#side", "cullface": "east"},
+				"south": {"texture": "#side", "cullface": "south"},
+				"west": {"texture": "#top"},
+				"up": {"texture": "#top"}
+			}
+		},
+		{
+			"from": [8, 8, 0],
+			"to": [16, 10, 16],
+			"faces": {
+				"north": {"texture": "#side", "cullface": "north"},
+				"east": {"texture": "#side", "cullface": "east"},
+				"south": {"texture": "#side", "cullface": "south"},
+				"west": {"texture": "#top"},
+				"up": {"texture": "#top"}
+			}
+		}
+	],
+	"display": {
+		"thirdperson_lefthand": {
+			"rotation": [75, -135, 0],
+			"translation": [0, 2.5, 0],
+			"scale": [0.375, 0.375, 0.375]
+		},
+		"gui": {
+			"rotation": [30, 135, 0],
+			"scale": [0.625, 0.625, 0.625]
+		},
+		"head": {
+			"rotation": [0, -90, 0]
+		}
+	}
+}
\ No newline at end of file
diff --git a/src/main/resources/assets/engineersdecor/models/block/stairs/decor_straight_stairs_model.json b/src/main/resources/assets/engineersdecor/models/block/stairs/decor_straight_stairs_model.json
new file mode 100644
index 0000000..3c2ba30
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/models/block/stairs/decor_straight_stairs_model.json
@@ -0,0 +1,48 @@
+{
+	"credit": "I made this with the Blockbench",
+  "parent": "block/block",
+  "textures": {
+    "particle": "engineersdecor:blocks/clinker_brick/clinker_brick_texture0",
+    "side"  : "engineersdecor:blocks/clinker_brick/clinker_brick_texture0"
+  },
+	"elements": [
+		{
+			"from": [0, 0, 0],
+			"to": [16, 8, 16],
+			"faces": {
+				"north": {"uv": [0, 8, 16, 16], "texture": "#side", "cullface": "north"},
+				"east": {"uv": [0, 8, 16, 16], "texture": "#side", "cullface": "east"},
+				"south": {"uv": [0, 8, 16, 16], "texture": "#side", "cullface": "south"},
+				"west": {"uv": [0, 8, 16, 16], "texture": "#side", "cullface": "west"},
+				"up": {"uv": [0, 0, 16, 16], "texture": "#side"},
+				"down": {"uv": [0, 0, 16, 16], "texture": "#side", "cullface": "down"}
+			}
+		},
+		{
+			"from": [8, 8, 0],
+			"to": [16, 16, 16],
+			"faces": {
+				"north": {"uv": [0, 0, 8, 8], "texture": "#side", "cullface": "north"},
+				"east": {"uv": [0, 0, 16, 8], "texture": "#side", "cullface": "east"},
+				"south": {"uv": [8, 0, 16, 8], "texture": "#side", "cullface": "south"},
+				"west": {"uv": [0, 0, 16, 8], "texture": "#side"},
+				"up": {"uv": [8, 0, 16, 16], "texture": "#side", "cullface": "up"},
+				"down": {"uv": [8, 0, 16, 16], "texture": "#side", "cullface": "down"}
+			}
+		}
+	],
+	"display": {
+		"thirdperson_lefthand": {
+			"rotation": [75, -135, 0],
+			"translation": [0, 2.5, 0],
+			"scale": [0.375, 0.375, 0.375]
+		},
+		"gui": {
+			"rotation": [30, 135, 0],
+			"scale": [0.625, 0.625, 0.625]
+		},
+		"head": {
+			"rotation": [0, -90, 0]
+		}
+	}
+}
\ No newline at end of file
diff --git a/src/main/resources/assets/engineersdecor/models/block/wall/concrete_wall_default.json b/src/main/resources/assets/engineersdecor/models/block/wall/concrete_wall_default.json
new file mode 100644
index 0000000..3e07444
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/models/block/wall/concrete_wall_default.json
@@ -0,0 +1,9 @@
+{
+	"textures": {
+    "wall": "engineersdecor:blocks/concrete/rebar_concrete_texture0",
+    "particle": "engineersdecor:blocks/concrete/rebar_concrete_texture0"
+	},
+	"elements": [{
+    "from": [7.9, 7.9, 7.9], "to": [8, 8, 8], "faces": { "down": {"texture": "#wall"} }
+  }]
+}
diff --git a/src/main/resources/assets/engineersdecor/models/block/wall/concrete_wall_inventory.json b/src/main/resources/assets/engineersdecor/models/block/wall/concrete_wall_inventory.json
new file mode 100644
index 0000000..dea042b
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/models/block/wall/concrete_wall_inventory.json
@@ -0,0 +1,164 @@
+{
+	"credit": "I made this with the Blockbench",
+	"parent": "block/block",
+	"ambientocclusion": false,
+	"textures": {
+		"wall": "engineersdecor:blocks/concrete/rebar_concrete_texture0",
+		"particle": "engineersdecor:blocks/concrete/rebar_concrete_texture0"
+	},
+	"elements": [
+		{
+			"name": "Center post",
+			"from": [4, 0, 4],
+			"to": [12, 16, 12],
+			"faces": {
+				"north": {"uv": [4, 0, 12, 16], "texture": "#wall"},
+				"east": {"uv": [4, 0, 12, 16], "texture": "#wall"},
+				"south": {"uv": [4, 0, 12, 16], "texture": "#wall"},
+				"west": {"uv": [4, 0, 12, 16], "texture": "#wall"},
+				"up": {"uv": [4, 4, 12, 12], "texture": "#wall"},
+				"down": {"uv": [4, 4, 12, 12], "texture": "#wall", "cullface": "down"}
+			}
+		},
+		{
+			"name": "Full wall",
+			"from": [5, 0, 12],
+			"to": [11, 16, 16],
+			"faces": {
+				"north": {"uv": [5, 1, 11, 16], "texture": "#wall", "cullface": "north"},
+				"east": {"uv": [0, 1, 4, 16], "texture": "#wall"},
+				"south": {"uv": [5, 1, 11, 16], "texture": "#wall", "cullface": "south"},
+				"west": {"uv": [12, 1, 16, 16], "texture": "#wall"},
+				"up": {"uv": [5, 12, 11, 16], "texture": "#wall"},
+				"down": {"uv": [5, 0, 11, 4], "texture": "#wall", "cullface": "down"}
+			}
+		},
+		{
+			"name": "Full wall",
+			"from": [11, 0, 12],
+			"to": [12, 1, 16],
+			"faces": {
+				"north": {"uv": [4, 15, 5, 16], "texture": "#wall", "cullface": "north"},
+				"east": {"uv": [0, 15, 4, 16], "texture": "#wall"},
+				"south": {"uv": [11, 15, 12, 16], "texture": "#wall", "cullface": "south"},
+				"west": {"uv": [12, 15, 16, 16], "texture": "#wall"},
+				"up": {"uv": [11, 12, 12, 16], "texture": "#wall"},
+				"down": {"uv": [11, 0, 12, 4], "texture": "#wall", "cullface": "down"}
+			}
+		},
+		{
+			"name": "Full wall",
+			"from": [5, 0, 0],
+			"to": [11, 16, 4],
+			"faces": {
+				"north": {"uv": [5, 1, 11, 16], "texture": "#wall", "cullface": "north"},
+				"east": {"uv": [12, 1, 16, 16], "texture": "#wall"},
+				"south": {"uv": [5, 1, 11, 16], "texture": "#wall", "cullface": "south"},
+				"west": {"uv": [0, 1, 4, 16], "texture": "#wall"},
+				"up": {"uv": [5, 0, 11, 4], "texture": "#wall"},
+				"down": {"uv": [5, 12, 11, 16], "texture": "#wall", "cullface": "down"}
+			}
+		},
+		{
+			"name": "Full wall",
+			"from": [11, 0, 0],
+			"to": [12, 1, 4],
+			"faces": {
+				"north": {"uv": [4, 15, 5, 16], "texture": "#wall", "cullface": "north"},
+				"east": {"uv": [12, 15, 16, 16], "texture": "#wall"},
+				"south": {"uv": [11, 15, 12, 16], "texture": "#wall", "cullface": "south"},
+				"west": {"uv": [0, 15, 4, 16], "texture": "#wall"},
+				"up": {"uv": [11, 0, 12, 4], "texture": "#wall"},
+				"down": {"uv": [11, 12, 12, 16], "texture": "#wall", "cullface": "down"}
+			}
+		},
+		{
+			"name": "Full wall",
+			"from": [11, 14, 12],
+			"to": [12, 16, 16],
+			"faces": {
+				"north": {"uv": [4, 0, 5, 2], "texture": "#wall", "cullface": "north"},
+				"east": {"uv": [0, 0, 4, 2], "texture": "#wall"},
+				"south": {"uv": [11, 0, 12, 2], "texture": "#wall", "cullface": "south"},
+				"west": {"uv": [12, 0, 16, 2], "texture": "#wall"},
+				"up": {"uv": [11, 12, 12, 16], "texture": "#wall"},
+				"down": {"uv": [11, 0, 12, 4], "texture": "#wall", "cullface": "down"}
+			}
+		},
+		{
+			"name": "Full wall",
+			"from": [11, 14, 0],
+			"to": [12, 16, 4],
+			"faces": {
+				"north": {"uv": [4, 0, 5, 2], "texture": "#wall", "cullface": "north"},
+				"east": {"uv": [12, 0, 16, 2], "texture": "#wall"},
+				"south": {"uv": [11, 0, 12, 2], "texture": "#wall", "cullface": "south"},
+				"west": {"uv": [0, 0, 4, 2], "texture": "#wall"},
+				"up": {"uv": [11, 0, 12, 4], "texture": "#wall"},
+				"down": {"uv": [11, 12, 12, 16], "texture": "#wall", "cullface": "down"}
+			}
+		},
+		{
+			"name": "Full wall",
+			"from": [4, 0, 12],
+			"to": [5, 1, 16],
+			"faces": {
+				"north": {"uv": [11, 15, 12, 16], "texture": "#wall", "cullface": "north"},
+				"east": {"uv": [0, 15, 4, 16], "texture": "#wall"},
+				"south": {"uv": [4, 15, 5, 16], "texture": "#wall", "cullface": "south"},
+				"west": {"uv": [12, 15, 16, 16], "texture": "#wall"},
+				"up": {"uv": [4, 12, 5, 16], "texture": "#wall"},
+				"down": {"uv": [4, 0, 5, 4], "texture": "#wall", "cullface": "down"}
+			}
+		},
+		{
+			"name": "Full wall",
+			"from": [4, 0, 0],
+			"to": [5, 1, 4],
+			"faces": {
+				"north": {"uv": [11, 15, 12, 16], "texture": "#wall", "cullface": "north"},
+				"east": {"uv": [12, 15, 16, 16], "texture": "#wall"},
+				"south": {"uv": [4, 15, 5, 16], "texture": "#wall", "cullface": "south"},
+				"west": {"uv": [0, 15, 4, 16], "texture": "#wall"},
+				"up": {"uv": [4, 0, 5, 4], "texture": "#wall"},
+				"down": {"uv": [4, 12, 5, 16], "texture": "#wall", "cullface": "down"}
+			}
+		},
+		{
+			"name": "Full wall",
+			"from": [4, 14, 0],
+			"to": [5, 16, 4],
+			"faces": {
+				"north": {"uv": [11, 0, 12, 2], "texture": "#wall", "cullface": "north"},
+				"east": {"uv": [12, 0, 16, 2], "texture": "#wall"},
+				"south": {"uv": [4, 0, 5, 2], "texture": "#wall", "cullface": "south"},
+				"west": {"uv": [0, 0, 4, 2], "texture": "#wall"},
+				"up": {"uv": [4, 0, 5, 4], "texture": "#wall"},
+				"down": {"uv": [4, 12, 5, 16], "texture": "#wall", "cullface": "down"}
+			}
+		},
+		{
+			"name": "Full wall",
+			"from": [4, 14, 12],
+			"to": [5, 16, 16],
+			"faces": {
+				"north": {"uv": [11, 0, 12, 2], "texture": "#wall", "cullface": "north"},
+				"east": {"uv": [0, 0, 4, 2], "texture": "#wall"},
+				"south": {"uv": [4, 0, 5, 2], "texture": "#wall", "cullface": "south"},
+				"west": {"uv": [12, 0, 16, 2], "texture": "#wall"},
+				"up": {"uv": [4, 12, 5, 16], "texture": "#wall"},
+				"down": {"uv": [4, 0, 5, 4], "texture": "#wall", "cullface": "down"}
+			}
+		}
+	],
+	"display": {
+		"gui": {
+			"rotation": [30, 135, 0],
+			"scale": [0.625, 0.625, 0.625]
+		},
+		"fixed": {
+			"rotation": [0, 90, 0],
+			"scale": [0.5, 0.5, 0.5]
+		}
+	}
+}
\ No newline at end of file
diff --git a/src/main/resources/assets/engineersdecor/models/block/wall/concrete_wall_post.json b/src/main/resources/assets/engineersdecor/models/block/wall/concrete_wall_post.json
new file mode 100644
index 0000000..d88fb8a
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/models/block/wall/concrete_wall_post.json
@@ -0,0 +1,22 @@
+{
+	"credit": "I made this with the Blockbench",
+	"textures": {
+    "wall": "engineersdecor:blocks/concrete/rebar_concrete_texture0",
+    "particle": "engineersdecor:blocks/concrete/rebar_concrete_texture0"
+	},
+	"elements": [
+		{
+			"name": "Center post",
+			"from": [4, 0, 4],
+			"to": [12, 16, 12],
+			"faces": {
+				"north": {"uv": [4, 0, 12, 16], "texture": "#wall"},
+				"east": {"uv": [4, 0, 12, 16], "texture": "#wall"},
+				"south": {"uv": [4, 0, 12, 16], "texture": "#wall"},
+				"west": {"uv": [4, 0, 12, 16], "texture": "#wall"},
+				"up": {"uv": [4, 4, 12, 12], "texture": "#wall", "cullface": "up"},
+				"down": {"uv": [4, 4, 12, 12], "texture": "#wall", "cullface": "down"}
+			}
+		}
+	]
+}
\ No newline at end of file
diff --git a/src/main/resources/assets/engineersdecor/models/block/wall/concrete_wall_side.json b/src/main/resources/assets/engineersdecor/models/block/wall/concrete_wall_side.json
new file mode 100644
index 0000000..de382a6
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/models/block/wall/concrete_wall_side.json
@@ -0,0 +1,65 @@
+{
+	"credit": "I made this with the Blockbench",
+	"textures": {
+		"wall": "engineersdecor:blocks/concrete/rebar_concrete_texture0",
+		"particle": "engineersdecor:blocks/concrete/rebar_concrete_texture0"
+	},
+	"elements": [
+		{
+			"name": "wall",
+			"from": [5, 0, 0],
+			"to": [11, 16, 8],
+			"faces": {
+				"north": {"uv": [5, 0, 11, 16], "texture": "#wall", "cullface": "north"},
+				"east": {"uv": [8, 0, 16, 16], "texture": "#wall"},
+				"west": {"uv": [0, 0, 8, 16], "texture": "#wall"},
+				"up": {"uv": [5, 0, 11, 8], "texture": "#wall"},
+				"down": {"uv": [5, 8, 11, 16], "texture": "#wall"}
+			}
+		},
+		{
+			"name": "wall",
+			"from": [11, 14, 0],
+			"to": [11.875, 16, 8],
+			"faces": {
+				"north": {"uv": [4.25, 0, 5, 1.875], "texture": "#wall", "cullface": "north"},
+				"east": {"uv": [8, 0, 16, 1.875], "texture": "#wall"},
+				"up": {"uv": [11, 0, 11.75, 8], "texture": "#wall"},
+				"down": {"uv": [11, 8, 11.75, 16], "texture": "#wall", "cullface": "down"}
+			}
+		},
+		{
+			"name": "wall",
+			"from": [11, 0, 0],
+			"to": [11.875, 1, 8],
+			"faces": {
+				"north": {"uv": [4.125, 15, 5, 16], "texture": "#wall", "cullface": "north"},
+				"east": {"uv": [8, 15, 16, 16], "texture": "#wall"},
+				"up": {"uv": [11, 0, 11.875, 8], "texture": "#wall"},
+				"down": {"uv": [11, 8, 11.875, 16], "texture": "#wall", "cullface": "down"}
+			}
+		},
+		{
+			"name": "wall",
+			"from": [4.125, 14, 0],
+			"to": [5, 16, 8],
+			"faces": {
+				"north": {"uv": [11, 0, 11.75, 1.875], "texture": "#wall", "cullface": "north"},
+				"west": {"uv": [0, 0, 8, 1.875], "texture": "#wall"},
+				"up": {"uv": [4.25, 0, 5, 8], "texture": "#wall"},
+				"down": {"uv": [4.25, 8, 5, 16], "texture": "#wall", "cullface": "down"}
+			}
+		},
+		{
+			"name": "wall",
+			"from": [4.125, 0, 0],
+			"to": [5, 1, 8],
+			"faces": {
+				"north": {"uv": [10.875, 15, 11.75, 16], "texture": "#wall", "cullface": "north"},
+				"west": {"uv": [0, 15, 8, 16], "texture": "#wall"},
+				"up": {"uv": [4.25, 0, 5.125, 8], "texture": "#wall"},
+				"down": {"uv": [4.25, 8, 5.125, 16], "texture": "#wall", "cullface": "down"}
+			}
+		}
+	]
+}
\ No newline at end of file
diff --git a/src/main/resources/assets/engineersdecor/recipes/_constants.json b/src/main/resources/assets/engineersdecor/recipes/_constants.json
new file mode 100644
index 0000000..fb9df22
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/recipes/_constants.json
@@ -0,0 +1,138 @@
+[
+  {
+    "ingredient": {
+      "type": "forge:ore_dict",
+      "ore": "itemSlag"
+    },
+    "name": "itemSlag"
+  },
+  {
+    "ingredient": {
+      "type": "forge:ore_dict",
+      "ore": "plankTreatedWood"
+    },
+    "name": "plankTreatedWood"
+  },
+  {
+    "ingredient": {
+      "type": "forge:ore_dict",
+      "ore": "slabTreatedWood"
+    },
+    "name": "slabTreatedWood"
+  },
+  {
+    "ingredient": {
+      "type": "forge:ore_dict",
+      "ore": "stickTreatedWood"
+    },
+    "name": "stickTreatedWood"
+  },
+
+  {
+    "ingredient": {
+      "type": "forge:ore_dict",
+      "ore": "plateSteel"
+    },
+    "name": "plateSteel"
+  },
+  {
+    "ingredient": {
+      "type": "forge:ore_dict",
+      "ore": "stickSteel"
+    },
+    "name": "stickSteel"
+  },
+
+  {
+    "ingredient": {
+      "type": "forge:ore_dict",
+      "ore": "stickIron"
+    },
+    "name": "stickIron"
+  },
+
+  {
+    "ingredient": {
+      "type": "forge:ore_dict",
+      "ore": "plankWood"
+    },
+    "name": "plankWood"
+  },
+  {
+    "ingredient": {
+      "type": "forge:ore_dict",
+      "ore": "stickWood"
+    },
+    "name": "stickWood"
+  },
+
+  {
+    "ingredient": {
+      "type": "forge:ore_dict",
+      "ore": "sand"
+    },
+    "name": "sand"
+  },
+  {
+    "ingredient": {
+      "type": "forge:ore_dict",
+      "ore": "sandstone"
+    },
+    "name": "sandstone"
+  },
+  {
+    "ingredient": {
+      "type": "forge:ore_dict",
+      "ore": "bricksStone"
+    },
+    "name": "bricksStone"
+  },
+  {
+    "ingredient": {
+      "type": "forge:ore_dict",
+      "ore": "ingotBrick"
+    },
+    "name": "ingotBrick"
+  },
+  {
+    "ingredient": {
+      "type": "forge:ore_dict",
+      "ore": "ingotBrickNether"
+    },
+    "name": "ingotBrickNether"
+  },
+  {
+    "ingredient": [
+      {
+        "type": "forge:ore_dict",
+        "ore": "ingotBrick"
+      },
+      {
+        "type": "forge:ore_dict",
+        "ore": "ingotBrickNether"
+      }
+    ],
+    "name": "ingotAnyBrick"
+  },
+  {
+    "ingredient": [
+      {
+        "type": "forge:ore_dict",
+        "ore": "stickIron"
+      },
+      {
+        "type": "forge:ore_dict",
+        "ore": "stickSteel"
+      }
+    ],
+    "name": "stickFerroMetal"
+  },
+  {
+    "ingredient": {
+      "item": "immersiveengineering:stone_decoration",
+      "data": 5
+    },
+    "name": "blockConcreteIe"
+  }
+
+]
\ No newline at end of file
diff --git a/src/main/resources/assets/engineersdecor/recipes/_factories.json b/src/main/resources/assets/engineersdecor/recipes/_factories.json
new file mode 100644
index 0000000..034a0ee
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/recipes/_factories.json
@@ -0,0 +1,5 @@
+{
+  "conditions": {
+    "grc": "wile.engineersdecor.detail.RecipeCondModSpecific"
+  }
+}
diff --git a/src/main/resources/assets/engineersdecor/recipes/clinker_brick_recipe.json b/src/main/resources/assets/engineersdecor/recipes/clinker_brick_recipe.json
new file mode 100644
index 0000000..de65ae4
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/recipes/clinker_brick_recipe.json
@@ -0,0 +1,28 @@
+{
+  "conditions": [
+    {
+      "type": "engineersdecor:grc",
+      "result": "engineersdecor:clinker_brick_block"
+    }
+  ],
+  "type": "minecraft:crafting_shaped",
+  "pattern": [
+    "BBB",
+    "BNB",
+    "BBB"
+  ],
+  "key": {
+    "B": {
+      "item": "#ingotAnyBrick",
+      "data": 0
+    },
+    "N": {
+      "item": "minecraft:brick_block",
+      "data": 0
+    }
+  },
+  "result": {
+    "item": "engineersdecor:clinker_brick_block",
+    "count": 4
+  }
+}
diff --git a/src/main/resources/assets/engineersdecor/recipes/clinker_brick_stairs_recipe.json b/src/main/resources/assets/engineersdecor/recipes/clinker_brick_stairs_recipe.json
new file mode 100644
index 0000000..f94e31a
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/recipes/clinker_brick_stairs_recipe.json
@@ -0,0 +1,24 @@
+{
+  "conditions": [
+    {
+      "type": "engineersdecor:grc",
+      "result": "engineersdecor:clinker_brick_stairs"
+    }
+  ],
+  "type": "minecraft:crafting_shaped",
+  "pattern": [
+    "C  ",
+    "CC ",
+    "CCC"
+  ],
+  "key": {
+    "C": {
+      "item": "engineersdecor:clinker_brick_block",
+      "data": 0
+    }
+  },
+  "result": {
+    "item": "engineersdecor:clinker_brick_stairs",
+    "count": 9
+  }
+}
diff --git a/src/main/resources/assets/engineersdecor/recipes/clinker_brick_stairs_recipe_decompose.json b/src/main/resources/assets/engineersdecor/recipes/clinker_brick_stairs_recipe_decompose.json
new file mode 100644
index 0000000..afb32ae
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/recipes/clinker_brick_stairs_recipe_decompose.json
@@ -0,0 +1,23 @@
+{
+  "conditions": [
+    {
+      "type": "engineersdecor:grc",
+      "result": "engineersdecor:clinker_brick_block"
+    }
+  ],
+  "type": "minecraft:crafting_shaped",
+  "pattern": [
+    "SS",
+    "SS"
+  ],
+  "key": {
+    "S": {
+      "item": "engineersdecor:clinker_brick_stairs",
+      "data": 0
+    }
+  },
+  "result": {
+    "item": "engineersdecor:clinker_brick_block",
+    "count": 3
+  }
+}
diff --git a/src/main/resources/assets/engineersdecor/recipes/concrete_wall_recipe_with_ie_installed.json b/src/main/resources/assets/engineersdecor/recipes/concrete_wall_recipe_with_ie_installed.json
new file mode 100644
index 0000000..87a9306
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/recipes/concrete_wall_recipe_with_ie_installed.json
@@ -0,0 +1,25 @@
+{
+  "conditions": [
+    {
+      "type": "engineersdecor:grc",
+      "result": "engineersdecor:concrete_wall",
+      "required": ["immersiveengineering:stone_decoration"]
+    }
+  ],
+  "type": "minecraft:crafting_shaped",
+  "pattern": [
+    "   ",
+    "CCC",
+    "CCC"
+  ],
+  "key": {
+    "C": {
+      "item": "#blockConcreteIe",
+      "data": 0
+    }
+  },
+  "result": {
+    "item": "engineersdecor:concrete_wall",
+    "count": 6
+  }
+}
diff --git a/src/main/resources/assets/engineersdecor/recipes/metal_rung_ladder_recipe.json b/src/main/resources/assets/engineersdecor/recipes/metal_rung_ladder_recipe.json
new file mode 100644
index 0000000..9fdde71
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/recipes/metal_rung_ladder_recipe.json
@@ -0,0 +1,25 @@
+{
+  "conditions": [
+    {
+      "type": "engineersdecor:grc",
+      "result": "engineersdecor:metal_rung_ladder",
+      "required": ["immersiveengineering:material"]
+    }
+  ],
+  "type": "minecraft:crafting_shaped",
+  "pattern": [
+    "S S",
+    "SSS",
+    "   "
+  ],
+  "key": {
+    "S": {
+      "item": "#stickFerroMetal",
+      "data": 0
+    }
+  },
+  "result": {
+    "item": "engineersdecor:metal_rung_ladder",
+    "count": 4
+  }
+}
diff --git a/src/main/resources/assets/engineersdecor/recipes/metal_rung_steps_recipe.json b/src/main/resources/assets/engineersdecor/recipes/metal_rung_steps_recipe.json
new file mode 100644
index 0000000..d8f06c4
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/recipes/metal_rung_steps_recipe.json
@@ -0,0 +1,25 @@
+{
+  "conditions": [
+    {
+      "type": "engineersdecor:grc",
+      "result": "engineersdecor:metal_rung_steps",
+      "required": ["immersiveengineering:material"]
+    }
+  ],
+  "type": "minecraft:crafting_shaped",
+  "pattern": [
+    " SS",
+    "SS ",
+    " SS"
+  ],
+  "key": {
+    "S": {
+      "item": "#stickFerroMetal",
+      "data": 0
+    }
+  },
+  "result": {
+    "item": "engineersdecor:metal_rung_steps",
+    "count": 4
+  }
+}
diff --git a/src/main/resources/assets/engineersdecor/recipes/rebar_concrete_recipe.json b/src/main/resources/assets/engineersdecor/recipes/rebar_concrete_recipe.json
new file mode 100644
index 0000000..f3cf998
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/recipes/rebar_concrete_recipe.json
@@ -0,0 +1,29 @@
+{
+  "conditions": [
+    {
+      "type": "engineersdecor:grc",
+      "result": "engineersdecor:rebar_concrete",
+      "required": ["immersiveengineering:stone_decoration"]
+    }
+  ],
+  "type": "minecraft:crafting_shaped",
+  "pattern": [
+    "SCS",
+    "CSC",
+    "SCS"
+  ],
+  "key": {
+    "C": {
+      "item": "#blockConcreteIe",
+      "data": 0
+    },
+    "S": {
+      "item": "#stickSteel",
+      "data": 0
+    }
+  },
+  "result": {
+    "item": "engineersdecor:rebar_concrete",
+    "count": 4
+  }
+}
diff --git a/src/main/resources/assets/engineersdecor/recipes/rebar_concrete_stairs_recipe.json b/src/main/resources/assets/engineersdecor/recipes/rebar_concrete_stairs_recipe.json
new file mode 100644
index 0000000..532ed8b
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/recipes/rebar_concrete_stairs_recipe.json
@@ -0,0 +1,24 @@
+{
+  "conditions": [
+    {
+      "type": "engineersdecor:grc",
+      "result": "engineersdecor:rebar_concrete_stairs"
+    }
+  ],
+  "type": "minecraft:crafting_shaped",
+  "pattern": [
+    "C  ",
+    "CC ",
+    "CCC"
+  ],
+  "key": {
+    "C": {
+      "item": "engineersdecor:rebar_concrete",
+      "data": 0
+    }
+  },
+  "result": {
+    "item": "engineersdecor:rebar_concrete_stairs",
+    "count": 9
+  }
+}
diff --git a/src/main/resources/assets/engineersdecor/recipes/rebar_concrete_wall_recipe.json b/src/main/resources/assets/engineersdecor/recipes/rebar_concrete_wall_recipe.json
new file mode 100644
index 0000000..4ec19fa
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/recipes/rebar_concrete_wall_recipe.json
@@ -0,0 +1,24 @@
+{
+  "conditions": [
+    {
+      "type": "engineersdecor:grc",
+      "result": "engineersdecor:rebar_concrete_wall"
+    }
+  ],
+  "type": "minecraft:crafting_shaped",
+  "pattern": [
+    "   ",
+    "CCC",
+    "CCC"
+  ],
+  "key": {
+    "C": {
+      "item": "engineersdecor:rebar_concrete",
+      "data": 0
+    }
+  },
+  "result": {
+    "item": "engineersdecor:rebar_concrete_wall",
+    "count": 6
+  }
+}
diff --git a/src/main/resources/assets/engineersdecor/recipes/slag_brick_recipe_with_slag.json b/src/main/resources/assets/engineersdecor/recipes/slag_brick_recipe_with_slag.json
new file mode 100644
index 0000000..d1239c2
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/recipes/slag_brick_recipe_with_slag.json
@@ -0,0 +1,29 @@
+{
+  "conditions": [
+    {
+      "type": "engineersdecor:grc",
+      "result": "engineersdecor:clinker_brick_block",
+      "required": ["immersiveengineering:material"]
+    }
+  ],
+  "type": "minecraft:crafting_shaped",
+  "pattern": [
+    "BBB",
+    "BSB",
+    "BBB"
+  ],
+  "key": {
+    "B": {
+      "item": "#ingotBrick",
+      "data": 0
+    },
+    "S": {
+      "item": "#itemSlag",
+      "data": 0
+    }
+  },
+  "result": {
+    "item": "engineersdecor:slag_brick_block",
+    "count": 4
+  }
+}
diff --git a/src/main/resources/assets/engineersdecor/recipes/slag_brick_recipe_without_slag.json b/src/main/resources/assets/engineersdecor/recipes/slag_brick_recipe_without_slag.json
new file mode 100644
index 0000000..d9b9e9d
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/recipes/slag_brick_recipe_without_slag.json
@@ -0,0 +1,29 @@
+{
+  "conditions": [
+    {
+      "type": "engineersdecor:grc",
+      "result": "engineersdecor:clinker_brick_block",
+      "missing": ["immersiveengineering:material"]
+    }
+  ],
+  "type": "minecraft:crafting_shaped",
+  "pattern": [
+    "BBB",
+    "BSB",
+    "BBB"
+  ],
+  "key": {
+    "B": {
+      "item": "#ingotBrick",
+      "data": 0
+    },
+    "S": {
+      "item": "minecraft:nether_brick",
+      "data": 0
+    }
+  },
+  "result": {
+    "item": "engineersdecor:slag_brick_block",
+    "count": 4
+  }
+}
diff --git a/src/main/resources/assets/engineersdecor/recipes/slag_brick_stairs_recipe.json b/src/main/resources/assets/engineersdecor/recipes/slag_brick_stairs_recipe.json
new file mode 100644
index 0000000..5b8e69e
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/recipes/slag_brick_stairs_recipe.json
@@ -0,0 +1,24 @@
+{
+  "conditions": [
+    {
+      "type": "engineersdecor:grc",
+      "result": "engineersdecor:slag_brick_stairs"
+    }
+  ],
+  "type": "minecraft:crafting_shaped",
+  "pattern": [
+    "C  ",
+    "CC ",
+    "CCC"
+  ],
+  "key": {
+    "C": {
+      "item": "engineersdecor:slag_brick_block",
+      "data": 0
+    }
+  },
+  "result": {
+    "item": "engineersdecor:slag_brick_stairs",
+    "count": 9
+  }
+}
diff --git a/src/main/resources/assets/engineersdecor/recipes/treated_wood_ladder_recipe.json b/src/main/resources/assets/engineersdecor/recipes/treated_wood_ladder_recipe.json
new file mode 100644
index 0000000..cd81662
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/recipes/treated_wood_ladder_recipe.json
@@ -0,0 +1,25 @@
+{
+  "conditions": [
+    {
+      "type": "engineersdecor:grc",
+      "result": "engineersdecor:treated_wood_ladder",
+      "required": ["immersiveengineering:material"]
+    }
+  ],
+  "type": "minecraft:crafting_shaped",
+  "pattern": [
+    "S S",
+    "SSS",
+    "S S"
+  ],
+  "key": {
+    "S": {
+      "item": "#stickTreatedWood",
+      "data": 0
+    }
+  },
+  "result": {
+    "item": "engineersdecor:treated_wood_ladder",
+    "count": 4
+  }
+}
diff --git a/src/main/resources/assets/engineersdecor/recipes/treated_wood_pole_recipe.json b/src/main/resources/assets/engineersdecor/recipes/treated_wood_pole_recipe.json
new file mode 100644
index 0000000..62330e4
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/recipes/treated_wood_pole_recipe.json
@@ -0,0 +1,29 @@
+{
+  "conditions": [
+    {
+      "type": "engineersdecor:grc",
+      "result": "engineersdecor:treated_wood_pole",
+      "required": ["immersiveengineering:material"]
+    }
+  ],
+  "type": "minecraft:crafting_shaped",
+  "pattern": [
+    " S ",
+    " W ",
+    " W "
+  ],
+  "key": {
+    "W": {
+      "item": "#plankTreatedWood",
+      "data": 0
+    },
+    "S": {
+      "item": "#slabTreatedWood",
+      "data": 0
+    }
+  },
+  "result": {
+    "item": "engineersdecor:treated_wood_pole",
+    "count": 6
+  }
+}
diff --git a/src/main/resources/assets/engineersdecor/recipes/treated_wood_table_recipe.json b/src/main/resources/assets/engineersdecor/recipes/treated_wood_table_recipe.json
new file mode 100644
index 0000000..ad942dd
--- /dev/null
+++ b/src/main/resources/assets/engineersdecor/recipes/treated_wood_table_recipe.json
@@ -0,0 +1,29 @@
+{
+  "conditions": [
+    {
+      "type": "engineersdecor:grc",
+      "result": "engineersdecor:treated_wood_table",
+      "required": ["immersiveengineering:material"]
+    }
+  ],
+  "type": "minecraft:crafting_shaped",
+  "pattern": [
+    "WWW",
+    "S S",
+    "S S"
+  ],
+  "key": {
+    "W": {
+      "item": "#slabTreatedWood",
+      "data": 0
+    },
+    "S": {
+      "item": "engineersdecor:treated_wood_pole",
+      "data": 0
+    }
+  },
+  "result": {
+    "item": "engineersdecor:treated_wood_table",
+    "count": 1
+  }
+}
diff --git a/src/main/resources/assets/engineersdecor/textures/blocks/clinker_brick/clinker_brick_texture0.png b/src/main/resources/assets/engineersdecor/textures/blocks/clinker_brick/clinker_brick_texture0.png
new file mode 100644
index 0000000..5a06481
Binary files /dev/null and b/src/main/resources/assets/engineersdecor/textures/blocks/clinker_brick/clinker_brick_texture0.png differ
diff --git a/src/main/resources/assets/engineersdecor/textures/blocks/clinker_brick/clinker_brick_texture1.png b/src/main/resources/assets/engineersdecor/textures/blocks/clinker_brick/clinker_brick_texture1.png
new file mode 100644
index 0000000..1d536e6
Binary files /dev/null and b/src/main/resources/assets/engineersdecor/textures/blocks/clinker_brick/clinker_brick_texture1.png differ
diff --git a/src/main/resources/assets/engineersdecor/textures/blocks/clinker_brick/clinker_brick_texture2.png b/src/main/resources/assets/engineersdecor/textures/blocks/clinker_brick/clinker_brick_texture2.png
new file mode 100644
index 0000000..04b7f03
Binary files /dev/null and b/src/main/resources/assets/engineersdecor/textures/blocks/clinker_brick/clinker_brick_texture2.png differ
diff --git a/src/main/resources/assets/engineersdecor/textures/blocks/clinker_brick/clinker_brick_texture3.png b/src/main/resources/assets/engineersdecor/textures/blocks/clinker_brick/clinker_brick_texture3.png
new file mode 100644
index 0000000..cb6f0f7
Binary files /dev/null and b/src/main/resources/assets/engineersdecor/textures/blocks/clinker_brick/clinker_brick_texture3.png differ
diff --git a/src/main/resources/assets/engineersdecor/textures/blocks/clinker_brick/clinker_brick_texture4.png b/src/main/resources/assets/engineersdecor/textures/blocks/clinker_brick/clinker_brick_texture4.png
new file mode 100644
index 0000000..77541ae
Binary files /dev/null and b/src/main/resources/assets/engineersdecor/textures/blocks/clinker_brick/clinker_brick_texture4.png differ
diff --git a/src/main/resources/assets/engineersdecor/textures/blocks/clinker_brick/clinker_brick_texture5.png b/src/main/resources/assets/engineersdecor/textures/blocks/clinker_brick/clinker_brick_texture5.png
new file mode 100644
index 0000000..a73f43f
Binary files /dev/null and b/src/main/resources/assets/engineersdecor/textures/blocks/clinker_brick/clinker_brick_texture5.png differ
diff --git a/src/main/resources/assets/engineersdecor/textures/blocks/clinker_brick/clinker_brick_texture6.png b/src/main/resources/assets/engineersdecor/textures/blocks/clinker_brick/clinker_brick_texture6.png
new file mode 100644
index 0000000..6002fdf
Binary files /dev/null and b/src/main/resources/assets/engineersdecor/textures/blocks/clinker_brick/clinker_brick_texture6.png differ
diff --git a/src/main/resources/assets/engineersdecor/textures/blocks/clinker_brick/clinker_brick_texture7.png b/src/main/resources/assets/engineersdecor/textures/blocks/clinker_brick/clinker_brick_texture7.png
new file mode 100644
index 0000000..5b39955
Binary files /dev/null and b/src/main/resources/assets/engineersdecor/textures/blocks/clinker_brick/clinker_brick_texture7.png differ
diff --git a/src/main/resources/assets/engineersdecor/textures/blocks/concrete/rebar_concrete_texture0.png b/src/main/resources/assets/engineersdecor/textures/blocks/concrete/rebar_concrete_texture0.png
new file mode 100644
index 0000000..c0157c1
Binary files /dev/null and b/src/main/resources/assets/engineersdecor/textures/blocks/concrete/rebar_concrete_texture0.png differ
diff --git a/src/main/resources/assets/engineersdecor/textures/blocks/concrete/rebar_concrete_texture1.png b/src/main/resources/assets/engineersdecor/textures/blocks/concrete/rebar_concrete_texture1.png
new file mode 100644
index 0000000..5645eab
Binary files /dev/null and b/src/main/resources/assets/engineersdecor/textures/blocks/concrete/rebar_concrete_texture1.png differ
diff --git a/src/main/resources/assets/engineersdecor/textures/blocks/concrete/rebar_concrete_texture2.png b/src/main/resources/assets/engineersdecor/textures/blocks/concrete/rebar_concrete_texture2.png
new file mode 100644
index 0000000..f1a97db
Binary files /dev/null and b/src/main/resources/assets/engineersdecor/textures/blocks/concrete/rebar_concrete_texture2.png differ
diff --git a/src/main/resources/assets/engineersdecor/textures/blocks/concrete/rebar_concrete_texture3.png b/src/main/resources/assets/engineersdecor/textures/blocks/concrete/rebar_concrete_texture3.png
new file mode 100644
index 0000000..6e39b40
Binary files /dev/null and b/src/main/resources/assets/engineersdecor/textures/blocks/concrete/rebar_concrete_texture3.png differ
diff --git a/src/main/resources/assets/engineersdecor/textures/blocks/concrete/rebar_concrete_texture4.png b/src/main/resources/assets/engineersdecor/textures/blocks/concrete/rebar_concrete_texture4.png
new file mode 100644
index 0000000..8773119
Binary files /dev/null and b/src/main/resources/assets/engineersdecor/textures/blocks/concrete/rebar_concrete_texture4.png differ
diff --git a/src/main/resources/assets/engineersdecor/textures/blocks/concrete/rebar_concrete_texture5.png b/src/main/resources/assets/engineersdecor/textures/blocks/concrete/rebar_concrete_texture5.png
new file mode 100644
index 0000000..c9aab19
Binary files /dev/null and b/src/main/resources/assets/engineersdecor/textures/blocks/concrete/rebar_concrete_texture5.png differ
diff --git a/src/main/resources/assets/engineersdecor/textures/blocks/concrete/rebar_concrete_texture6.png b/src/main/resources/assets/engineersdecor/textures/blocks/concrete/rebar_concrete_texture6.png
new file mode 100644
index 0000000..99e6367
Binary files /dev/null and b/src/main/resources/assets/engineersdecor/textures/blocks/concrete/rebar_concrete_texture6.png differ
diff --git a/src/main/resources/assets/engineersdecor/textures/blocks/concrete/rebar_concrete_texture7.png b/src/main/resources/assets/engineersdecor/textures/blocks/concrete/rebar_concrete_texture7.png
new file mode 100644
index 0000000..8ee5d60
Binary files /dev/null and b/src/main/resources/assets/engineersdecor/textures/blocks/concrete/rebar_concrete_texture7.png differ
diff --git a/src/main/resources/assets/engineersdecor/textures/blocks/iestyle/ironsheet_roof.png b/src/main/resources/assets/engineersdecor/textures/blocks/iestyle/ironsheet_roof.png
new file mode 100644
index 0000000..23dff87
Binary files /dev/null and b/src/main/resources/assets/engineersdecor/textures/blocks/iestyle/ironsheet_roof.png differ
diff --git a/src/main/resources/assets/engineersdecor/textures/blocks/iestyle/ironsheet_roof_top.png b/src/main/resources/assets/engineersdecor/textures/blocks/iestyle/ironsheet_roof_top.png
new file mode 100644
index 0000000..a5f0382
Binary files /dev/null and b/src/main/resources/assets/engineersdecor/textures/blocks/iestyle/ironsheet_roof_top.png differ
diff --git a/src/main/resources/assets/engineersdecor/textures/blocks/iestyle/steel_texture.png b/src/main/resources/assets/engineersdecor/textures/blocks/iestyle/steel_texture.png
new file mode 100644
index 0000000..9584364
Binary files /dev/null and b/src/main/resources/assets/engineersdecor/textures/blocks/iestyle/steel_texture.png differ
diff --git a/src/main/resources/assets/engineersdecor/textures/blocks/iestyle/treated_wood.png b/src/main/resources/assets/engineersdecor/textures/blocks/iestyle/treated_wood.png
new file mode 100644
index 0000000..a1d0537
Binary files /dev/null and b/src/main/resources/assets/engineersdecor/textures/blocks/iestyle/treated_wood.png differ
diff --git a/src/main/resources/assets/engineersdecor/textures/blocks/iestyle/treated_wood_framed_nailed_texture.png b/src/main/resources/assets/engineersdecor/textures/blocks/iestyle/treated_wood_framed_nailed_texture.png
new file mode 100644
index 0000000..6c7a9c6
Binary files /dev/null and b/src/main/resources/assets/engineersdecor/textures/blocks/iestyle/treated_wood_framed_nailed_texture.png differ
diff --git a/src/main/resources/assets/engineersdecor/textures/blocks/iestyle/treated_wood_framed_texture.png b/src/main/resources/assets/engineersdecor/textures/blocks/iestyle/treated_wood_framed_texture.png
new file mode 100644
index 0000000..3ce7527
Binary files /dev/null and b/src/main/resources/assets/engineersdecor/textures/blocks/iestyle/treated_wood_framed_texture.png differ
diff --git a/src/main/resources/assets/engineersdecor/textures/blocks/iestyle/treated_wood_pole_texture.png b/src/main/resources/assets/engineersdecor/textures/blocks/iestyle/treated_wood_pole_texture.png
new file mode 100644
index 0000000..8c50fc8
Binary files /dev/null and b/src/main/resources/assets/engineersdecor/textures/blocks/iestyle/treated_wood_pole_texture.png differ
diff --git a/src/main/resources/assets/engineersdecor/textures/blocks/iestyle/treated_wood_rough_texture.png b/src/main/resources/assets/engineersdecor/textures/blocks/iestyle/treated_wood_rough_texture.png
new file mode 100644
index 0000000..fccfc82
Binary files /dev/null and b/src/main/resources/assets/engineersdecor/textures/blocks/iestyle/treated_wood_rough_texture.png differ
diff --git a/src/main/resources/assets/engineersdecor/textures/blocks/pole/treated_wood_pole_side_texture.png b/src/main/resources/assets/engineersdecor/textures/blocks/pole/treated_wood_pole_side_texture.png
new file mode 100644
index 0000000..533f852
Binary files /dev/null and b/src/main/resources/assets/engineersdecor/textures/blocks/pole/treated_wood_pole_side_texture.png differ
diff --git a/src/main/resources/assets/engineersdecor/textures/blocks/pole/treated_wood_pole_top_texture.png b/src/main/resources/assets/engineersdecor/textures/blocks/pole/treated_wood_pole_top_texture.png
new file mode 100644
index 0000000..4605187
Binary files /dev/null and b/src/main/resources/assets/engineersdecor/textures/blocks/pole/treated_wood_pole_top_texture.png differ
diff --git a/src/main/resources/assets/engineersdecor/textures/blocks/slag_brick/slag_brick_texture0.png b/src/main/resources/assets/engineersdecor/textures/blocks/slag_brick/slag_brick_texture0.png
new file mode 100644
index 0000000..8378625
Binary files /dev/null and b/src/main/resources/assets/engineersdecor/textures/blocks/slag_brick/slag_brick_texture0.png differ
diff --git a/src/main/resources/assets/engineersdecor/textures/blocks/slag_brick/slag_brick_texture1.png b/src/main/resources/assets/engineersdecor/textures/blocks/slag_brick/slag_brick_texture1.png
new file mode 100644
index 0000000..1e56869
Binary files /dev/null and b/src/main/resources/assets/engineersdecor/textures/blocks/slag_brick/slag_brick_texture1.png differ
diff --git a/src/main/resources/assets/engineersdecor/textures/blocks/slag_brick/slag_brick_texture2.png b/src/main/resources/assets/engineersdecor/textures/blocks/slag_brick/slag_brick_texture2.png
new file mode 100644
index 0000000..8832f88
Binary files /dev/null and b/src/main/resources/assets/engineersdecor/textures/blocks/slag_brick/slag_brick_texture2.png differ
diff --git a/src/main/resources/assets/engineersdecor/textures/blocks/slag_brick/slag_brick_texture3.png b/src/main/resources/assets/engineersdecor/textures/blocks/slag_brick/slag_brick_texture3.png
new file mode 100644
index 0000000..d1edf88
Binary files /dev/null and b/src/main/resources/assets/engineersdecor/textures/blocks/slag_brick/slag_brick_texture3.png differ
diff --git a/src/main/resources/assets/engineersdecor/textures/blocks/slag_brick/slag_brick_texture4.png b/src/main/resources/assets/engineersdecor/textures/blocks/slag_brick/slag_brick_texture4.png
new file mode 100644
index 0000000..dea4b97
Binary files /dev/null and b/src/main/resources/assets/engineersdecor/textures/blocks/slag_brick/slag_brick_texture4.png differ
diff --git a/src/main/resources/assets/engineersdecor/textures/blocks/slag_brick/slag_brick_texture5.png b/src/main/resources/assets/engineersdecor/textures/blocks/slag_brick/slag_brick_texture5.png
new file mode 100644
index 0000000..baa5672
Binary files /dev/null and b/src/main/resources/assets/engineersdecor/textures/blocks/slag_brick/slag_brick_texture5.png differ
diff --git a/src/main/resources/assets/engineersdecor/textures/blocks/slag_brick/slag_brick_texture6.png b/src/main/resources/assets/engineersdecor/textures/blocks/slag_brick/slag_brick_texture6.png
new file mode 100644
index 0000000..6895552
Binary files /dev/null and b/src/main/resources/assets/engineersdecor/textures/blocks/slag_brick/slag_brick_texture6.png differ
diff --git a/src/main/resources/assets/engineersdecor/textures/blocks/slag_brick/slag_brick_texture7.png b/src/main/resources/assets/engineersdecor/textures/blocks/slag_brick/slag_brick_texture7.png
new file mode 100644
index 0000000..966aee4
Binary files /dev/null and b/src/main/resources/assets/engineersdecor/textures/blocks/slag_brick/slag_brick_texture7.png differ
diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info
new file mode 100644
index 0000000..d3a4be4
--- /dev/null
+++ b/src/main/resources/mcmod.info
@@ -0,0 +1,16 @@
+[
+    {
+      "modid": "engineersdecor",
+      "name": "Engineer's Decor",
+      "description": "Adds cosmetic blocks for the engineer's workshop, factory and home.",
+      "version": "${version}",
+      "mcversion": "${mcversion}",
+      "url": "https://github.com/stfwi/engineers-decor/",
+      "authorList": ["wile"],
+      "credits": "BluSunrize, malte0811, et al., the Forge Smiths, the Modders of the World.",
+      "logoFile": "assets/engineersdecor/logo.png",
+      "screenshots": [],
+      "useDependencyInformation": false,
+      "dependencies": ["Forge"]
+    }
+]
diff --git a/src/main/resources/pack.mcmeta b/src/main/resources/pack.mcmeta
new file mode 100644
index 0000000..73a4b04
--- /dev/null
+++ b/src/main/resources/pack.mcmeta
@@ -0,0 +1,7 @@
+{
+  "pack": {
+    "description": "engineersdecor resources",
+    "pack_format": 3,
+    "_comment": "A pack_format of 3 should be used starting with Minecraft 1.11. All resources, including language files, should be lowercase (eg: en_us.lang). A pack_format of 2 will load your mod resources with LegacyV2Adapter, which requires language files to have uppercase letters (eg: en_US.lang)."
+  }
+}